@@ -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_ | SCRAPE_INTERVAL_ | ||
@@ -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_re | + 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_re | |||
+ "linux-x64-test-results" "${BUILD_DIR}"/test-results.*.xml | |||
+ fi | |||
} | } | ||
trap at-exit EXIT | trap at-exit EXIT | ||
@@ -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_re | + 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_re | |||
+ "windows-x64-test-results" "${BUILD_DIR}"/test-results.*.xml | |||
+ fi | |||
} | } | ||
trap at-exit EXIT | trap at-exit EXIT | ||
@@ -94,3 +94,9 @@ b6262880b34629e9 | |||
39c7dc7207e76e72 | 39c7dc7207e76e72 | ||
e80bc777749331e9 | e80bc777749331e9 | ||
7e5cd8f1b6c5263e | 7e5cd8f1b6c5263e | ||
+ | |||
+# NFC: clang-format test_demangle.pass.cpp but keep test "lines" | |||
+d33bf2e9df578ff7 | |||
+ | |||
+# [lldb][NFC] clang-format MainLoopPosix.cpp | |||
+66bdbfbaa08fa3d8 |
@@ -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 |
@@ -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/** |
@@ -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 | + 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: |
@@ -41,13 +41,13 @@ RUN ninja -C ./build stage2-clang-bol | |||
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 | |||
+ |
@@ -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 |
@@ -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 | |||
+ 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_project | |||
+ | |||
+ linux_projects_t | |||
+ linux_check_targ | |||
+ linux_projects=$(add-dependencies ${linux_projects_t | |||
+ | |||
+ linux_runtimes_t | |||
+ linux_runtime_ch | |||
+ linux_runtimes=$(echo ${linux_runtimes_t | |||
+ | |||
+ if [[ "${linux_projects}" == "" ]]; then | |||
+ echo "No projects to build" | |||
+ exit 0 | |||
+ fi | |||
+ | |||
+ echo "Building projects: ${linux_projects}" | |||
+ echo "Running project checks targets: ${linux_check_targ | |||
+ echo "Building runtimes: ${linux_runtimes}" | |||
+ echo "Running runtimes checks targets: ${linux_runtime_ch | |||
+ | |||
+ export CC=/opt/llvm/bin/clang | |||
+ export CXX=/opt/llvm/bin/clang++ | |||
+ | |||
+ ./.ci/monolithic-linux.sh "$(echo ${linux_projects} | tr ' ' ';')" "$(echo ${linux_check_targ |
@@ -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=<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` | ||
@@ -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 | unsigned getIndex(const BinaryBasicBlock | ||
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 setHasAddressTak | |||
+ | |||
/// 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 handleAArch64Ind | void handleAArch64Ind | ||
+ /// Analyze instruction to identify a function reference. | |||
+ void analyzeInstructi | |||
+ | |||
/// 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. |
@@ -25,7 +25,8 @@ namespace bolt { | |||
class ADRRelaxationPas | class ADRRelaxationPas | ||
public: | public: | ||
- explicit ADRRelaxationPass( | + explicit ADRRelaxationPass(const cl::opt<bool> &PrintPass) | ||
+ : BinaryFunctionPa | |||
const char *getName() const override { return "adr-relaxation"; } | const char *getName() const override { return "adr-relaxation"; } | ||
@@ -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 IdenticalCodeFol | class IdenticalCodeFol | ||
protected: | protected: | ||
- bool shouldOptimize(const BinaryFunction &BF) const override { | + /// Return true if the function is safe to fold. | ||
- if (BF.hasUnknownContro | + bool shouldOptimize(const BinaryFunction &BF) const override; | ||
- return false; | |||
- if (BF.isFolded()) | |||
- return false; | |||
- if (BF.hasSDTMarker()) | |||
- return false; | |||
- return BinaryFunctionPa | |||
- } | |||
public: | public: | ||
+ enum class ICFLevel { | |||
+ None, /// No ICF. (Default) | |||
+ Safe, /// Safe ICF. | |||
+ All, /// Aggressive ICF. | |||
+ }; | |||
explicit IdenticalCodeFol | explicit IdenticalCodeFol | ||
: BinaryFunctionPa | : BinaryFunctionPa | ||
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 isAddressInVTabl | |||
+ return VTableBitVector.test(Address / 8); | |||
+ } | |||
+ | |||
+ /// Mark memory address of a vtable as used. | |||
+ void setAddressUsedIn | |||
+ VTableBitVector.set(Address / 8); | |||
+ } | |||
+ | |||
+ /// Scan symbol table and mark memory addresses of | |||
+ /// vtables. | |||
+ void initVTableRefere | |||
+ | |||
+ /// Analyze code section and relocations and mark functions that are not | |||
+ /// safe to fold. | |||
+ void markFunctionsUns | |||
+ | |||
+ /// 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 analyzeDataReloc | |||
+ | |||
+ /// Process functions that have been disassembled and mark functions that are | |||
+ /// used in non-control flow instructions as unsafe to fold. | |||
+ void analyzeFunctions | |||
+}; | |||
+ | |||
+class DeprecatedICFNum | |||
+ : public cl::parser<IdenticalCodeFol | |||
+public: | |||
+ explicit DeprecatedICFNum | |||
+ : cl::parser<IdenticalCodeFol | |||
+ | |||
+ bool parse(cl::Option &O, StringRef ArgName, StringRef Arg, | |||
+ IdenticalCodeFol | |||
+ if (Arg == "0" || Arg == "1") { | |||
+ Value = (Arg == "0") ? IdenticalCodeFol | |||
+ : IdenticalCodeFol | |||
+ errs() << formatv("BOLT-WARNING: specifying numeric value \"{0}\" " | |||
+ "for option -{1} is deprecated\n", | |||
+ Arg, ArgName); | |||
+ return false; | |||
+ } | |||
+ return cl::parser<IdenticalCodeFol | |||
+ Value); | |||
+ } | |||
}; | }; | ||
} // namespace bolt | } // namespace bolt |
@@ -1504,6 +1504,20 @@ MCSymbol *BinaryFunction: | |||
return Target; | return Target; | ||
} | } | ||
+void BinaryFunction::analyzeInstructi | |||
+ 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.getFunctionForSy | |||
+ BF->setHasAddressTak | |||
+ } | |||
+} | |||
+ | |||
bool BinaryFunction::scanExternalRefs | bool BinaryFunction::scanExternalRefs | ||
bool Success = true; | bool Success = true; | ||
bool DisassemblyFaile | bool DisassemblyFaile | ||
@@ -1624,6 +1638,8 @@ bool BinaryFunction:: | |||
[](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 { | |||
+ analyzeInstructi | |||
} | } | ||
// Emit the instruction using temp emitter and generate relocations. | // Emit the instruction using temp emitter and generate relocations. |
@@ -15,6 +15,7 @@ | |||
#include "bolt/Core/ParallelUtilitie | #include "bolt/Core/ParallelUtilitie | ||
#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-ic | |||
cl::ReallyHidden, | cl::ReallyHidden, | ||
cl::ZeroOrMore, | cl::ZeroOrMore, | ||
cl::cat(BoltOptCategory)); | cl::cat(BoltOptCategory)); | ||
+ | |||
+cl::opt<bolt::IdenticalCodeFol | |||
+ DeprecatedICFNum | |||
+ ICF("icf", cl::desc("fold functions with identical code"), | |||
+ cl::init(bolt::IdenticalCodeFol | |||
+ cl::values(clEnumValN(bolt::IdenticalCodeFol | |||
+ "Enable identical code folding"), | |||
+ clEnumValN(bolt::IdenticalCodeFol | |||
+ "Enable identical code folding"), | |||
+ clEnumValN(bolt::IdenticalCodeFol | |||
+ "Enable identical code folding"), | |||
+ clEnumValN(bolt::IdenticalCodeFol | |||
+ "none", | |||
+ "Disable identical code folding (default)"), | |||
+ clEnumValN(bolt::IdenticalCodeFol | |||
+ "Disable identical code folding (default)"), | |||
+ clEnumValN(bolt::IdenticalCodeFol | |||
+ "safe", "Enable safe identical code folding")), | |||
+ cl::ZeroOrMore, cl::ValueOptional, cl::cat(BoltOptCategory)); | |||
} // namespace opts | } // namespace opts | ||
+bool IdenticalCodeFol | |||
+ if (BF.hasUnknownContro | |||
+ 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 BinaryFunctionPa | |||
+} | |||
+ | |||
/// 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_m | |||
namespace llvm { | namespace llvm { | ||
namespace bolt { | namespace bolt { | ||
+void IdenticalCodeFol | |||
+ 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) | |||
+ setAddressUsedIn | |||
+ } | |||
+} | |||
+ | |||
+void IdenticalCodeFol | |||
+ initVTableRefere | |||
+ // 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 (isAddressInVTabl | |||
+ continue; | |||
+ if (BinaryFunction *BF = BC.getFunctionForSy | |||
+ BF->setHasAddressTak | |||
+ } | |||
+ // 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.dynamicRelocatio | |||
+ const uint64_t RelAddr = Rel.Offset + Sec.getAddress(); | |||
+ if (isAddressInVTabl | |||
+ continue; | |||
+ if (BinaryFunction *BF = BC.getBinaryFunctio | |||
+ BF->setHasAddressTak | |||
+ } | |||
+ } | |||
+} | |||
+ | |||
+void IdenticalCodeFol | |||
+ ParallelUtilitie | |||
+ for (const BinaryBasicBlock | |||
+ for (const MCInst &Inst : BB) | |||
+ if (!(BC.MIB->isCall(Inst) || BC.MIB->isBranch(Inst))) | |||
+ BF.analyzeInstructi | |||
+ }; | |||
+ ParallelUtilitie | |||
+ [&](const BinaryFunction &BF) -> bool { return !BF.hasCFG(); }; | |||
+ ParallelUtilitie | |||
+ BC, ParallelUtilitie | |||
+ SkipFunc, "markUnsafe"); | |||
+ | |||
+ LLVM_DEBUG({ | |||
+ for (const auto &BFIter : BC.getBinaryFunctio | |||
+ if (!BFIter.second.hasAddressTaken()) | |||
+ continue; | |||
+ dbgs() << "BOLT-DEBUG: skipping function with reference taken " | |||
+ << BFIter.second.getOneName() << '\n'; | |||
+ } | |||
+ }); | |||
+} | |||
+ | |||
+void IdenticalCodeFol | |||
+ NamedRegionTimer | |||
+ "markFunctionsUns | |||
+ "ICF breakdown", opts::TimeICF); | |||
+ if (!BC.isX86()) | |||
+ BC.outs() << "BOLT-WARNING: safe ICF is only supported for x86\n"; | |||
+ analyzeDataReloc | |||
+ analyzeFunctions | |||
+} | |||
Error IdenticalCodeFol | Error IdenticalCodeFol | ||
const size_t OriginalFunction | const size_t OriginalFunction | ||
@@ -385,7 +487,7 @@ Error IdenticalCodeFol | |||
"ICF breakdown", opts::TimeICF); | "ICF breakdown", opts::TimeICF); | ||
for (auto &BFI : BC.getBinaryFunctio | for (auto &BFI : BC.getBinaryFunctio | ||
BinaryFunction &BF = BFI.second; | BinaryFunction &BF = BFI.second; | ||
- if ( | + if (!shouldOptimize(BF)) | ||
continue; | continue; | ||
CongruentBuckets | CongruentBuckets | ||
} | } | ||
@@ -475,7 +577,8 @@ Error IdenticalCodeFol | |||
LLVM_DEBUG(SinglePass.stopTimer()); | LLVM_DEBUG(SinglePass.stopTimer()); | ||
}; | }; | ||
- | + if (opts::ICF == ICFLevel::Safe) | ||
+ markFunctionsUns | |||
hashFunctions(); | hashFunctions(); | ||
createCongruentB | createCongruentB | ||
@@ -138,9 +138,9 @@ BinaryBasicBlock | |||
const std::pair<uint64_t, BinaryBasicBlock | const std::pair<uint64_t, BinaryBasicBlock | ||
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; |
@@ -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::IdenticalCodeFol | |||
+ llvm::bolt::DeprecatedICFNum | |||
+ 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> JTFootprintReduc | static cl::opt<bool> JTFootprintReduc | ||
"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> PrintJTFootprint | |||
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> | |||
+ PrintAdrRelaxati | |||
+ 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 BinaryFunctionPa | |||
opts::StripRepRet); | opts::StripRepRet); | ||
Manager.registerPass(std::make_unique<IdenticalCodeFol | Manager.registerPass(std::make_unique<IdenticalCodeFol | ||
- opts::ICF); | + opts::ICF != IdenticalCodeFolding::ICFLevel::None); | ||
Manager.registerPass( | Manager.registerPass( | ||
std::make_unique<SpecializeMemcpy | std::make_unique<SpecializeMemcpy | ||
@@ -423,7 +428,7 @@ Error BinaryFunctionPa | |||
Manager.registerPass(std::make_unique<Inliner>(PrintInline)); | Manager.registerPass(std::make_unique<Inliner>(PrintInline)); | ||
Manager.registerPass(std::make_unique<IdenticalCodeFol | Manager.registerPass(std::make_unique<IdenticalCodeFol | ||
- 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 BinaryFunctionPa | |||
Manager.registerPass(std::make_unique<ReorderData>()); | Manager.registerPass(std::make_unique<ReorderData>()); | ||
if (BC.isAArch64()) { | if (BC.isAArch64()) { | ||
- Manager.registerPass( | + Manager.registerPass( | ||
+ std::make_unique<ADRRelaxationPas | |||
// 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 |
@@ -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 | +extern cl::opt<bolt::IdenticalCodeFolding::ICFLevel, false, | ||
+ llvm::bolt::DeprecatedICFNum | |||
+ ICF; | |||
static cl::opt<bool> IgnoreLTOSuffix( | static cl::opt<bool> IgnoreLTOSuffix( | ||
"ignore-lto-suffix", | "ignore-lto-suffix", | ||
@@ -697,7 +699,7 @@ void RewriteInstance: | |||
} | } | ||
// Pre-pass ICF | // Pre-pass ICF | ||
- if (opts::ICF) { | + if (opts::ICF != IdenticalCodeFolding::ICFLevel::None) { | ||
IdenticalCodeFol | IdenticalCodeFol | ||
outs() << "BOLT-DIFF: Starting ICF pass for binary 1"; | outs() << "BOLT-DIFF: Starting ICF pass for binary 1"; | ||
BC->logBOLTErrorsAnd | BC->logBOLTErrorsAnd |
@@ -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/IdenticalCodeFol | |||
#include "bolt/Passes/ReorderFunctions | #include "bolt/Passes/ReorderFunctions | ||
#include "bolt/Profile/BoltAddressTrans | #include "bolt/Profile/BoltAddressTrans | ||
#include "bolt/Profile/DataAggregator.h" | #include "bolt/Profile/DataAggregator.h" | ||
@@ -85,6 +86,9 @@ extern cl::opt<bolt::Re | |||
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::IdenticalCodeFol | |||
+ llvm::bolt::DeprecatedICFNum | |||
+ 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: | |||
exit(1); | exit(1); | ||
} | } | ||
+ if (!BC->HasRelocations && | |||
+ opts::ICF == IdenticalCodeFol | |||
+ BC->errs() << "BOLT-ERROR: binary built without relocations. Safe ICF is " | |||
+ "not supported\n"; | |||
+ exit(1); | |||
+ } | |||
+ | |||
if (opts::Instrument || | if (opts::Instrument || | ||
(opts::ReorderFunctions | (opts::ReorderFunctions | ||
!opts::HotText.getNumOccurrence | !opts::HotText.getNumOccurrence |
@@ -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 |
@@ -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 0x551db97d5e23dc | .file 0 "gnu_tls_push" "main.cpp" md5 0x551db97d5e23dc | ||
- .globl main | + .globl main | ||
- .p2align 4, 0x90 | |||
.type main,@function | .type main,@function | ||
-main: # @main | +main: | ||
.Lfunc_begin0: | .Lfunc_begin0: | ||
- .loc 0 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_offs | + .loc 0 4 3 epilogue_begin is_stmt 0 | ||
- .cfi_offset %rbp, -16 | |||
- movq %rsp, %rbp | |||
- .cfi_def_cfa_regi | |||
- 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, | |||
- .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_offs | |||
- .cfi_offset %rbp, -16 | |||
- movq %rsp, %rbp | |||
- .cfi_def_cfa_regi | |||
- 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 |
@@ -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 Derived3Destruct | |||
+# ICFCHECK-NEXT: folding Derived3Func into Derived2Func | |||
+ | |||
+# SAFEICFCHECK: skipping function with reference taken Derived3Func | |||
+# SAFEICFCHECK-NEXT: ICF iteration 1 | |||
+# SAFEICFCHECK-NEXT: folding Derived3Destruct | |||
+# 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 main(int argc, char **argv) { | |||
+## int sum = 0; | |||
+## int a = returnFourOrFive | |||
+## 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 fooGlobalFuncHel | |||
+## 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 Derived2Destruct | |||
+ .type Derived2Destruct | |||
+Derived2Destruct | |||
+ jmp _ZdlPvm@PLT | |||
+ .size Derived2Destruct | |||
+ | |||
+ .weak Derived3Func | |||
+ .type Derived3Func,@function | |||
+Derived3Func: | |||
+ imull %esi, %eax | |||
+ retq | |||
+ .size Derived3Func, .-Derived3Func | |||
+ | |||
+ .weak _ZN4BaseD2Ev | |||
+ .type _ZN4BaseD2Ev,@function | |||
+_ZN4BaseD2Ev: | |||
+ retq | |||
+ .size _ZN4BaseD2Ev, .-_ZN4BaseD2Ev | |||
+ | |||
+ .weak Derived3Destruct | |||
+ .type Derived3Destruct | |||
+Derived3Destruct | |||
+ jmp _ZdlPvm@PLT | |||
+ .size Derived3Destruct | |||
+ | |||
+ .type _ZTV8Derived2,@object | |||
+ .section .data.rel.ro._ZTV8Derived2,"awG",@progbits,_ZTV8De | |||
+ .weak _ZTV8Derived2 | |||
+_ZTV8Derived2: | |||
+ .quad 0 | |||
+ .quad _ZTI8Derived2 | |||
+ .quad Derived2Func | |||
+ .quad _ZN4BaseD2Ev | |||
+ .quad Derived2Destruct | |||
+ .size _ZTV8Derived2, 40 | |||
+ | |||
+ .type _ZTV8Derived3,@object | |||
+ .section .data.rel.ro._ZTV8Derived3,"awG",@progbits,_ZTV8De | |||
+ .weak _ZTV8Derived3 | |||
+_ZTV8Derived3: | |||
+ .quad 0 | |||
+ .quad _ZTI8Derived3 | |||
+ .quad Derived3Func | |||
+ .quad _ZN4BaseD2Ev | |||
+ .quad Derived3Destruct | |||
+ .size _ZTV8Derived3, 40 |
@@ -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 | |||
+## const int (* const funcGlobalBarMul | |||
+## helper2(funcGlobalBarAdd | |||
+## } | |||
+## 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 localStaticVarBa | |||
+ movq localStaticVarFo | |||
+ callq helperFunc | |||
+ retq | |||
+ .size main, .-main | |||
+ | |||
+ .type localStaticVarBa | |||
+ .data | |||
+localStaticVarBa | |||
+ .quad barAddFunc | |||
+ .size localStaticVarBa | |||
+ | |||
+ .type localStaticVarFo | |||
+localStaticVarFo | |||
+ .quad fooAddFunc | |||
+ .size localStaticVarFo |
@@ -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 |
@@ -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 | |||
+ | |||
+# 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: ===--------- | |||
+ | |||
+# SAFEICFCHECKNOCF | |||
+# SAFEICFCHECKNOCF | |||
+# SAFEICFCHECKNOCF | |||
+# SAFEICFCHECKNOCF | |||
+ | |||
+## 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 |
@@ -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 | |||
+## const int (*const funcGlobalBarMul | |||
+## int main(int argc, char **argv) { | |||
+## int temp = helper1(funcGlobalBarAdd | |||
+## 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 |
@@ -35,13 +35,13 @@ _start: | |||
.L0: | .L0: | ||
jmp L1 | jmp L1 | ||
# CHECK: jit | # CHECK: jit | ||
-# CHECK-SAME: # ID: 1 {{.*}} # Likely: | +# 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: | +# 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_t | .type __start___jump_t | ||
__start___jump_t | __start___jump_t | ||
- .long .L0 - . | + .long .L0 - . # Jump address | ||
- .long L1 - . | + .long L1 - . # Target address | ||
- .quad 1 # Key address | + .quad fake_static_key + 1 - . # Key address; LSB = 1 : likely | ||
- .long L1 - . | + .long L1 - . # Jump address | ||
- .long L2 - . | + .long L2 - . # Target address | ||
- .quad 0 # Key address | + .quad fake_static_key -. # Key address; LSB = 0 : unlikely | ||
.globl __stop___jump_ta | .globl __stop___jump_ta | ||
.type __stop___jump_ta | .type __stop___jump_ta | ||
__stop___jump_ta | __stop___jump_ta | ||
+## 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 |
@@ -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 |
@@ -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 | +# CHECK: cannot mix profile with and without boltedcollection | ||
#--- a.fdata | #--- a.fdata | ||
boltedcollection | boltedcollection |
@@ -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 | +# CHECK: cannot mix profile with and without no_lbr | ||
#--- a.fdata | #--- a.fdata | ||
no_lbr | no_lbr |
@@ -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 mergeLegacyProfi | |||
std::optional<bool> BoltedCollection | std::optional<bool> BoltedCollection | ||
std::optional<bool> NoLBRCollection; | std::optional<bool> NoLBRCollection; | ||
std::mutex BoltedCollection | std::mutex BoltedCollection | ||
- 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(BoltedCollection | std::lock_guard<std::mutex> Lock(BoltedCollection | ||
// Check if the string "boltedcollection | // Check if the string "boltedcollection | ||
- if (Buf.starts_with("boltedcollection | + checkMode("boltedcollection | ||
- if (!BoltedCollection | |||
- report_error( | |||
- Filename, | |||
- "cannot mix profile collected in BOLT and non-BOLT deployments"); | |||
- BoltedCollection | |||
- Buf = Buf.drop_front(17); | |||
- } else { | |||
- if (BoltedCollection | |||
- report_error( | |||
- Filename, | |||
- "cannot mix profile collected in BOLT and non-BOLT deployments"); | |||
- BoltedCollection | |||
- } | |||
// 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 | // (or second line if BoltedCollection | ||
- 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 | + 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 | Profile->insert_or_assign | ||
- } | + } 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 mergeLegacyProfi | |||
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) { | ||
- | + CounterTy Count = MergedProfile.lookup(Key) + Value; | ||
MergedProfile.insert_or_assign | MergedProfile.insert_or_assign | ||
} | } | ||
@@ -354,8 +354,12 @@ void mergeLegacyProfi | |||
output() << "boltedcollection | output() << "boltedcollection | ||
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 << " | + 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"; | ||
} | } |
@@ -236,10 +236,10 @@ static RecordDecl *getRecordDeclFo | |||
return nullptr; | return nullptr; | ||
} | } | ||
-TypeInfo getTypeInfoForType(const QualType &T) { | +TypeInfo getTypeInfoForType(const QualType &T, const PrintingPolicy &Policy) { | ||
const TagDecl *TD = getTagDeclForTyp | const TagDecl *TD = getTagDeclForTyp | ||
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 getTypeInfoForTy | |||
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(Reco | |||
if (!shouldSerializeI | if (!shouldSerializeI | ||
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(), | ||
getFinalAccessSp | getFinalAccessSp | ||
populateMemberTy | populateMemberTy | ||
@@ -412,9 +413,10 @@ static void parseEnumerators | |||
} | } | ||
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->getDefaultArgRan | FieldInfo.DefaultValue = getSourceCode(D, P->getDefaultArgRan | ||
} | } | ||
} | } | ||
@@ -541,7 +543,8 @@ static void populateFunction | |||
bool &IsInAnonymousNam | bool &IsInAnonymousNam | ||
populateSymbolIn | populateSymbolIn | ||
IsInAnonymousNam | IsInAnonymousNam | ||
- I.ReturnType = getTypeInfoForTy | + auto &LO = D->getLangOpts(); | ||
+ I.ReturnType = getTypeInfoForTy | |||
parseParameters(I, D); | parseParameters(I, D); | ||
PopulateTemplate | PopulateTemplate | ||
@@ -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 = getTypeInfoForTy | + auto &LO = D->getLangOpts(); | ||
+ Info.Underlying = getTypeInfoForTy | |||
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 = getTypeInfoForTy | + auto &LO = D->getLangOpts(); | ||
+ Info.Underlying = getTypeInfoForTy | |||
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. |
@@ -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/UncheckedOptiona | #include "clang/Analysis/FlowSensitive/Models/UncheckedOptiona | ||
-#include <optional> | |||
namespace clang::tidy::bugprone { | namespace clang::tidy::bugprone { | ||
@@ -26,8 +25,7 @@ class UncheckedOptiona | |||
public: | public: | ||
UncheckedOptiona | UncheckedOptiona | ||
: ClangTidyCheck(Name, Context), | : ClangTidyCheck(Name, Context), | ||
- ModelOptions{ | + ModelOptions{Options.get("IgnoreSmartPointerDereference", false)} {} | ||
- Options.getLocalOrGlobal | |||
void registerMatchers | void registerMatchers | ||
void check(const ast_matchers::MatchFinder::MatchResult &Result) override; | void check(const ast_matchers::MatchFinder::MatchResult &Result) override; | ||
bool isLanguageVersio | bool isLanguageVersio |
@@ -277,7 +277,7 @@ ProTypeMemberIni | |||
ClangTidyContext | ClangTidyContext | ||
: ClangTidyCheck(Name, Context), | : ClangTidyCheck(Name, Context), | ||
IgnoreArrays(Options.get("IgnoreArrays", false)), | IgnoreArrays(Options.get("IgnoreArrays", false)), | ||
- UseAssignment(Options. | + UseAssignment(Options.get("UseAssignment", false)) {} | ||
void ProTypeMemberIni | void ProTypeMemberIni | ||
auto IsUserProvidedNo | auto IsUserProvidedNo |
@@ -119,11 +119,10 @@ void RvalueReferenceP | |||
RvalueReferenceP | RvalueReferenceP | ||
StringRef Name, ClangTidyContext | StringRef Name, ClangTidyContext | ||
: ClangTidyCheck(Name, Context), | : ClangTidyCheck(Name, Context), | ||
- AllowPartialMove(Options. | + AllowPartialMove(Options.get("AllowPartialMove", false)), | ||
- IgnoreUnnamedParams( | + IgnoreUnnamedParams(Options.get("IgnoreUnnamedParams", false)), | ||
- Options.getLocalOrGlobal | |||
IgnoreNonDeduced | IgnoreNonDeduced | ||
- Options. | + Options.get("IgnoreNonDeducedTemplateTypes", false)) {} | ||
void RvalueReferenceP | void RvalueReferenceP | ||
ClangTidyOptions | ClangTidyOptions |
@@ -57,10 +57,9 @@ struct MissingIncludeIn | |||
IncludeCleanerCh | IncludeCleanerCh | ||
ClangTidyContext | ClangTidyContext | ||
: ClangTidyCheck(Name, Context), | : ClangTidyCheck(Name, Context), | ||
- IgnoreHeaders( | + IgnoreHeaders( | ||
- Options. | + utils::options::parseStringList(Options.get("IgnoreHeaders", ""))), | ||
- DeduplicateFindings( | + DeduplicateFindings(Options.get("DeduplicateFindings", true)) { | ||
- Options.getLocalOrGlobal | |||
for (const auto &Header : IgnoreHeaders) { | for (const auto &Header : IgnoreHeaders) { | ||
if (!llvm::Regex{Header}.isValid()) | if (!llvm::Regex{Header}.isValid()) | ||
configurationDia | configurationDia |
@@ -77,7 +77,7 @@ InefficientVecto | |||
: ClangTidyCheck(Name, Context), | : ClangTidyCheck(Name, Context), | ||
VectorLikeClasse | VectorLikeClasse | ||
Options.get("VectorLikeClasse | Options.get("VectorLikeClasse | ||
- EnableProto(Options. | + EnableProto(Options.get("EnableProto", false)) {} | ||
void InefficientVecto | void InefficientVecto | ||
ClangTidyOptions | ClangTidyOptions |
@@ -26,7 +26,7 @@ public: | |||
ClangTidyContext | ClangTidyContext | ||
: ClangTidyCheck(Name, Context), | : ClangTidyCheck(Name, Context), | ||
IgnoreMacros(Options.getLocalOrGlobal | IgnoreMacros(Options.getLocalOrGlobal | ||
- Strict(Options. | + Strict(Options.get("Strict", false)) {} | ||
void storeOptions(ClangTidyOptions | void storeOptions(ClangTidyOptions | ||
void registerMatchers | void registerMatchers |
@@ -21,8 +21,7 @@ class RedundantAccessS | |||
public: | public: | ||
RedundantAccessS | RedundantAccessS | ||
: ClangTidyCheck(Name, Context), | : ClangTidyCheck(Name, Context), | ||
- CheckFirstDeclaration( | + CheckFirstDeclaration(Options.get("CheckFirstDeclaration", false)) {} | ||
- Options.getLocalOrGlobal | |||
bool isLanguageVersio | bool isLanguageVersio | ||
return LangOpts.CPlusPlus; | return LangOpts.CPlusPlus; | ||
} | } |
@@ -94,7 +94,7 @@ RedundantCasting | |||
ClangTidyContext | ClangTidyContext | ||
: ClangTidyCheck(Name, Context), | : ClangTidyCheck(Name, Context), | ||
IgnoreMacros(Options.getLocalOrGlobal | IgnoreMacros(Options.getLocalOrGlobal | ||
- IgnoreTypeAliases(Options. | + IgnoreTypeAliases(Options.get("IgnoreTypeAliases", false)) {} | ||
void RedundantCasting | void RedundantCasting | ||
Options.store(Opts, "IgnoreMacros", IgnoreMacros); | Options.store(Opts, "IgnoreMacros", IgnoreMacros); |
@@ -397,7 +397,7 @@ RenamerClangTidy | |||
ClangTidyContext | ClangTidyContext | ||
: ClangTidyCheck(CheckName, Context), | : ClangTidyCheck(CheckName, Context), | ||
AggressiveDepend | AggressiveDepend | ||
- Options. | + Options.get("AggressiveDependentMemberLookup", false)) {} | ||
RenamerClangTidy | RenamerClangTidy | ||
void RenamerClangTidy | void RenamerClangTidy |
@@ -550,9 +550,14 @@ bool SymbolCollector: | |||
// Avoid indexing internal symbols in protobuf generated headers. | // Avoid indexing internal symbols in protobuf generated headers. | ||
if (isPrivateProtoDe | if (isPrivateProtoDe | ||
return false; | return false; | ||
+ | |||
+ // System headers that end with `intrin.h` likely contain useful symbols. | |||
if (!Opts.CollectReserved && | if (!Opts.CollectReserved && | ||
(hasReservedName(ND) || hasReservedScope | (hasReservedName(ND) || hasReservedScope | ||
- 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; |
@@ -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: | + expression: CXXBindTemporary | ||
expression: CXXTemporaryObje | expression: CXXTemporaryObje | ||
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: CXXTemporaryObje | |||
+ 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; |
@@ -2111,6 +2111,20 @@ TEST_F(SymbolCol | |||
EXPECT_THAT(Symbols, IsEmpty()); | EXPECT_THAT(Symbols, IsEmpty()); | ||
} | } | ||
+TEST_F(SymbolCollectorT | |||
+ const char *Header = R"cpp( | |||
+ #pragma once | |||
+ void __foo(); | |||
+ )cpp"; | |||
+ | |||
+ TestHeaderName = "xintrin.h"; | |||
+ TestHeaderURI = URI::create(testPath(TestHeaderName)).toString(); | |||
+ InMemoryFileSyst | |||
+ CollectorOpts.FallbackDir = testRoot(); | |||
+ runSymbolCollect | |||
+ EXPECT_THAT(Symbols, UnorderedElement | |||
+} | |||
+ | |||
TEST_F(SymbolCollectorT | TEST_F(SymbolCollectorT | ||
const char *Header = R"cpp( | const char *Header = R"cpp( | ||
template <class T> | template <class T> |
@@ -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>`, AggressiveDepend | |||
+ :doc:`bugprone-unchecked-optional-access <clang-tidy/checks/bugprone/unchecked-optional-access>`, IgnoreSmartPoint | |||
+ :doc:`cppcoreguideline | |||
+ :doc:`cppcoreguideline | |||
+ :doc:`misc-include-cleaner <clang-tidy/checks/misc/include-cleaner>`, IgnoreHeaders; DeduplicateFindi | |||
+ :doc:`performance-inefficient-vector-operation <clang-tidy/checks/performance/inefficient-vector-operation>`, EnableProto | |||
+ :doc:`readability-identifier-naming <clang-tidy/checks/readability/identifier-naming>`, AggressiveDepend | |||
+ :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>`, CheckFirstDeclar | |||
+ :doc:`readability-redundant-casting <clang-tidy/checks/readability/redundant-casting>`, IgnoreTypeAliase | |||
+ | |||
New checks | New checks | ||
^^^^^^^^^^ | ^^^^^^^^^^ | ||
@@ -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: '0000000000000000 | |||
+// YAML-NEXT: ChildFunctions: | |||
+ | |||
+// MD: # Global Namespace | |||
+// MD: ## Functions | |||
+ | |||
+extern bool b(); | |||
+ | |||
+// YAML-NEXT: - USR: '88A104C263241E35 | |||
+// 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: 'EA3287837B3F175C | |||
+// 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: '60A47E4696CEFC41 | |||
+// 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: 'B3A9EC6BECD5869C | |||
+// 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: '307041280A81EB46 | |||
+// 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: 'A1CE9AB0064C412F | |||
+// 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: '5C2C44ED4825C066 | |||
+// 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: '412341570FD3AD2C | |||
+// 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()* |
@@ -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: | +// YAML-NEXT: Name: 'bool' | ||
-// YAML-NEXT: QualName: | +// 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( | +// 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,bo | |||
// 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, | +// 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,bo | |||
// 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, | +// 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_ | // MD: ### func_with_tuple_ | ||
-// MD: *tuple<int, int, | +// 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_ | // MD: **t** The input to func_with_tuple_ |
@@ -1,5 +1,5 @@ | |||
// RUN: %check_clang_tidy | // RUN: %check_clang_tidy | ||
-// RUN: -config="{CheckOptions: {StrictMode: true}}" -- | +// RUN: -config="{CheckOptions: {bugprone-argument-comment.StrictMode: true}}" -- | ||
void f(int _with_underscore | void f(int _with_underscore | ||
void g(int x_); | void g(int x_); |
@@ -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 | // RUN: %check_clang_tidy | ||
namespace Const { | namespace Const { |
@@ -1,5 +1,5 @@ | |||
// RUN: %check_clang_tidy | // RUN: %check_clang_tidy | ||
-// 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 { | ||
}; | }; |
@@ -1,5 +1,5 @@ | |||
// RUN: %check_clang_tidy | // RUN: %check_clang_tidy | ||
-// 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 { |
@@ -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_heade | // RUN: -- -isystem %clang_tidy_heade | ||
// RUN: -DPRI_CMDLINE_MAC | // RUN: -DPRI_CMDLINE_MAC | ||
// RUN: -D__PRI_CMDLINE_M | // RUN: -D__PRI_CMDLINE_M | ||
// 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_heade | // RUN: -- -isystem %clang_tidy_heade | ||
// RUN: -DPRI_CMDLINE_MAC | // RUN: -DPRI_CMDLINE_MAC | ||
// RUN: -D__PRI_CMDLINE_M | // RUN: -D__PRI_CMDLINE_M |
@@ -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_heade | // RUN: -- -isystem %clang_tidy_heade | ||
// 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_heade | // RUN: -- -isystem %clang_tidy_heade | ||
#include <cstdio> | #include <cstdio> |
@@ -1,12 +1,12 @@ | |||
// 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_heade | // RUN: -- -isystem %clang_tidy_heade | ||
// RUN: -DPRI_CMDLINE_MAC | // RUN: -DPRI_CMDLINE_MAC | ||
// RUN: -D__PRI_CMDLINE_M | // RUN: -D__PRI_CMDLINE_M | ||
// 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_heade | // RUN: -- -isystem %clang_tidy_heade | ||
// RUN: -DPRI_CMDLINE_MAC | // RUN: -DPRI_CMDLINE_MAC | ||
// RUN: -D__PRI_CMDLINE_M | // RUN: -D__PRI_CMDLINE_M |
@@ -631,8 +631,8 @@ TEST(SerializeTe | |||
TEST(SerializeTests, emitFunctionTemp | TEST(SerializeTests, emitFunctionTemp | ||
EmittedInfoList Infos; | EmittedInfoList Infos; | ||
// A template and a specialization. | // A template and a specialization. | ||
- ExtractInfosFromCode("template<typename T = int> | + ExtractInfosFromCode("template<typename T = int> bool GetFoo(T);\n" | ||
- "template<> | + "template<> bool GetFoo<bool>(bool);", | ||
2, | 2, | ||
/*Public=*/false, Infos); | /*Public=*/false, Infos); | ||
@@ -666,6 +666,8 @@ TEST(SerializeTe | |||
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, emitClassTemplat | TEST(SerializeTests, emitClassTemplat |
@@ -71,10 +71,12 @@ TEST(IncludeClea | |||
std::vector<ClangTidyError> Errors; | std::vector<ClangTidyError> Errors; | ||
ClangTidyOptions | ClangTidyOptions | ||
- Opts.CheckOptions[ | + 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(appendPathFileSy | + llvm::Regex::escape( | ||
- llvm::Regex::escape(appendPathFileSy | + appendPathFileSy | ||
+ llvm::Regex::escape( | |||
+ appendPathFileSy | |||
EXPECT_EQ( | EXPECT_EQ( | ||
PostCode, | PostCode, | ||
runCheckOnCode<IncludeCleanerCh | runCheckOnCode<IncludeCleanerCh | ||
@@ -139,7 +141,7 @@ int BarResult2 = $diag2^bar();)") | |||
{ | { | ||
std::vector<ClangTidyError> Errors; | std::vector<ClangTidyError> Errors; | ||
ClangTidyOptions | ClangTidyOptions | ||
- Opts.CheckOptions. | + Opts.CheckOptions["test-check-0.DeduplicateFindings"] = "false"; | ||
runCheckOnCode<IncludeCleanerCh | runCheckOnCode<IncludeCleanerCh | ||
Opts, | Opts, | ||
{{"baz.h", R"(#pragma once | {{"baz.h", R"(#pragma once | ||
@@ -170,7 +172,7 @@ std::vector x; | |||
)"; | )"; | ||
ClangTidyOptions | ClangTidyOptions | ||
- Opts.CheckOptions[ | + Opts.CheckOptions["test-check-0.IgnoreHeaders"] = llvm::StringRef{ | ||
"public.h;<vector>;baz.h;" + | "public.h;<vector>;baz.h;" + | ||
llvm::Regex::escape(appendPathFileSy | llvm::Regex::escape(appendPathFileSy | ||
std::vector<ClangTidyError> Errors; | std::vector<ClangTidyError> Errors; |
@@ -362,7 +362,6 @@ if (APPLE AND NOT CMAKE_LINKER MATCHES ".*lld.*") | |||
message(STATUS "Host linker version: ${HOST_LINK_VERSIO | message(STATUS "Host linker version: ${HOST_LINK_VERSIO | ||
endif() | endif() | ||
-include(CMakeParseArgume | |||
include(AddClang) | include(AddClang) | ||
set(CMAKE_INCLUDE_CU | set(CMAKE_INCLUDE_CU |
@@ -333,7 +333,7 @@ foreach(target armv6m-none-eabi | |||
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)\" | + 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- | |||
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)\" | + 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 "") |
@@ -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 | +* 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. | ||
@@ -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_t | |||
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-comprehensiv | |||
``__builtin_elemen | ``__builtin_elemen | ||
``__builtin_elemen | ``__builtin_elemen | ||
+- 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_overfl | |||
+ 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/SanitizerSpecial | <https://clang.llvm.org/docs/SanitizerSpecial | ||
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_sp | - Fixed an issue that led to crashes when calling ``Type.get_exception_sp |
@@ -191,8 +191,9 @@ using DeviceTypeArgume | |||
/// an identifier. The 'asterisk' means 'the rest'. | /// an identifier. The 'asterisk' means 'the rest'. | ||
class OpenACCDeviceTyp | class OpenACCDeviceTyp | ||
: public OpenACCClauseWit | : public OpenACCClauseWit | ||
- | + private llvm::TrailingObjects<OpenACCDeviceTypeClause, | ||
DeviceTypeArgume | DeviceTypeArgume | ||
+ 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 OpenACCWaitClaus | class OpenACCWaitClaus | ||
: public OpenACCClauseWit | : public OpenACCClauseWit | ||
- | + private llvm::TrailingObjects<OpenACCWaitClause, Expr *> { | ||
+ friend TrailingObjects; | |||
SourceLocation QueuesLoc; | SourceLocation QueuesLoc; | ||
OpenACCWaitClaus | OpenACCWaitClaus | ||
Expr *DevNumExpr, SourceLocation QueuesLoc, | Expr *DevNumExpr, SourceLocation QueuesLoc, | ||
@@ -419,7 +421,8 @@ public: | |||
class OpenACCNumGangsC | class OpenACCNumGangsC | ||
: public OpenACCClauseWit | : public OpenACCClauseWit | ||
- | + private llvm::TrailingObjects<OpenACCNumGangsClause, Expr *> { | ||
+ friend TrailingObjects; | |||
OpenACCNumGangsC | OpenACCNumGangsC | ||
ArrayRef<Expr *> IntExprs, SourceLocation EndLoc) | ArrayRef<Expr *> IntExprs, SourceLocation EndLoc) | ||
@@ -449,7 +452,8 @@ public: | |||
class OpenACCTileClaus | class OpenACCTileClaus | ||
: public OpenACCClauseWit | : public OpenACCClauseWit | ||
- | + private llvm::TrailingObjects<OpenACCTileClause, Expr *> { | ||
+ friend TrailingObjects; | |||
OpenACCTileClaus | OpenACCTileClaus | ||
ArrayRef<Expr *> SizeExprs, SourceLocation EndLoc) | ArrayRef<Expr *> SizeExprs, SourceLocation EndLoc) | ||
: OpenACCClauseWit | : OpenACCClauseWit | ||
@@ -503,7 +507,8 @@ public: | |||
class OpenACCGangClaus | class OpenACCGangClaus | ||
: public OpenACCClauseWit | : public OpenACCClauseWit | ||
- | + private llvm::TrailingObjects<OpenACCGangClause, Expr *, OpenACCGangKind> { | ||
+ friend TrailingObjects; | |||
protected: | protected: | ||
OpenACCGangClaus | OpenACCGangClaus | ||
ArrayRef<OpenACCGangKind> GangKinds, | ArrayRef<OpenACCGangKind> GangKinds, | ||
@@ -658,7 +663,8 @@ public: | |||
class OpenACCPrivateCl | class OpenACCPrivateCl | ||
: public OpenACCClauseWit | : public OpenACCClauseWit | ||
- | + private llvm::TrailingObjects<OpenACCPrivateClause, Expr *> { | ||
+ friend TrailingObjects; | |||
OpenACCPrivateCl | OpenACCPrivateCl | ||
ArrayRef<Expr *> VarList, SourceLocation EndLoc) | ArrayRef<Expr *> VarList, SourceLocation EndLoc) | ||
@@ -680,7 +686,8 @@ public: | |||
class OpenACCFirstPriv | class OpenACCFirstPriv | ||
: public OpenACCClauseWit | : public OpenACCClauseWit | ||
- | + private llvm::TrailingObjects<OpenACCFirstPrivateClause, Expr *> { | ||
+ friend TrailingObjects; | |||
OpenACCFirstPriv | OpenACCFirstPriv | ||
ArrayRef<Expr *> VarList, SourceLocation EndLoc) | ArrayRef<Expr *> VarList, SourceLocation EndLoc) | ||
@@ -702,7 +709,8 @@ public: | |||
class OpenACCDevicePtr | class OpenACCDevicePtr | ||
: public OpenACCClauseWit | : public OpenACCClauseWit | ||
- | + private llvm::TrailingObjects<OpenACCDevicePtrClause, Expr *> { | ||
+ friend TrailingObjects; | |||
OpenACCDevicePtr | OpenACCDevicePtr | ||
ArrayRef<Expr *> VarList, SourceLocation EndLoc) | ArrayRef<Expr *> VarList, SourceLocation EndLoc) | ||
@@ -724,7 +732,8 @@ public: | |||
class OpenACCAttachCla | class OpenACCAttachCla | ||
: public OpenACCClauseWit | : public OpenACCClauseWit | ||
- | + private llvm::TrailingObjects<OpenACCAttachClause, Expr *> { | ||
+ friend TrailingObjects; | |||
OpenACCAttachCla | OpenACCAttachCla | ||
ArrayRef<Expr *> VarList, SourceLocation EndLoc) | ArrayRef<Expr *> VarList, SourceLocation EndLoc) | ||
@@ -746,7 +755,8 @@ public: | |||
class OpenACCDetachCla | class OpenACCDetachCla | ||
: public OpenACCClauseWit | : public OpenACCClauseWit | ||
- | + private llvm::TrailingObjects<OpenACCDetachClause, Expr *> { | ||
+ friend TrailingObjects; | |||
OpenACCDetachCla | OpenACCDetachCla | ||
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 OpenACCDeleteCla | |||
+ : public OpenACCClauseWit | |||
+ private llvm::TrailingObjects<OpenACCDeleteCla | |||
+ friend TrailingObjects; | |||
+ | |||
+ OpenACCDeleteCla | |||
+ ArrayRef<Expr *> VarList, SourceLocation EndLoc) | |||
+ : OpenACCClauseWit | |||
+ EndLoc) { | |||
+ std::uninitialized_co | |||
+ getTrailingObjec | |||
+ setExprs(MutableArrayRef(getTrailingObjec | |||
+ } | |||
+ | |||
+public: | |||
+ static bool classof(const OpenACCClause *C) { | |||
+ return C->getClauseKind() == OpenACCClauseKin | |||
+ } | |||
+ static OpenACCDeleteCla | |||
+ Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc, | |||
+ ArrayRef<Expr *> VarList, SourceLocation EndLoc); | |||
+}; | |||
+ | |||
+class OpenACCUseDevice | |||
+ : public OpenACCClauseWit | |||
+ private llvm::TrailingObjects<OpenACCUseDevice | |||
+ friend TrailingObjects; | |||
+ | |||
+ OpenACCUseDevice | |||
+ ArrayRef<Expr *> VarList, SourceLocation EndLoc) | |||
+ : OpenACCClauseWit | |||
+ LParenLoc, EndLoc) { | |||
+ std::uninitialized_co | |||
+ getTrailingObjec | |||
+ setExprs(MutableArrayRef(getTrailingObjec | |||
+ } | |||
+ | |||
+public: | |||
+ static bool classof(const OpenACCClause *C) { | |||
+ return C->getClauseKind() == OpenACCClauseKin | |||
+ } | |||
+ static OpenACCUseDevice | |||
+ Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc, | |||
+ ArrayRef<Expr *> VarList, SourceLocation EndLoc); | |||
+}; | |||
+ | |||
class OpenACCNoCreateC | class OpenACCNoCreateC | ||
: public OpenACCClauseWit | : public OpenACCClauseWit | ||
- | + private llvm::TrailingObjects<OpenACCNoCreateClause, Expr *> { | ||
+ friend TrailingObjects; | |||
OpenACCNoCreateC | OpenACCNoCreateC | ||
ArrayRef<Expr *> VarList, SourceLocation EndLoc) | ArrayRef<Expr *> VarList, SourceLocation EndLoc) | ||
@@ -790,7 +847,8 @@ public: | |||
class OpenACCPresentCl | class OpenACCPresentCl | ||
: public OpenACCClauseWit | : public OpenACCClauseWit | ||
- | + private llvm::TrailingObjects<OpenACCPresentClause, Expr *> { | ||
+ friend TrailingObjects; | |||
OpenACCPresentCl | OpenACCPresentCl | ||
ArrayRef<Expr *> VarList, SourceLocation EndLoc) | ArrayRef<Expr *> VarList, SourceLocation EndLoc) | ||
@@ -812,7 +870,8 @@ public: | |||
class OpenACCCopyClaus | class OpenACCCopyClaus | ||
: public OpenACCClauseWit | : public OpenACCClauseWit | ||
- | + private llvm::TrailingObjects<OpenACCCopyClause, Expr *> { | ||
+ friend TrailingObjects; | |||
OpenACCCopyClaus | OpenACCCopyClaus | ||
SourceLocation LParenLoc, ArrayRef<Expr *> VarList, | SourceLocation LParenLoc, ArrayRef<Expr *> VarList, | ||
@@ -841,7 +900,8 @@ public: | |||
class OpenACCCopyInCla | class OpenACCCopyInCla | ||
: public OpenACCClauseWit | : public OpenACCClauseWit | ||
- | + private llvm::TrailingObjects<OpenACCCopyInClause, Expr *> { | ||
+ friend TrailingObjects; | |||
bool IsReadOnly; | bool IsReadOnly; | ||
OpenACCCopyInCla | OpenACCCopyInCla | ||
@@ -873,7 +933,8 @@ public: | |||
class OpenACCCopyOutCl | class OpenACCCopyOutCl | ||
: public OpenACCClauseWit | : public OpenACCClauseWit | ||
- | + private llvm::TrailingObjects<OpenACCCopyOutClause, Expr *> { | ||
+ friend TrailingObjects; | |||
bool IsZero; | bool IsZero; | ||
OpenACCCopyOutCl | OpenACCCopyOutCl | ||
@@ -905,7 +966,8 @@ public: | |||
class OpenACCCreateCla | class OpenACCCreateCla | ||
: public OpenACCClauseWit | : public OpenACCClauseWit | ||
- | + private llvm::TrailingObjects<OpenACCCreateClause, Expr *> { | ||
+ friend TrailingObjects; | |||
bool IsZero; | bool IsZero; | ||
OpenACCCreateCla | OpenACCCreateCla | ||
@@ -937,7 +999,8 @@ public: | |||
class OpenACCReduction | class OpenACCReduction | ||
: public OpenACCClauseWit | : public OpenACCClauseWit | ||
- | + private llvm::TrailingObjects<OpenACCReductionClause, Expr *> { | ||
+ friend TrailingObjects; | |||
OpenACCReduction | OpenACCReduction | ||
OpenACCReduction | OpenACCReduction |
@@ -127,11 +127,12 @@ public: | |||
/// the 'Kind'. | /// the 'Kind'. | ||
class OpenACCComputeCo | class OpenACCComputeCo | ||
: public OpenACCAssociate | : public OpenACCAssociate | ||
- | + private llvm::TrailingObjects<OpenACCComputeConstruct, | ||
- | + const OpenACCClause *> { | ||
friend class ASTStmtWriter; | friend class ASTStmtWriter; | ||
friend class ASTStmtReader; | friend class ASTStmtReader; | ||
friend class ASTContext; | friend class ASTContext; | ||
+ friend TrailingObjects; | |||
OpenACCComputeCo | OpenACCComputeCo | ||
: OpenACCAssociate | : OpenACCAssociate | ||
OpenACCComputeCo | OpenACCComputeCo | ||
@@ -189,7 +190,7 @@ public: | |||
/// Construct. | /// Construct. | ||
class OpenACCLoopConst | class OpenACCLoopConst | ||
: public OpenACCAssociate | : public OpenACCAssociate | ||
- | + 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 OpenACCLoopConst | |||
friend class OpenACCAssociate | friend class OpenACCAssociate | ||
friend class OpenACCCombinedC | friend class OpenACCCombinedC | ||
friend class OpenACCComputeCo | friend class OpenACCComputeCo | ||
+ friend TrailingObjects; | |||
OpenACCLoopConst | OpenACCLoopConst | ||
@@ -245,8 +247,9 @@ public: | |||
// shared with both loop and compute constructs. | // shared with both loop and compute constructs. | ||
class OpenACCCombinedC | class OpenACCCombinedC | ||
: public OpenACCAssociate | : public OpenACCAssociate | ||
- | + private llvm::TrailingObjects<OpenACCCombinedConstruct, | ||
const OpenACCClause *> { | const OpenACCClause *> { | ||
+ friend TrailingObjects; | |||
OpenACCCombinedC | OpenACCCombinedC | ||
: OpenACCAssociate | : OpenACCAssociate | ||
OpenACCCombinedC | OpenACCCombinedC | ||
@@ -297,8 +300,9 @@ public: | |||
// and clauses, but is otherwise pretty simple. | // and clauses, but is otherwise pretty simple. | ||
class OpenACCDataConst | class OpenACCDataConst | ||
: public OpenACCAssociate | : public OpenACCAssociate | ||
- | + private llvm::TrailingObjects<OpenACCDataConstruct, | ||
const OpenACCClause *> { | const OpenACCClause *> { | ||
+ friend TrailingObjects; | |||
OpenACCDataConst | OpenACCDataConst | ||
: OpenACCAssociate | : OpenACCAssociate | ||
OpenACCDataConst | OpenACCDataConst | ||
@@ -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 OpenACCEnterData | class OpenACCEnterData | ||
: public OpenACCConstruct | : public OpenACCConstruct | ||
- | + private llvm::TrailingObjects<OpenACCEnterDataConstruct, | ||
const OpenACCClause *> { | const OpenACCClause *> { | ||
+ friend TrailingObjects; | |||
OpenACCEnterData | OpenACCEnterData | ||
: OpenACCConstruct | : OpenACCConstruct | ||
OpenACCDirective | OpenACCDirective | ||
@@ -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 OpenACCExitDataC | class OpenACCExitDataC | ||
: public OpenACCConstruct | : public OpenACCConstruct | ||
- | + private llvm::TrailingObjects<OpenACCExitDataConstruct, | ||
const OpenACCClause *> { | const OpenACCClause *> { | ||
+ friend TrailingObjects; | |||
OpenACCExitDataC | OpenACCExitDataC | ||
: OpenACCConstruct | : OpenACCConstruct | ||
OpenACCDirective | OpenACCDirective | ||
@@ -420,8 +426,9 @@ public: | |||
// statement and clauses, but is otherwise pretty simple. | // statement and clauses, but is otherwise pretty simple. | ||
class OpenACCHostDataC | class OpenACCHostDataC | ||
: public OpenACCAssociate | : public OpenACCAssociate | ||
- | + private llvm::TrailingObjects<OpenACCHostDataConstruct, | ||
const OpenACCClause *> { | const OpenACCClause *> { | ||
+ friend TrailingObjects; | |||
OpenACCHostDataC | OpenACCHostDataC | ||
: OpenACCAssociate | : OpenACCAssociate | ||
OpenACCHostDataC | OpenACCHostDataC |
@@ -4762,6 +4762,12 @@ def HLSLAsDouble : LangBuiltin<"HLS | |||
let Prototype = "void(...)"; | let Prototype = "void(...)"; | ||
} | } | ||
+def HLSLWaveActiveAl | |||
+ let Spellings = ["__builtin_hlsl_w | |||
+ let Attributes = [NoThrow, Const]; | |||
+ let Prototype = "bool(bool)"; | |||
+} | |||
+ | |||
def HLSLWaveActiveAn | def HLSLWaveActiveAn | ||
let Spellings = ["__builtin_hlsl_w | let Spellings = ["__builtin_hlsl_w | ||
let Attributes = [NoThrow, Const]; | let Attributes = [NoThrow, Const]; |
@@ -3233,8 +3233,8 @@ def err_attribute_to | |||
"%0 attribute takes at least %1 argument%s1">; | "%0 attribute takes at least %1 argument%s1">; | ||
def err_attribute_in | def err_attribute_in | ||
def err_attribute_in | def err_attribute_in | ||
- "'_BitInt' | + "'_BitInt' %select{vector|matrix}0 element width must be %select{a power of 2|" | ||
- "at least as wide as 'CHAR_BIT'} | + "at least as wide as 'CHAR_BIT'}1">; | ||
def err_attribute_in | def err_attribute_in | ||
def err_attribute_ba | def err_attribute_ba | ||
"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_re | |||
// 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_ | def warn_comparison_ | ||
- "%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<TautologicalComp | InGroup<TautologicalComp | ||
def warn_comparison_ | def warn_comparison_ | ||
@@ -12682,6 +12682,9 @@ def err_acc_not_a_va | |||
: 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_va | |||
+ : Error<"OpenACC variable in 'use_device' clause is not a valid variable " | |||
+ "name or array name">; | |||
def err_acc_typechec | def err_acc_typechec | ||
: 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 | def err_acc_subarray | ||
@@ -12801,6 +12804,8 @@ def err_acc_loop_ter | |||
def err_acc_loop_not | def err_acc_loop_not | ||
: 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_construc | |||
+ : Error<"OpenACC '%0' construct must have at least one %1 clause">; | |||
// AMDGCN builtins diagnostics | // AMDGCN builtins diagnostics | ||
def err_amdgcn_globa | def err_amdgcn_globa |
@@ -102,6 +102,7 @@ FEATURE(numerica | |||
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 | FEATURE(thread_sanitizer | ||
FEATURE(dataflow_sanitiz | FEATURE(dataflow_sanitiz | ||
FEATURE(scudo, LangOpts.Sanitize.hasOneOf(SanitizerKind::Scudo)) | FEATURE(scudo, LangOpts.Sanitize.hasOneOf(SanitizerKind::Scudo)) |
@@ -38,6 +38,7 @@ VISIT_CLAUSE(Cre | |||
CLAUSE_ALIAS(PCreate, Create, true) | CLAUSE_ALIAS(PCreate, Create, true) | ||
CLAUSE_ALIAS(PresentOrCreate, | CLAUSE_ALIAS(PresentOrCreate, | ||
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(Red | |||
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) |
@@ -73,6 +73,9 @@ SANITIZER("fuzze | |||
// libFuzzer-required instrumentation, | // libFuzzer-required instrumentation, | ||
SANITIZER("fuzzer-no-link", FuzzerNoLink) | SANITIZER("fuzzer-no-link", FuzzerNoLink) | ||
+// TypeSanitizer | |||
+SANITIZER("type", Type) | |||
+ | |||
// ThreadSanitizer | // ThreadSanitizer | ||
SANITIZER("thread", Thread) | SANITIZER("thread", Thread) | ||
@@ -748,11 +748,28 @@ let SMETargetGuard = "sme2" in { | |||
let SMETargetGuard = "sme-f8f32" in { | let SMETargetGuard = "sme-f8f32" in { | ||
def SVDOT_LANE_FP8_Z | def SVDOT_LANE_FP8_Z | ||
def SVDOT_LANE_FP8_Z | def SVDOT_LANE_FP8_Z | ||
+ | |||
+ def SVVDOTB_LANE_FP8 | |||
+ def SVVDOTT_LANE_FP8 | |||
+ | |||
+ def SVDOT_SINGLE_FP8 | |||
+ def SVDOT_SINGLE_FP8 | |||
+ | |||
+ def SVDOT_MULTI_FP8_ | |||
+ def SVDOT_MULTI_FP8_ | |||
} | } | ||
let SMETargetGuard = "sme-f8f16" in { | let SMETargetGuard = "sme-f8f16" in { | ||
def SVDOT_LANE_FP8_Z | def SVDOT_LANE_FP8_Z | ||
def SVDOT_LANE_FP8_Z | def SVDOT_LANE_FP8_Z | ||
+ | |||
+ def SVVDOT_LANE_FP8_ | |||
+ | |||
+ def SVDOT_SINGLE_FP8 | |||
+ def SVDOT_SINGLE_FP8 | |||
+ | |||
+ def SVDOT_MULTI_FP8_ | |||
+ def SVDOT_MULTI_FP8_ | |||
} | } | ||
//////////////////////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////////////////////// | ||
@@ -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_ | def SVMOPA_FP8_ZA32 : Inst<"svmopa_za32[_mf8]_m_fpm", "viPPdd>", "m", MergeNone, "aarch64_sme_fp8_ | ||
[IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], [ImmCheck<0, ImmCheck0_3>]>; | [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], [ImmCheck<0, ImmCheck0_3>]>; | ||
+ // FMLALL (indexed) | |||
+ def SVMLA_FP8_LANE_Z | |||
+ [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], [ImmCheck<3, ImmCheck0_15>]>; | |||
+ def SVMLA_FP8_LANE_Z | |||
+ [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], [ImmCheck<3, ImmCheck0_15>]>; | |||
+ def SVMLA_FP8_LANE_Z | |||
+ [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], [ImmCheck<3, ImmCheck0_15>]>; | |||
+ // FMLALL (single) | |||
+ def SVMLA_FP8_SINGLE | |||
+ [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], []>; | |||
+ def SVMLA_FP8_SINGLE | |||
+ [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], []>; | |||
+ def SVMLA_FP8_SINGLE | |||
+ [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], []>; | |||
+ // FMLALL (multiple) | |||
+ def SVMLA_FP8_MULTI_ | |||
+ [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], []>; | |||
+ def SVMLA_FP8_MULTI_ | |||
+ [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_ | def SVMOPA_FP8_ZA16 : Inst<"svmopa_za16[_mf8]_m_fpm", "viPPdd>", "m", MergeNone, "aarch64_sme_fp8_ | ||
[IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], [ImmCheck<0, ImmCheck0_1>]>; | [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], [ImmCheck<0, ImmCheck0_1>]>; | ||
+ // FMLAL (indexed) | |||
+ def SVMLA_FP8_LANE_Z | |||
+ [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], [ImmCheck<3, ImmCheck0_15>]>; | |||
+ def SVMLA_FP8_LANE_Z | |||
+ [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], [ImmCheck<3, ImmCheck0_15>]>; | |||
+ def SVMLA_FP8_LANE_Z | |||
+ [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], [ImmCheck<3, ImmCheck0_15>]>; | |||
+ // FMLAL (single) | |||
+ def SVMLA_FP8_SINGLE | |||
+ [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], []>; | |||
+ def SVMLA_FP8_SINGLE | |||
+ [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], []>; | |||
+ def SVMLA_FP8_SINGLE | |||
+ [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], []>; | |||
+ // FMLAL (multiple) | |||
+ def SVMLA_FP8_MULTI_ | |||
+ [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], []>; | |||
+ def SVMLA_FP8_MULTI_ | |||
+ [IsStreaming, IsInOutZA, SetsFPMR, IsOverloadNone], []>; | |||
} | } | ||
} // let SVETargetGuard = InvalidMode | } // let SVETargetGuard = InvalidMode |
@@ -1056,11 +1056,11 @@ def z : Separate<["-"], "z">, Flags<[LinkerInp | |||
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 | + 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 : JoinedAndSeparat | def Xoffload_linker : JoinedAndSeparat | ||
- Visibility<[ClangOption, | + 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_Gro | def Xpreprocessor : Separate<["-"], "Xpreprocessor">, Group<Preprocessor_Gro | ||
@@ -1176,7 +1176,7 @@ def compatibility__v | |||
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, | +def : Separate<["--"], "config">, Visibility<[ClangOption, FlangOption]>, Alias<config>; | ||
def no_default_confi | def no_default_confi | ||
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 | |||
Visibility<[ClangOption, CLOption, DXCOption, FlangOption]>, | Visibility<[ClangOption, CLOption, DXCOption, FlangOption]>, | ||
Alias<fno_color_diagno | Alias<fno_color_diagno | ||
def fdiagnostics_col | def fdiagnostics_col | ||
- Visibility<[ClangOption, | + Visibility<[ClangOption, FlangOption]>, | ||
Values<"auto,always,neve | Values<"auto,always,neve | ||
HelpText<"When to use colors in diagnostics">; | HelpText<"When to use colors in diagnostics">; | ||
def fansi_escape_cod | def fansi_escape_cod | ||
@@ -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, | + Visibility<[ClangOption, FlangOption]>; | ||
def fno_record_comma | def fno_record_comma | ||
Group<f_Group>, | Group<f_Group>, | ||
- Visibility<[ClangOption, | + Visibility<[ClangOption, FlangOption]>; | ||
def : Flag<["-"], "frecord-gcc-switches">, Alias<frecord_command_ | def : Flag<["-"], "frecord-gcc-switches">, Alias<frecord_command_ | ||
def : Flag<["-"], "fno-record-gcc-switches">, Alias<fno_record_comma | def : Flag<["-"], "fno-record-gcc-switches">, Alias<fno_record_comma | ||
def fcommon : Flag<["-"], "fcommon">, Group<f_Group>, | def fcommon : Flag<["-"], "fcommon">, Group<f_Group>, | ||
@@ -3463,6 +3463,9 @@ defm diagnostics_show | |||
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_protec | def fno_stack_protec | ||
HelpText<"Disable the use of stack protectors">; | HelpText<"Disable the use of stack protectors">; | ||
def fno_strict_alias | def fno_strict_alias | ||
@@ -4296,6 +4299,9 @@ defm stack_size_secti | |||
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 | def stack_usage_file | ||
@@ -5648,7 +5654,7 @@ def gpulibc : Flag<["-"], "gpulibc">, Visibility<[Clan | |||
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 | + 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<[Clan | |||
HelpText<"Disable standard #include directories for the C++ standard library">, | HelpText<"Disable standard #include directories for the C++ standard library">, | ||
MarshallingInfoN | MarshallingInfoN | ||
def nostdlib : Flag<["-"], "nostdlib">, | def nostdlib : Flag<["-"], "nostdlib">, | ||
- Visibility<[ClangOption, | + Visibility<[ClangOption, FlangOption]>, | ||
Group<Link_Group>; | Group<Link_Group>; | ||
def stdlib : Flag<["-"], "stdlib">, | def stdlib : Flag<["-"], "stdlib">, | ||
- Visibility<[ClangOption, | + 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="> | |||
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, | + 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 | def frtlib_add_rpath | ||
@@ -5851,7 +5857,7 @@ def segs__read__writ | |||
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, | + 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_ | |||
def static_libgcc : Flag<["-"], "static-libgcc">; | def static_libgcc : Flag<["-"], "static-libgcc">; | ||
def static_libstdcxx | def static_libstdcxx | ||
def static : Flag<["-", "--"], "static">, Group<Link_Group>, | def static : Flag<["-", "--"], "static">, Group<Link_Group>, | ||
- Visibility<[ClangOption, | + 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<"re | |||
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_underscor | defm second_underscor | ||
@@ -6908,6 +6913,7 @@ defm underscoring : OptInFC1FFlag<"u | |||
defm ppc_native_vec_e | defm ppc_native_vec_e | ||
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">; |
@@ -87,6 +87,7 @@ public: | |||
bool needsHwasanAlias | bool needsHwasanAlias | ||
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); } |
@@ -10659,6 +10659,11 @@ public: | |||
SourceLocation EndLoc); | SourceLocation EndLoc); | ||
void ActOnForEachDecl | void ActOnForEachDecl | ||
+ /// DiagnoseDiscarde | |||
+ /// semantically a discarded-value expression, diagnose if any [[nodiscard]] | |||
+ /// value has been discarded. | |||
+ void DiagnoseDiscarde | |||
+ | |||
/// DiagnoseUnusedEx | /// DiagnoseUnusedEx | ||
/// whose result is unused, warn. | /// whose result is unused, warn. | ||
void DiagnoseUnusedEx | void DiagnoseUnusedEx |
@@ -399,6 +399,8 @@ public: | |||
ClauseKind == OpenACCClauseKin | ClauseKind == OpenACCClauseKin | ||
ClauseKind == OpenACCClauseKin | ClauseKind == OpenACCClauseKin | ||
ClauseKind == OpenACCClauseKin | ClauseKind == OpenACCClauseKin | ||
+ ClauseKind == OpenACCClauseKin | |||
+ ClauseKind == OpenACCClauseKin | |||
ClauseKind == OpenACCClauseKin | ClauseKind == OpenACCClauseKin | ||
ClauseKind == OpenACCClauseKin | ClauseKind == OpenACCClauseKin | ||
ClauseKind == OpenACCClauseKin | ClauseKind == OpenACCClauseKin | ||
@@ -536,6 +538,8 @@ public: | |||
ClauseKind == OpenACCClauseKin | ClauseKind == OpenACCClauseKin | ||
ClauseKind == OpenACCClauseKin | ClauseKind == OpenACCClauseKin | ||
ClauseKind == OpenACCClauseKin | ClauseKind == OpenACCClauseKin | ||
+ ClauseKind == OpenACCClauseKin | |||
+ ClauseKind == OpenACCClauseKin | |||
ClauseKind == OpenACCClauseKin | ClauseKind == OpenACCClauseKin | ||
ClauseKind == OpenACCClauseKin | ClauseKind == OpenACCClauseKin | ||
ClauseKind == OpenACCClauseKin | ClauseKind == OpenACCClauseKin | ||
@@ -573,6 +577,8 @@ public: | |||
ClauseKind == OpenACCClauseKin | ClauseKind == OpenACCClauseKin | ||
ClauseKind == OpenACCClauseKin | ClauseKind == OpenACCClauseKin | ||
ClauseKind == OpenACCClauseKin | ClauseKind == OpenACCClauseKin | ||
+ ClauseKind == OpenACCClauseKin | |||
+ ClauseKind == OpenACCClauseKin | |||
ClauseKind == OpenACCClauseKin | ClauseKind == OpenACCClauseKin | ||
ClauseKind == OpenACCClauseKin | ClauseKind == OpenACCClauseKin | ||
ClauseKind == OpenACCClauseKin | ClauseKind == OpenACCClauseKin | ||
@@ -656,7 +662,8 @@ public: | |||
/// parsing has consumed the 'annot_pragma_ope | /// parsing has consumed the 'annot_pragma_ope | ||
/// 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_ope | /// parsing has consumed the 'annot_pragma_ope |
@@ -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 | + /// 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_MA | ||
- /// enclosing function. | |||
- FUNCTION_DECL_TO | |||
/// 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. |
@@ -537,17 +537,14 @@ private: | |||
/// namespace as if it is not delayed. | /// namespace as if it is not delayed. | ||
DelayedNamespace | DelayedNamespace | ||
- /// Mapping from | + /// Mapping from main decl ID to the related decls IDs. | ||
- /// | + /// | ||
- /// These | + /// These related decls have to be loaded right after the main decl. | ||
- /// It is required to have canonical declaration for | + /// It is required to have canonical declaration for related decls from the | ||
- /// same module as enclosing | + /// same module as the enclosing main decl. Without this, due to lazy | ||
- /// captured variables in the lambda. Without this, due to lazy | + /// deserialization, | ||
- /// deserialization, | + /// 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>> | |||
- FunctionToLambda | |||
struct PendingUpdateRec | struct PendingUpdateRec | ||
Decl *D; | Decl *D; |
@@ -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 | + /// Mapping from the main decl to related decls inside the main decls. | ||
- /// function. | |||
/// | /// | ||
- /// These | + /// These related decls have to be loaded right after the main decl they | ||
- /// In order to have canonical declaration for | + /// belong to. In order to have canonical declaration for related decls from | ||
- /// module as | + /// the same module as the main decl during deserialization. | ||
- llvm::DenseMap<LocalDeclID, SmallVector<LocalDeclID, 4>> | + 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. |
@@ -6483,14 +6483,6 @@ bool Compiler<Emitter | |||
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 | |||
return false; | return false; | ||
} | } | ||
- if (!ToT | + if (!ToT) { | ||
- if (!this- | + 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 | |||
ToType->isSpecificBuilti | ToType->isSpecificBuilti | ||
uint32_t ResultBitWidth = std::max(Ctx.getBitWidth(ToType), 8u); | uint32_t ResultBitWidth = std::max(Ctx.getBitWidth(ToType), 8u); | ||
- if (!this- | + if (!this->emitBitCastPrim(*ToT, ToTypeIsUChar || ToType->isStdByteType(), | ||
- | + ResultBitWidth, TargetSemantics, E)) | ||
return false; | return false; | ||
if (DiscardResult) | if (DiscardResult) |
@@ -179,7 +179,10 @@ public: | |||
unsigned countLeadingZero | unsigned countLeadingZero | ||
if constexpr (!Signed) | if constexpr (!Signed) | ||
return llvm::countl_zero<ReprT>(V); | return llvm::countl_zero<ReprT>(V); | ||
- llvm_unreachable | + if (isPositive()) | ||
+ return llvm::countl_zero<typename AsUnsigned::ReprT>( | |||
+ static_cast<typename AsUnsigned::ReprT>(V)); | |||
+ llvm_unreachable | |||
} | } | ||
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); |
@@ -318,18 +318,6 @@ template <PrimType Name, class T = typename PrimConv<Name>:: | |||
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.checkingPotentia | if (!S.checkingPotentia | ||
@@ -2511,50 +2499,52 @@ inline bool DoShift(InterpSt | |||
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_l | |||
- if (!S.noteUndefinedBeh | |||
- 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), | + ComparisonCatego | ||
- LT::AsUnsigned::from(Bits - 1), Bits, &R); | + if (LHS.isNegative()) | ||
- else | + R = LT::AsUnsigned::zero(LHS.bitWidth()); | ||
+ else { | |||
+ RHS = RT::from(LHS.countLeadingZero | |||
+ 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); | + ComparisonCatego | ||
- 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 CheckNewTypeMism | |||
bool InvalidNewDelete | bool InvalidNewDelete | ||
template <PrimType Name, class T = typename PrimConv<Name>::T> | template <PrimType Name, class T = typename PrimConv<Name>::T> | ||
-inline bool | +inline bool BitCastPrim(InterpState &S, CodePtr OpPC, bool TargetIsUCharOrByte, | ||
- | + 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 HasIndeterminate | + 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 HasIndeterminate | |||
- 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>) { | ||
- HasIndeterminate | + assert(Sem); | ||
- return false; | + BitWidth = Bits(llvm::APFloatBase::getSizeInBits(*Sem)); | ||
+ } | |||
- if (!CheckBitCast(S, OpPC, HasIndeterminate | + if (!DoBitCast(S, OpPC, FromPtr, Buff.data(), BitWidth, FullBitWidth, | ||
- return false; | + HasIndeterminate | ||
+ return false; | |||
- if constexpr (std::is_same_v<T, Floating>) { | + if (!CheckBitCast(S, OpPC, HasIndeterminate | ||
- assert(Sem); | + return false; | ||
- S.Stk.push<Floating>(T::bitcastFromMemor | + | ||
- } else { | + if constexpr (std::is_same_v<T, Floating>) { | ||
- | + assert(Sem); | ||
- | + S.Stk.push<Floating>(T::bitcastFromMemory(Buff.data(), *Sem)); | ||
+ } else { | |||
+ assert(!Sem); | |||
+ S.Stk.push<T>(T::bitcastFromMemor | |||
+ } | |||
+ return true; | |||
} | } | ||
- return true; | |||
} | } | ||
-inline bool | +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>(); | ||
@@ -1917,7 +1917,8 @@ static bool interp__builtin_ | |||
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) | |||
diagnoseNonConst | diagnoseNonConst | ||
if (Size.isZero()) { | if (Size.isZero()) { | ||
@@ -1925,14 +1926,18 @@ static bool interp__builtin_ | |||
return true; | return true; | ||
} | } | ||
+ bool IsWide = | |||
+ (ID == Builtin::BIwmemcmp || ID == Builtin::BI__builtin_wmem | |||
+ | |||
+ 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()))) { | ||
S.FFDiag(S.Current->getSource(OpPC), | S.FFDiag(S.Current->getSource(OpPC), | ||
diag::note_constexpr_m | diag::note_constexpr_m | ||
- << ("'" + | + << ("'" + ASTCtx.BuiltinInfo.getName(ID) + "'").str() << PtrA.getType() | ||
- << | + << PtrB.getType(); | ||
return false; | return false; | ||
} | } | ||
@@ -1941,42 +1946,62 @@ static bool interp__builtin_ | |||
// 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( | + Bits(ASTCtx.getTypeSize(PtrA.getFieldDesc()->getType()))); | ||
readPointerToBuf | readPointerToBuf | ||
// 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 ( | + if (ASTCtx.getTargetInfo().isBigEndian()) | ||
swapBytes(BufferA.Data.get(), BufferA.byteSize().getQuantity()); | swapBytes(BufferA.Data.get(), BufferA.byteSize().getQuantity()); | ||
BitcastBuffer BufferB( | BitcastBuffer BufferB( | ||
- Bits( | + Bits(ASTCtx.getTypeSize(PtrB.getFieldDesc()->getType()))); | ||
readPointerToBuf | readPointerToBuf | ||
// 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 ( | + 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.getTypeSizeInCha | ||
- } 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 B = *reinterpret_cast | |||
+ 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 ( | + if (ByteSize <= CmpSize) { | ||
pushInteger(S, 0, Call->getType()); | pushInteger(S, 0, Call->getType()); | ||
return true; | return true; | ||
} | } | ||
@@ -2467,6 +2492,8 @@ bool InterpretBuiltin | |||
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_wmem | |||
+ case Builtin::BIwmemcmp: | |||
if (!interp__builtin_ | if (!interp__builtin_ | ||
return false; | return false; | ||
break; | break; |
@@ -839,13 +839,14 @@ def IsConstantContex | |||
def CheckAllocations | def CheckAllocations | ||
def BitCastTypeClass | def BitCastTypeClass | ||
- let Types = [Uint8, Sint8, Uint16, Sint16, Uint32, Sint32, Uint64, Sint64, | + let Types = [Uint8, Sint8, Uint16, Sint16, Uint32, Sint32, Uint64, Sint64, | ||
+ IntAP, IntAPS, Bool, Float, Ptr]; | |||
} | } | ||
-def | +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 | +def BitCast : Opcode; |
@@ -2990,6 +2990,9 @@ bool Expr::isUnusedRe | |||
case ExprWithCleanups | case ExprWithCleanups | ||
return cast<ExprWithCleanups | return cast<ExprWithCleanups | ||
->isUnusedResultAW | ->isUnusedResultAW | ||
+ case OpaqueValueExprC | |||
+ return cast<OpaqueValueExpr>(this)->getSourceExpr()->isUnusedResultAW | |||
+ WarnE, Loc, R1, R2, Ctx); | |||
} | } | ||
} | } | ||
@@ -32,7 +32,8 @@ bool OpenACCClauseWit | |||
return OpenACCPrivateCl | return OpenACCPrivateCl | ||
OpenACCFirstPriv | OpenACCFirstPriv | ||
OpenACCDevicePtr | OpenACCDevicePtr | ||
- | + OpenACCDeleteClause::classof(C) || | ||
+ OpenACCUseDevice | |||
OpenACCDetachCla | OpenACCDetachCla | ||
OpenACCNoCreateC | OpenACCNoCreateC | ||
OpenACCPresentCl | OpenACCPresentCl | ||
@@ -288,6 +289,26 @@ OpenACCDetachCla | |||
return new (Mem) OpenACCDetachCla | return new (Mem) OpenACCDetachCla | ||
} | } | ||
+OpenACCDeleteCla | |||
+ SourceLocation BeginLoc, | |||
+ SourceLocation LParenLoc, | |||
+ ArrayRef<Expr *> VarList, | |||
+ SourceLocation EndLoc) { | |||
+ void *Mem = | |||
+ C.Allocate(OpenACCDeleteCla | |||
+ return new (Mem) OpenACCDeleteCla | |||
+} | |||
+ | |||
+OpenACCUseDevice | |||
+ SourceLocation BeginLoc, | |||
+ SourceLocation LParenLoc, | |||
+ ArrayRef<Expr *> VarList, | |||
+ SourceLocation EndLoc) { | |||
+ void *Mem = C.Allocate( | |||
+ OpenACCUseDevice | |||
+ return new (Mem) OpenACCUseDevice | |||
+} | |||
+ | |||
OpenACCDevicePtr | OpenACCDevicePtr | ||
SourceLocation BeginLoc, | SourceLocation BeginLoc, | ||
SourceLocation LParenLoc, | SourceLocation LParenLoc, | ||
@@ -564,6 +585,21 @@ void OpenACCClausePri | |||
OS << ")"; | OS << ")"; | ||
} | } | ||
+void OpenACCClausePri | |||
+ OS << "delete("; | |||
+ llvm::interleaveComma(C.getVarList(), OS, | |||
+ [&](const Expr *E) { printExpr(E); }); | |||
+ OS << ")"; | |||
+} | |||
+ | |||
+void OpenACCClausePri | |||
+ const OpenACCUseDevice | |||
+ OS << "use_device("; | |||
+ llvm::interleaveComma(C.getVarList(), OS, | |||
+ [&](const Expr *E) { printExpr(E); }); | |||
+ OS << ")"; | |||
+} | |||
+ | |||
void OpenACCClausePri | void OpenACCClausePri | ||
const OpenACCDevicePtr | const OpenACCDevicePtr | ||
OS << "deviceptr("; | OS << "deviceptr("; |
@@ -2515,6 +2515,11 @@ public: | |||
} | } | ||
} | } | ||
+ void VisitClauseWithV | |||
+ 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 OpenACCClausePro | |||
} | } | ||
void OpenACCClausePro | void OpenACCClausePro | ||
- for (auto *E : Clause.getVarList()) | + VisitClauseWithV | ||
- Profiler.VisitStmt(E); | |||
} | } | ||
void OpenACCClausePro | void OpenACCClausePro | ||
const OpenACCCopyInCla | const OpenACCCopyInCla | ||
- for (auto *E : Clause.getVarList()) | + VisitClauseWithV | ||
- Profiler.VisitStmt(E); | |||
} | } | ||
void OpenACCClausePro | void OpenACCClausePro | ||
const OpenACCCopyOutCl | const OpenACCCopyOutCl | ||
- for (auto *E : Clause.getVarList()) | + VisitClauseWithV | ||
- Profiler.VisitStmt(E); | |||
} | } | ||
void OpenACCClausePro | void OpenACCClausePro | ||
const OpenACCCreateCla | const OpenACCCreateCla | ||
- for (auto *E : Clause.getVarList()) | + VisitClauseWithV | ||
- Profiler.VisitStmt(E); | |||
} | } | ||
void OpenACCClausePro | void OpenACCClausePro | ||
@@ -2589,44 +2590,47 @@ void OpenACCClausePro | |||
void OpenACCClausePro | void OpenACCClausePro | ||
const OpenACCPrivateCl | const OpenACCPrivateCl | ||
- for (auto *E : Clause.getVarList()) | + VisitClauseWithV | ||
- Profiler.VisitStmt(E); | |||
} | } | ||
void OpenACCClausePro | void OpenACCClausePro | ||
const OpenACCFirstPriv | const OpenACCFirstPriv | ||
- for (auto *E : Clause.getVarList()) | + VisitClauseWithV | ||
- Profiler.VisitStmt(E); | |||
} | } | ||
void OpenACCClausePro | void OpenACCClausePro | ||
const OpenACCAttachCla | const OpenACCAttachCla | ||
- for (auto *E : Clause.getVarList()) | + VisitClauseWithV | ||
- Profiler.VisitStmt(E); | |||
} | } | ||
void OpenACCClausePro | void OpenACCClausePro | ||
const OpenACCDetachCla | const OpenACCDetachCla | ||
- for (auto *E : Clause.getVarList()) | + VisitClauseWithV | ||
- Profiler.VisitStmt(E); | +} | ||
+ | |||
+void OpenACCClausePro | |||
+ const OpenACCDeleteCla | |||
+ VisitClauseWithV | |||
} | } | ||
void OpenACCClausePro | void OpenACCClausePro | ||
const OpenACCDevicePtr | const OpenACCDevicePtr | ||
- for (auto *E : Clause.getVarList()) | + VisitClauseWithV | ||
- Profiler.VisitStmt(E); | |||
} | } | ||
void OpenACCClausePro | void OpenACCClausePro | ||
const OpenACCNoCreateC | const OpenACCNoCreateC | ||
- for (auto *E : Clause.getVarList()) | + VisitClauseWithV | ||
- Profiler.VisitStmt(E); | |||
} | } | ||
void OpenACCClausePro | void OpenACCClausePro | ||
const OpenACCPresentCl | const OpenACCPresentCl | ||
- for (auto *E : Clause.getVarList()) | + VisitClauseWithV | ||
- Profiler.VisitStmt(E); | +} | ||
+ | |||
+void OpenACCClausePro | |||
+ const OpenACCUseDevice | |||
+ VisitClauseWithV | |||
} | } | ||
void OpenACCClausePro | void OpenACCClausePro | ||
@@ -2678,8 +2682,7 @@ void OpenACCClausePro | |||
void OpenACCClausePro | void OpenACCClausePro | ||
const OpenACCReduction | const OpenACCReduction | ||
- for (auto *E : Clause.getVarList()) | + VisitClauseWithV | ||
- Profiler.VisitStmt(E); | |||
} | } | ||
} // namespace | } // namespace | ||
@@ -412,6 +412,7 @@ void TextNodeDumper:: | |||
case OpenACCClauseKin | case OpenACCClauseKin | ||
case OpenACCClauseKin | case OpenACCClauseKin | ||
case OpenACCClauseKin | case OpenACCClauseKin | ||
+ case OpenACCClauseKin | |||
case OpenACCClauseKin | case OpenACCClauseKin | ||
case OpenACCClauseKin | case OpenACCClauseKin | ||
case OpenACCClauseKin | case OpenACCClauseKin | ||
@@ -424,6 +425,7 @@ void TextNodeDumper:: | |||
case OpenACCClauseKin | case OpenACCClauseKin | ||
case OpenACCClauseKin | case OpenACCClauseKin | ||
case OpenACCClauseKin | case OpenACCClauseKin | ||
+ case OpenACCClauseKin | |||
case OpenACCClauseKin | case OpenACCClauseKin | ||
case OpenACCClauseKin | case OpenACCClauseKin | ||
// The condition expression will be printed as a part of the 'children', | // The condition expression will be printed as a part of the 'children', |
@@ -77,6 +77,7 @@ | |||
#include "llvm/Transforms/Instrumentation/SanitizerBinaryM | #include "llvm/Transforms/Instrumentation/SanitizerBinaryM | ||
#include "llvm/Transforms/Instrumentation/SanitizerCoverag | #include "llvm/Transforms/Instrumentation/SanitizerCoverag | ||
#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(co | |||
MPM.addPass(createModuleToFu | MPM.addPass(createModuleToFu | ||
} | } | ||
+ if (LangOpts.Sanitize.has(SanitizerKind::Type)) { | |||
+ MPM.addPass(ModuleTypeSaniti | |||
+ MPM.addPass(createModuleToFu | |||
+ } | |||
+ | |||
if (LangOpts.Sanitize.has(SanitizerKind::NumericalStabili | if (LangOpts.Sanitize.has(SanitizerKind::NumericalStabili | ||
MPM.addPass(NumericalStabili | MPM.addPass(NumericalStabili | ||
@@ -19436,6 +19436,15 @@ case Builtin::BI__bui | |||
/*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 | |||
+ Value *Op = EmitScalarExpr(E->getArg(0)); | |||
+ assert(Op->getType()->isIntegerTy(1) && | |||
+ "Intrinsic WaveActiveAllTru | |||
+ | |||
+ Intrinsic::ID ID = CGM.getHLSLRuntime().getWaveActiveAll | |||
+ return EmitRuntimeCall( | |||
+ Intrinsic::getOrInsertDecla | |||
+ } | |||
case Builtin::BI__builtin_hlsl | case Builtin::BI__builtin_hlsl | ||
Value *Op = EmitScalarExpr(E->getArg(0)); | Value *Op = EmitScalarExpr(E->getArg(0)); | ||
assert(Op->getType()->isIntegerTy(1) && | assert(Op->getType()->isIntegerTy(1) && |
@@ -2021,28 +2021,10 @@ llvm::DISubrouti | |||
// 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->getPointeeCXXRec | + llvm::DIType *ThisPtrType = getOrCreateType(ThisPtr, Unit); | ||
- if (isa<ClassTemplateSpe | + TypeCache[ThisPtr.getAsOpaquePtr()].reset(ThisPtrType); | ||
- // Create pointer type directly in this case. | + ThisPtrType = DBuilder.createObjectPoin | ||
- const PointerType *ThisPtrTy = cast<PointerType>(ThisPtr); | + Elts.push_back(ThisPtrType); | ||
- uint64_t Size = CGM.getContext().getTypeSize(ThisPtrTy); | |||
- auto Align = getTypeAlignIfRe | |||
- llvm::DIType *PointeeType = | |||
- getOrCreateType(ThisPtrTy->getPointeeType(), Unit); | |||
- llvm::DIType *ThisPtrType = | |||
- DBuilder.createPointerTyp | |||
- 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.createObjectPoin | |||
- Elts.push_back(ThisPtrType); | |||
- } else { | |||
- llvm::DIType *ThisPtrType = getOrCreateType(ThisPtr, Unit); | |||
- TypeCache[ThisPtr.getAsOpaquePtr()].reset(ThisPtrType); | |||
- ThisPtrType = DBuilder.createObjectPoin | |||
- Elts.push_back(ThisPtrType); | |||
- } | |||
} | } | ||
// Copy rest of the arguments. | // Copy rest of the arguments. | ||
@@ -2995,20 +2977,21 @@ llvm::DIType *CGDebugInfo::Cr | |||
if (!ID) | if (!ID) | ||
return nullptr; | return nullptr; | ||
+ auto RuntimeLang = | |||
+ static_cast<llvm::dwarf::SourceLanguage>(TheCU->getSourceLanguag | |||
+ | |||
// 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 | if (DebugTypeExtRefs | ||
!ID->getImplementatio | !ID->getImplementatio | ||
- return DBuilder.createForwardDecl( | + return DBuilder.createForwardDecl( | ||
- ID->getName(), | + llvm::dwarf::DW_TAG_structure | ||
- getDeclContextDe | + getDeclContextDe | ||
// 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->getSourceLanguag | |||
// 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. |
@@ -479,6 +479,10 @@ llvm::Function *CodeGenModule:: | |||
!isInNoSanitizeLi | !isInNoSanitizeLi | ||
Fn->addFnAttr(llvm::Attribute::SanitizeMemTag); | Fn->addFnAttr(llvm::Attribute::SanitizeMemTag); | ||
+ if (getLangOpts().Sanitize.has(SanitizerKind::Type) && | |||
+ !isInNoSanitizeLi | |||
+ Fn->addFnAttr(llvm::Attribute::SanitizeType); | |||
+ | |||
if (getLangOpts().Sanitize.has(SanitizerKind::Thread) && | if (getLangOpts().Sanitize.has(SanitizerKind::Thread) && | ||
!isInNoSanitizeLi | !isInNoSanitizeLi | ||
Fn->addFnAttr(llvm::Attribute::SanitizeThread); | Fn->addFnAttr(llvm::Attribute::SanitizeThread); |
@@ -512,13 +512,17 @@ void CGHLSLRuntime::g | |||
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 |
@@ -92,6 +92,7 @@ public: | |||
GENERATE_HLSL_IN | GENERATE_HLSL_IN | ||
GENERATE_HLSL_IN | GENERATE_HLSL_IN | ||
GENERATE_HLSL_IN | GENERATE_HLSL_IN | ||
+ GENERATE_HLSL_IN | |||
GENERATE_HLSL_IN | GENERATE_HLSL_IN | ||
GENERATE_HLSL_IN | GENERATE_HLSL_IN | ||
GENERATE_HLSL_IN | GENERATE_HLSL_IN |
@@ -9042,337 +9042,69 @@ void CGOpenMPRuntime: | |||
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.getIntTypeForBit | |||
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.getTypeSizeInCha | CharUnits ElementSize = C.getTypeSizeInCha | ||
llvm::Type *ElemTy = CGM.getTypes().ConvertTypeForMe | llvm::Type *ElemTy = CGM.getTypes().ConvertTypeForMe | ||
- // Prepare mapper function arguments and attributes. | + CodeGenFunction MapperCGF(CGM); | ||
- ImplicitParamDec | + MappableExprsHan | ||
- C.VoidPtrTy, ImplicitParamKin | + auto PrivatizeAndGenM | ||
- ImplicitParamDec | + [&](llvm::OpenMPIRBuilder::InsertPointTy CodeGenIP, llvm::Value *PtrPHI, | ||
- ImplicitParamKin | + llvm::Value *BeginArg) -> llvm::OpenMPIRBuilder::MapInfosTy & { | ||
- ImplicitParamDec | + MapperCGF.Builder.restoreIP(CodeGenIP); | ||
- C.VoidPtrTy, ImplicitParamKin | + | ||
- ImplicitParamDec | + // Privatize the declared variable of mapper to be the current array | ||
- ImplicitParamKin | + // element. | ||
- ImplicitParamDec | + Address PtrCurrent( | ||
- ImplicitParamKin | + PtrPHI, ElemTy, | ||
- ImplicitParamDec | + Address(BeginArg, MapperCGF.VoidPtrTy, CGM.getPointerAlign()) | ||
- ImplicitParamKin | + .getAlignment() | ||
- FunctionArgList Args; | + .alignmentOfArray | ||
- 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); | + MappableExprsHan | ||
- const CGFunctionInfo &FnInfo = | + MEHandler.generateAllInfoF | ||
- CGM.getTypes().arrangeBuiltinFu | + | ||
- llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); | + auto FillInfoMap = [&](MappableExprsHan | ||
+ return emitMappingInfor | |||
+ }; | |||
+ 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 = getOrCreateUserD | |||
+ cast<OMPDeclareMapper | |||
+ assert(*MapperFunc && "Expect a valid mapper function is available."); | |||
+ return true; | |||
+ } | |||
+ return false; | |||
+ }; | |||
+ | |||
SmallString<64> TyStr; | SmallString<64> TyStr; | ||
llvm::raw_svector_ostr | llvm::raw_svector_ostr | ||
CGM.getCXXABI().getMangleContext | CGM.getCXXABI().getMangleContext | ||
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.SetInternalFunct | |||
- 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.GetAddrOfLocalVa | |||
- C.getPointerType(Int64Ty), Loc); | |||
- // Prepare common arguments for array initiation and deletion. | |||
- llvm::Value *Handle = MapperCGF.EmitLoadOfScalar | |||
- MapperCGF.GetAddrOfLocalVa | |||
- /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); | |||
- llvm::Value *BaseIn = MapperCGF.EmitLoadOfScalar | |||
- MapperCGF.GetAddrOfLocalVa | |||
- /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); | |||
- llvm::Value *BeginIn = MapperCGF.EmitLoadOfScalar | |||
- MapperCGF.GetAddrOfLocalVa | |||
- /*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().ConvertTypeForMe | |||
- llvm::Value *PtrEnd = MapperCGF.Builder.CreateGEP(ElemTy, PtrBegin, Size); | |||
- llvm::Value *MapType = MapperCGF.EmitLoadOfScalar | |||
- MapperCGF.GetAddrOfLocalVa | |||
- C.getPointerType(Int64Ty), Loc); | |||
- llvm::Value *MapName = MapperCGF.EmitLoadOfScalar | |||
- MapperCGF.GetAddrOfLocalVa | |||
- /*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 | |||
- emitUDMapperArra | |||
- 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 | |||
- llvm::BasicBlock *DoneBB = MapperCGF.createBasicBlock | |||
- // 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.GetAddrOfLocalVa | |||
- .getAlignment() | |||
- .alignmentOfArray | |||
- // 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.emitUserDefinedM | ||
- MappableExprsHan | + ElemTy, Name, CustomMapperCB); | ||
- MappableExprsHan | + UDMMap.try_emplace(D, NewFn); | ||
- MEHandler.generateAllInfoF | |||
- | |||
- // Call the runtime API __tgt_mapper_num | |||
- // pre-existing components. | |||
- llvm::Value *OffloadingArgs[] = {Handle}; | |||
- llvm::Value *PreviousSize = MapperCGF.EmitRuntimeCall( | |||
- OMPBuilder.getOrCreateRunti | |||
- OMPRTL___tgt_map | |||
- OffloadingArgs); | |||
- llvm::Value *ShiftedPreviousS | |||
- PreviousSize, | |||
- MapperCGF.Builder.getInt64(MappableExprsHan | |||
- | |||
- // 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().ConvertTypeForMe | |||
- llvm::Value *CurBeginArg = MapperCGF.Builder.CreateBitCast( | |||
- Info.Pointers[I], CGM.getTypes().ConvertTypeForMe | |||
- llvm::Value *CurSizeArg = Info.Sizes[I]; | |||
- llvm::Value *CurNameArg = | |||
- (CGM.getCodeGenOpts().getDebugInfo() == | |||
- llvm::codegenoptions::NoDebugInfo) | |||
- ? llvm::ConstantPointerN | |||
- : emitMappingInfor | |||
- | |||
- // Extract the MEMBER_OF field from the map type. | |||
- llvm::Value *OriMapType = MapperCGF.Builder.getInt64( | |||
- static_cast<std::underlying_type_ | |||
- Info.Types[I])); | |||
- llvm::Value *MemberMapType = | |||
- MapperCGF.Builder.CreateNUWAdd(OriMapType, ShiftedPreviousS | |||
- | |||
- // 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_ | |||
- OpenMPOffloadMap | |||
- OpenMPOffloadMap | |||
- llvm::BasicBlock *AllocBB = MapperCGF.createBasicBlock | |||
- llvm::BasicBlock *AllocElseBB = | |||
- MapperCGF.createBasicBlock | |||
- llvm::BasicBlock *ToBB = MapperCGF.createBasicBlock | |||
- llvm::BasicBlock *ToElseBB = MapperCGF.createBasicBlock | |||
- llvm::BasicBlock *FromBB = MapperCGF.createBasicBlock | |||
- llvm::BasicBlock *EndBB = MapperCGF.createBasicBlock | |||
- 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_ | |||
- OpenMPOffloadMap | |||
- OpenMPOffloadMap | |||
- MapperCGF.Builder.CreateBr(EndBB); | |||
- MapperCGF.EmitBlock(AllocElseBB); | |||
- llvm::Value *IsTo = MapperCGF.Builder.CreateICmpEQ( | |||
- LeftToFrom, | |||
- MapperCGF.Builder.getInt64( | |||
- static_cast<std::underlying_type_ | |||
- OpenMPOffloadMap | |||
- 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_ | |||
- OpenMPOffloadMap | |||
- MapperCGF.Builder.CreateBr(EndBB); | |||
- MapperCGF.EmitBlock(ToElseBB); | |||
- llvm::Value *IsFrom = MapperCGF.Builder.CreateICmpEQ( | |||
- LeftToFrom, | |||
- MapperCGF.Builder.getInt64( | |||
- static_cast<std::underlying_type_ | |||
- OpenMPOffloadMap | |||
- 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_ | |||
- OpenMPOffloadMap | |||
- // 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 = getOrCreateUserD | |||
- cast<OMPDeclareMapper | |||
- assert(MapperFunc && "Expect a valid mapper function is available."); | |||
- MapperCGF.EmitNounwindRunt | |||
- } else { | |||
- // Call the runtime API __tgt_push_mappe | |||
- // data structure. | |||
- MapperCGF.EmitRuntimeCall( | |||
- OMPBuilder.getOrCreateRunti | |||
- CGM.getModule(), OMPRTL___tgt_pus | |||
- 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_ | |||
- 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 | |||
- 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. | |||
- emitUDMapperArra | |||
- 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::emitUDMapperArra | |||
- 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 | |||
- 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_ | |||
- OpenMPOffloadMap | |||
- 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_ | |||
- OpenMPOffloadMap | |||
- 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_ | |||
- OpenMPOffloadMap | |||
- OpenMPOffloadMap | |||
- MapTypeArg = MapperCGF.Builder.CreateOr( | |||
- MapTypeArg, | |||
- MapperCGF.Builder.getInt64( | |||
- static_cast<std::underlying_type_ | |||
- OpenMPOffloadMap | |||
- | |||
- // Call the runtime API __tgt_push_mappe | |||
- // data structure. | |||
- llvm::Value *OffloadingArgs[] = {Handle, Base, Begin, | |||
- ArraySize, MapTypeArg, MapName}; | |||
- MapperCGF.EmitRuntimeCall( | |||
- OMPBuilder.getOrCreateRunti | |||
- OMPRTL___tgt_pus | |||
- OffloadingArgs); | |||
-} | |||
- | |||
llvm::Function *CGOpenMPRuntime::getOrCreateUserD | llvm::Function *CGOpenMPRuntime::getOrCreateUserD | ||
const OMPDeclareMapper | const OMPDeclareMapper | ||
auto I = UDMMap.find(D); | auto I = UDMMap.find(D); |
@@ -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 emitUDMapperArra | |||
- 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; |
@@ -837,6 +837,8 @@ void CodeGenFunction: | |||
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::NumericalStabili | if (SanOpts.has(SanitizerKind::NumericalStabili | ||
Fn->addFnAttr(llvm::Attribute::SanitizeNumerica | Fn->addFnAttr(llvm::Attribute::SanitizeNumerica | ||
if (SanOpts.hasOneOf(SanitizerKind::Memory | SanitizerKind::KernelMemory)) | if (SanOpts.hasOneOf(SanitizerKind::Memory | SanitizerKind::KernelMemory)) |
@@ -397,8 +397,8 @@ CodeGenModule::C | |||
if (LangOpts.HLSL) | if (LangOpts.HLSL) | ||
createHLSLRuntim | createHLSLRuntim | ||
- // Enable TBAA unless it's suppressed. | + // Enable TBAA unless it's suppressed. TSan and TySan need TBAA even at O0. | ||
- if (LangOpts.Sanitize. | + if (LangOpts.Sanitize.hasOneOf(SanitizerKind::Thread | SanitizerKind::Type) || | ||
(!CodeGenOpts.RelaxedAliasing && CodeGenOpts.OptimizationLeve | (!CodeGenOpts.RelaxedAliasing && CodeGenOpts.OptimizationLeve | ||
TBAA.reset(new CodeGenTBAA(Context, getTypes(), TheModule, CodeGenOpts, | TBAA.reset(new CodeGenTBAA(Context, getTypes(), TheModule, CodeGenOpts, | ||
getLangOpts())); | getLangOpts())); | ||
@@ -1218,6 +1218,9 @@ void CodeGenModule::R | |||
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 = |
@@ -314,8 +314,10 @@ llvm::MDNode *CodeGenTBAA::ge | |||
} | } | ||
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.OptimizationLeve | + // we're running TypeSanitizer). | ||
+ if (!Features.Sanitize.has(SanitizerKind::Type) && | |||
+ (CodeGenOpts.OptimizationLeve | |||
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 |
@@ -2370,8 +2370,7 @@ static void dump(llvm::raw_o | |||
} else { | } else { | ||
Ctx.dump(R.Count, OS); | Ctx.dump(R.Count, OS); | ||
- if (R.Kind == CounterMappingRe | + if (R.isBranch()) { | ||
- R.Kind == CounterMappingRe | |||
OS << ", "; | OS << ", "; | ||
Ctx.dump(R.FalseCount, OS); | Ctx.dump(R.FalseCount, OS); | ||
} | } |
@@ -3302,6 +3302,7 @@ void ItaniumCXXABI::E | |||
CharUnits Align = CGM.getContext().getDeclAlign(VD); | CharUnits Align = CGM.getContext().getDeclAlign(VD); | ||
Val = Builder.CreateAlignedLoa | Val = Builder.CreateAlignedLoa | ||
} | } | ||
+ Val = Builder.CreateAddrSpaceC | |||
Builder.CreateRet(Val); | Builder.CreateRet(Val); | ||
} | } |
@@ -3454,7 +3454,7 @@ llvm::Value *MicrosoftCXXABI | |||
if (inheritanceModel | if (inheritanceModel | ||
Dst = FirstField; | Dst = FirstField; | ||
} else { | } else { | ||
- Dst = | + Dst = llvm::PoisonValue::get(ConvertMemberPointerType(DstTy)); | ||
unsigned Idx = 0; | unsigned Idx = 0; | ||
Dst = Builder.CreateInsertValu | Dst = Builder.CreateInsertValu | ||
if (inheritanceModel | if (inheritanceModel |
@@ -19,9 +19,10 @@ using namespace CodeGen; | |||
SanitizerMetadat | SanitizerMetadat | ||
-static bool | +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 expandKernelSani | static SanitizerMask expandKernelSani | ||
@@ -31,13 +32,44 @@ static SanitizerMask expandKernelSani | |||
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 SanitizerMetadat | void SanitizerMetadat | ||
SourceLocation Loc, StringRef Name, | SourceLocation Loc, StringRef Name, | ||
QualType Ty, | QualType Ty, | ||
SanitizerMask NoSanitizeAttrMa | SanitizerMask NoSanitizeAttrMa | ||
bool IsDynInit) { | bool IsDynInit) { | ||
SanitizerSet FsanitizeArgumen | SanitizerSet FsanitizeArgumen | ||
- if ( | + if (!isAsanHwasanMemTagOrTysan(FsanitizeArgument)) | ||
return; | return; | ||
FsanitizeArgumen | FsanitizeArgumen | ||
@@ -57,11 +89,15 @@ void SanitizerMetadat | |||
Meta.NoHWAddress |= CGM.isInNoSanitizeLi | Meta.NoHWAddress |= CGM.isInNoSanitizeLi | ||
FsanitizeArgumen | FsanitizeArgumen | ||
- Meta.Memtag |= | + if (shouldTagGlobal(*GV)) { | ||
- | + Meta.Memtag |= static_cast<bool>(FsanitizeArgument.Mask & | ||
- Meta.Memtag &= !NoSanitizeAttrSe | + SanitizerKind::MemtagGlobals); | ||
- Meta.Memtag &= !CGM.isInNoSanitizeLi | + Meta.Memtag &= !NoSanitizeAttrSe | ||
- FsanitizeArgumen | + Meta.Memtag &= !CGM.isInNoSanitizeLi | ||
+ FsanitizeArgumen | |||
+ } else { | |||
+ Meta.Memtag = false; | |||
+ } | |||
Meta.IsDynInit = IsDynInit && !Meta.NoAddress && | Meta.IsDynInit = IsDynInit && !Meta.NoAddress && | ||
FsanitizeArgumen | FsanitizeArgumen | ||
@@ -70,11 +106,32 @@ void SanitizerMetadat | |||
GV, Loc, Ty, "init"); | GV, Loc, Ty, "init"); | ||
GV->setSanitizerMeta | GV->setSanitizerMeta | ||
+ | |||
+ if (Ty.isNull() || !CGM.getLangOpts().Sanitize.has(SanitizerKind::Type) || | |||
+ NoSanitizeAttrMa | |||
+ return; | |||
+ | |||
+ llvm::MDNode *TBAAInfo = CGM.getTBAATypeInfo(Ty); | |||
+ if (!TBAAInfo || TBAAInfo == CGM.getTBAATypeInfo(CGM.getContext().CharTy)) | |||
+ return; | |||
+ | |||
+ llvm::Metadata *GlobalMetadata[] = {llvm::ConstantAsMetada | |||
+ 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().getOrInsertNamed | |||
+ TysanGlobals->addOperand(ThisGlobal); | |||
} | } | ||
void SanitizerMetadat | void SanitizerMetadat | ||
bool IsDynInit) { | bool IsDynInit) { | ||
- if ( | + if (!isAsanHwasanMemTagOrTysan(CGM.getLangOpts().Sanitize)) | ||
return; | return; | ||
std::string QualName; | std::string QualName; | ||
llvm::raw_string_ostre | llvm::raw_string_ostre |
@@ -37,15 +37,15 @@ static const SanitizerMask NotAllowedWithMi | |||
static const SanitizerMask NotAllowedWithEx | static const SanitizerMask NotAllowedWithEx | ||
SanitizerKind::Function | SanitizerKind::KCFI; | SanitizerKind::Function | SanitizerKind::KCFI; | ||
static const SanitizerMask NeedsUnwindTable | static const SanitizerMask NeedsUnwindTable | ||
- SanitizerKind::Address | SanitizerKind::HWAddress | | + SanitizerKind::Address | SanitizerKind::HWAddress | SanitizerKind::Type | | ||
- SanitizerKind::Memory | SanitizerKind::DataFlow | | + SanitizerKind::Thread | SanitizerKind::Memory | SanitizerKind::DataFlow | | ||
SanitizerKind::NumericalStabili | SanitizerKind::NumericalStabili | ||
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::Type | SanitizerKind::MemtagStack | | ||
- | + 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::ImplicitConversi | SanitizerKind::ImplicitConversi | ||
SanitizerKind::DataFlow | SanitizerKind::Fuzzer | | SanitizerKind::DataFlow | SanitizerKind::Fuzzer | | ||
@@ -182,6 +182,7 @@ static void addDefaultIgnore | |||
{"msan_ignorelist.txt", SanitizerKind::Memory}, | {"msan_ignorelist.txt", SanitizerKind::Memory}, | ||
{"nsan_ignorelist.txt", SanitizerKind::NumericalStabili | {"nsan_ignorelist.txt", SanitizerKind::NumericalStabili | ||
{"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 | {"ubsan_ignorelist | ||
@@ -247,48 +248,76 @@ static SanitizerMask setGroupBits(San | |||
return Kinds; | return Kinds; | ||
} | } | ||
-// Computes the sanitizer mask | +// 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 | ||
parseSanitizeArg | parseSanitizeArg | ||
- bool DiagnoseErrors, SanitizerMask | + bool DiagnoseErrors, SanitizerMask Default, | ||
- SanitizerMask | + 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. | + "parseSanitizeArg | ||
- SanitizerMask Kinds; | + | ||
- SanitizerMask | + 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 DiagnosedAlwaysI | |||
+ SanitizerMask DiagnosedAlwaysO | |||
+ 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 & ~SupportedWithGro | + if (SanitizerMask KindsToDiagnose = | ||
- if (InvalidValues && DiagnoseErrors) { | + Add & AlwaysOut & ~DiagnosedAlwaysO | ||
- SanitizerSet S; | + if (DiagnoseErrors) { | ||
- S.Mask = InvalidValues; | + SanitizerSet SetToDiagnose; | ||
- D.Diag(diag::err_drv_unsuppor | + SetToDiagnose.Mask |= KindsToDiagnose; | ||
- << Arg->getSpelling() << toString(S); | + D.Diag(diag::err_drv_unsuppor | ||
+ << Arg->getSpelling() << toString(SetToDiagnose); | |||
+ DiagnosedAlwaysO | |||
+ } | |||
} | } | ||
- | + 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 & ~DiagnosedAlwaysI | |||
+ if (DiagnoseErrors) { | |||
+ SanitizerSet SetToDiagnose; | |||
+ SetToDiagnose.Mask |= KindsToDiagnose; | |||
+ D.Diag(diag::err_drv_unsuppor | |||
+ << Arg->getSpelling() << toString(SetToDiagnose); | |||
+ DiagnosedAlwaysI | |||
+ } | |||
+ } | |||
+ Output &= ~expandSanitizerG | |||
Arg->claim(); | Arg->claim(); | ||
- Remove |= expandSanitizerG | |||
} | } | ||
} | } | ||
- // Apply default behavior. | + return Output; | ||
- Kinds |= Default & ~Remove; | |||
- | |||
- return Kinds; | |||
} | } | ||
static SanitizerMask parseSanitizeTra | static SanitizerMask parseSanitizeTra | ||
const llvm::opt::ArgList &Args, | const llvm::opt::ArgList &Args, | ||
bool DiagnoseErrors) { | bool DiagnoseErrors) { | ||
- return parseSanitizeArg | + SanitizerMask AlwaysTrap; // Empty | ||
- TrappingDefault, | + SanitizerMask NeverTrap = ~(setGroupBits(TrappingSupporte | ||
+ | |||
+ // 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 parseSanitizeArg | |||
+ NeverTrap, options::OPT_fsanitize_tr | |||
options::OPT_fno_sanitize | options::OPT_fno_sanitize | ||
} | } | ||
@@ -542,6 +571,10 @@ SanitizerArgs::S | |||
std::pair<SanitizerMask, SanitizerMask> IncompatibleGrou | std::pair<SanitizerMask, SanitizerMask> IncompatibleGrou | ||
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::S | |||
// default in ASan? | // default in ASan? | ||
// Parse -f(no-)?sanitize-recover flags. | // Parse -f(no-)?sanitize-recover flags. | ||
- SanitizerMask RecoverableKinds = | + SanitizerMask RecoverableKinds = parseSanitizeArgs( | ||
- SanitizerMask DiagnosedUnrecov | + D, Args, DiagnoseErrors, RecoverableByDef | ||
- SanitizerMask DiagnosedAlwaysR | + Unrecoverable, options::OPT_fsanitize_re | ||
- for (const auto *Arg : Args) { | + options::OPT_fno_sanitize | ||
- if (Arg->getOption().matches(options::OPT_fsanitize_re | + RecoverableKinds | ||
- SanitizerMask Add = parseArgValues(D, Arg, DiagnoseErrors); | |||
- // Report error if user explicitly tries to recover from unrecoverable | |||
- // sanitizer. | |||
- if (SanitizerMask KindsToDiagnose = | |||
- Add & Unrecoverable & ~DiagnosedUnrecov | |||
- SanitizerSet SetToDiagnose; | |||
- SetToDiagnose.Mask |= KindsToDiagnose; | |||
- if (DiagnoseErrors) | |||
- D.Diag(diag::err_drv_unsuppor | |||
- << Arg->getSpelling() << toString(SetToDiagnose); | |||
- DiagnosedUnrecov | |||
- } | |||
- RecoverableKinds | |||
- Arg->claim(); | |||
- } else if (Arg->getOption().matches(options::OPT_fno_sanitize | |||
- SanitizerMask Remove = parseArgValues(D, Arg, DiagnoseErrors); | |||
- // Report error if user explicitly tries to disable recovery from | |||
- // always recoverable sanitizer. | |||
- if (SanitizerMask KindsToDiagnose = | |||
- Remove & AlwaysRecoverabl | |||
- SanitizerSet SetToDiagnose; | |||
- SetToDiagnose.Mask |= KindsToDiagnose; | |||
- if (DiagnoseErrors) | |||
- D.Diag(diag::err_drv_unsuppor | |||
- << Arg->getSpelling() << toString(SetToDiagnose); | |||
- DiagnosedAlwaysR | |||
- } | |||
- RecoverableKinds | |||
- Arg->claim(); | |||
- } | |||
- } | |||
- RecoverableKinds | |||
RecoverableKinds | RecoverableKinds | ||
+ RecoverableKinds | |||
TrappingKinds &= Kinds; | TrappingKinds &= Kinds; | ||
RecoverableKinds | RecoverableKinds | ||
@@ -1096,10 +1098,11 @@ SanitizerArgs::S | |||
options::OPT_fno_sanitize | options::OPT_fno_sanitize | ||
// Parse -link-cxx-sanitizer flag. | // Parse -link-cxx-sanitizer flag. | ||
- LinkCXXRuntimes = | + LinkCXXRuntimes = | ||
- options::OPT_fno_sanitize | + D.CCCIsCXX() && !Args.hasArg(clang::driver::options::OPT_nostdlibxx); | ||
- LinkCXXRuntimes) || | + LinkCXXRuntimes = | ||
- D.CCCIsCXX(); | + Args.hasFlag(options::OPT_fsanitize_li | ||
+ options::OPT_fno_sanitize | |||
NeedsMemProfRt = Args.hasFlag(options::OPT_fmemory_prof | NeedsMemProfRt = Args.hasFlag(options::OPT_fmemory_prof | ||
options::OPT_fmemory_prof | options::OPT_fmemory_prof |
@@ -1417,7 +1417,6 @@ void tools::addAsNeed | |||
void tools::linkSanitizerRun | void tools::linkSanitizerRun | ||
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::linkSanit | |||
// 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() | + !TC.getTriple().isMusl()) | ||
CmdArgs.push_back("-lresolv"); | CmdArgs.push_back("-lresolv"); | ||
} | } | ||
static void | static void | ||
collectSanitizer | collectSanitizer | ||
- const SanitizerArgs &SanArgs, | |||
SmallVectorImpl<StringRef> &SharedRuntimes, | SmallVectorImpl<StringRef> &SharedRuntimes, | ||
SmallVectorImpl<StringRef> &StaticRuntimes, | SmallVectorImpl<StringRef> &StaticRuntimes, | ||
SmallVectorImpl<StringRef> &NonWholeStaticRu | SmallVectorImpl<StringRef> &NonWholeStaticRu | ||
SmallVectorImpl<StringRef> &HelperStaticRunt | SmallVectorImpl<StringRef> &HelperStaticRunt | ||
SmallVectorImpl<StringRef> &RequiredSymbols) { | SmallVectorImpl<StringRef> &RequiredSymbols) { | ||
+ const SanitizerArgs &SanArgs = TC.getSanitizerArgs | |||
// Collect shared runtimes. | // Collect shared runtimes. | ||
if (SanArgs.needsSharedRt()) { | if (SanArgs.needsSharedRt()) { | ||
if (SanArgs.needsAsanRt()) { | if (SanArgs.needsAsanRt()) { | ||
@@ -1481,6 +1480,8 @@ collectSanitizer | |||
} | } | ||
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.needsHwasanAlias | if (SanArgs.needsHwasanAlias | ||
SharedRuntimes.push_back("hwasan_aliases"); | SharedRuntimes.push_back("hwasan_aliases"); | ||
@@ -1553,6 +1554,8 @@ collectSanitizer | |||
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.requiresMinimalR | if (SanArgs.requiresMinimalR | ||
StaticRuntimes.push_back("ubsan_minimal"); | StaticRuntimes.push_back("ubsan_minimal"); | ||
@@ -1589,12 +1592,12 @@ collectSanitizer | |||
// 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::addSanitizerRunt | bool tools::addSanitizerRunt | ||
- const SanitizerArgs &SanArgs, | |||
ArgStringList &CmdArgs) { | ArgStringList &CmdArgs) { | ||
+ const SanitizerArgs &SanArgs = TC.getSanitizerArgs | |||
SmallVector<StringRef, 4> SharedRuntimes, StaticRuntimes, | SmallVector<StringRef, 4> SharedRuntimes, StaticRuntimes, | ||
NonWholeStaticRu | NonWholeStaticRu | ||
if (SanArgs.linkRuntimes()) { | if (SanArgs.linkRuntimes()) { | ||
- collectSanitizerRuntimes(TC, Args, | + collectSanitizerRuntimes(TC, Args, SharedRuntimes, StaticRuntimes, | ||
NonWholeStaticRu | NonWholeStaticRu | ||
RequiredSymbols); | RequiredSymbols); | ||
} | } |
@@ -38,12 +38,10 @@ void addLinkerCompres | |||
void claimNoWarnArgs(const llvm::opt::ArgList &Args); | void claimNoWarnArgs(const llvm::opt::ArgList &Args); | ||
bool addSanitizerRunt | bool addSanitizerRunt | ||
- const SanitizerArgs &SanArgs, | |||
llvm::opt::ArgStringList &CmdArgs); | llvm::opt::ArgStringList &CmdArgs); | ||
void linkSanitizerRun | void linkSanitizerRun | ||
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, |
@@ -1600,6 +1600,8 @@ void DarwinClang::Add | |||
"Static sanitizer runtimes not supported"); | "Static sanitizer runtimes not supported"); | ||
AddLinkSanitizer | AddLinkSanitizer | ||
} | } | ||
+ if (Sanitize.needsTysanRt()) | |||
+ AddLinkSanitizer | |||
if (Sanitize.needsFuzzer() && !Args.hasArg(options::OPT_dynamiclib)) { | if (Sanitize.needsFuzzer() && !Args.hasArg(options::OPT_dynamiclib)) { | ||
AddLinkSanitizer | AddLinkSanitizer | ||
@@ -3603,6 +3605,10 @@ SanitizerMask Darwin::getSuppo | |||
Res |= SanitizerKind::Thread; | Res |= SanitizerKind::Thread; | ||
} | } | ||
+ if ((IsX86_64 || IsAArch64) && isTargetMacOSBas | |||
+ Res |= SanitizerKind::Type; | |||
+ } | |||
+ | |||
if (IsX86_64) | if (IsX86_64) | ||
Res |= SanitizerKind::NumericalStabili | Res |= SanitizerKind::NumericalStabili | ||
@@ -55,7 +55,9 @@ void Flang::addFortra | |||
options::OPT_fdefault_dou | options::OPT_fdefault_dou | ||
options::OPT_flarge_sizes | options::OPT_flarge_sizes | ||
options::OPT_fno_automati | options::OPT_fno_automati | ||
- options::OPT_fhermetic_module_files | + options::OPT_fhermetic_module_files, | ||
+ options::OPT_frealloc_lhs | |||
+ options::OPT_fno_realloc_ | |||
} | } | ||
void Flang::addPreprocessing | void Flang::addPreprocessing | ||
@@ -120,7 +122,8 @@ void Flang::addOtherO | |||
options::OPT_fintrinsic_m | options::OPT_fintrinsic_m | ||
options::OPT_std_EQ, options::OPT_W_Joined, | options::OPT_std_EQ, options::OPT_W_Joined, | ||
options::OPT_fconvert_EQ, | options::OPT_fconvert_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)) { |
@@ -297,9 +297,7 @@ void freebsd::Linker: | |||
D.getLTOMode() == LTOK_Thin); | D.getLTOMode() == LTOK_Thin); | ||
} | } | ||
- const SanitizerArgs &SanArgs = ToolChain.getSanitizerArgs | + bool NeedsSanitizerDe | ||
- bool NeedsSanitizerDe | |||
- addSanitizerRunt | |||
bool NeedsXRayDeps = addXRayRuntime(ToolChain, Args, CmdArgs); | bool NeedsXRayDeps = addXRayRuntime(ToolChain, Args, CmdArgs); | ||
addLinkerCompres | addLinkerCompres | ||
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA); | AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA); | ||
@@ -340,7 +338,7 @@ void freebsd::Linker: | |||
} | } | ||
if (NeedsSanitizerDe | if (NeedsSanitizerDe | ||
- linkSanitizerRuntimeDeps(ToolChain, Args, | + linkSanitizerRuntimeDeps(ToolChain, Args, CmdArgs); | ||
if (NeedsXRayDeps) | if (NeedsXRayDeps) | ||
linkXRayRuntimeD | linkXRayRuntimeD | ||
// FIXME: For some reason GCC passes -lgcc and -lgcc_s before adding | // FIXME: For some reason GCC passes -lgcc and -lgcc_s before adding |
@@ -184,8 +184,7 @@ void fuchsia::Linker: | |||
// 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 | + addSanitizerRunt | ||
- addSanitizerRunt | |||
addXRayRuntime(ToolChain, Args, CmdArgs); | addXRayRuntime(ToolChain, Args, CmdArgs); | ||
@@ -318,9 +317,10 @@ Fuchsia::Fuchsia | |||
Args.hasFlag(options::OPT_fexceptions, | Args.hasFlag(options::OPT_fexceptions, | ||
addMultilibFlag(Exceptions, "-fexceptions", Flags); | addMultilibFlag(Exceptions, "-fexceptions", Flags); | ||
addMultilibFlag(!Exceptions, "-fno-exceptions", Flags); | addMultilibFlag(!Exceptions, "-fno-exceptions", Flags); | ||
- const SanitizerArgs &SanArgs = getSanitizerArgs | + addMultilibFlag(getSanitizerArgs | ||
- addMultilibFlag(SanArgs.needsAsanRt(), "-fsanitize=address", Flags); | + Flags); | ||
- addMultilibFlag( | + 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); |
@@ -23,7 +23,6 @@ | |||
#include "clang/Driver/DriverDiagnostic | #include "clang/Driver/DriverDiagnostic | ||
#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: | |||
if (Args.hasArg(options::OPT_Z_Xlinker__n | if (Args.hasArg(options::OPT_Z_Xlinker__n | ||
CmdArgs.push_back("--no-demangle"); | CmdArgs.push_back("--no-demangle"); | ||
- const SanitizerArgs &SanArgs = ToolChain.getSanitizerArgs | + bool NeedsSanitizerDe | ||
- bool NeedsSanitizerDe | |||
- addSanitizerRunt | |||
bool NeedsXRayDeps = addXRayRuntime(ToolChain, Args, CmdArgs); | bool NeedsXRayDeps = addXRayRuntime(ToolChain, Args, CmdArgs); | ||
addLinkerCompres | addLinkerCompres | ||
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA); | AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA); | ||
@@ -586,7 +583,7 @@ void tools::gnutools: | |||
CmdArgs.push_back("--start-group"); | CmdArgs.push_back("--start-group"); | ||
if (NeedsSanitizerDe | if (NeedsSanitizerDe | ||
- linkSanitizerRuntimeDeps(ToolChain, Args, | + linkSanitizerRuntimeDeps(ToolChain, Args, CmdArgs); | ||
if (NeedsXRayDeps) | if (NeedsXRayDeps) | ||
linkXRayRuntimeD | linkXRayRuntimeD |
@@ -13,7 +13,6 @@ | |||
#include "clang/Driver/DriverDiagnostic | #include "clang/Driver/DriverDiagnostic | ||
#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::Assembl | |||
"-mcpu=hexagon" + | "-mcpu=hexagon" + | ||
toolchains::HexagonToolChain | toolchains::HexagonToolChain | ||
- SanitizerArgs SanArgs = HTC.getSanitizerArgs | + addSanitizerRunt | ||
- addSanitizerRunt | |||
assert((Output.isFilename() || Output.isNothing()) && "Invalid output."); | assert((Output.isFilename() || Output.isNothing()) && "Invalid output."); | ||
if (Output.isFilename()) { | if (Output.isFilename()) { | ||
@@ -303,8 +301,7 @@ constructHexagon | |||
bool UseShared = IsShared && !IsStatic; | bool UseShared = IsShared && !IsStatic; | ||
StringRef CpuVer = toolchains::HexagonToolChain | StringRef CpuVer = toolchains::HexagonToolChain | ||
- | + bool NeedsSanitizerDeps = addSanitizerRuntimes(HTC, Args, CmdArgs); | ||
- bool NeedsSanitizerDe | |||
bool NeedsXRayDeps = addXRayRuntime(HTC, Args, CmdArgs); | bool NeedsXRayDeps = addXRayRuntime(HTC, Args, CmdArgs); | ||
//---------------------------------------------------------------------------- | //---------------------------------------------------------------------------- | ||
@@ -374,7 +371,7 @@ constructHexagon | |||
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlib | if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlib | ||
if (NeedsSanitizerDe | if (NeedsSanitizerDe | ||
- linkSanitizerRuntimeDeps(HTC, Args, | + linkSanitizerRuntimeDeps(HTC, Args, CmdArgs); | ||
if (UNW != ToolChain::UNW_None) | if (UNW != ToolChain::UNW_None) | ||
CmdArgs.push_back("-lunwind"); | CmdArgs.push_back("-lunwind"); |
@@ -837,6 +837,8 @@ SanitizerMask Linux::getSuppor | |||
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 || |
@@ -274,12 +274,11 @@ void netbsd::Linker:: | |||
options::OPT_s, options::OPT_t}); | options::OPT_s, options::OPT_t}); | ||
ToolChain.AddFilePathLibAr | ToolChain.AddFilePathLibAr | ||
- const SanitizerArgs &SanArgs = ToolChain.getSanitizerArgs | + bool NeedsSanitizerDe | ||
- bool NeedsSanitizerDe | |||
- addSanitizerRunt | |||
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 | |||
if (SanArgs.needsSharedRt()) { | if (SanArgs.needsSharedRt()) { | ||
CmdArgs.push_back("-rpath"); | CmdArgs.push_back("-rpath"); | ||
CmdArgs.push_back(Args.MakeArgString(ToolChain.getCompilerRTPat | CmdArgs.push_back(Args.MakeArgString(ToolChain.getCompilerRTPat | ||
@@ -335,7 +334,7 @@ void netbsd::Linker:: | |||
} | } | ||
if (NeedsSanitizerDe | if (NeedsSanitizerDe | ||
- linkSanitizerRuntimeDeps(ToolChain, Args, | + linkSanitizerRuntimeDeps(ToolChain, Args, CmdArgs); | ||
if (NeedsXRayDeps) | if (NeedsXRayDeps) | ||
linkXRayRuntimeD | linkXRayRuntimeD | ||
if (Args.hasArg(options::OPT_pthread)) | if (Args.hasArg(options::OPT_pthread)) |
@@ -213,9 +213,7 @@ void openbsd::Linker: | |||
D.getLTOMode() == LTOK_Thin); | D.getLTOMode() == LTOK_Thin); | ||
} | } | ||
- const SanitizerArgs &SanArgs = ToolChain.getSanitizerArgs | + bool NeedsSanitizerDe | ||
- bool NeedsSanitizerDe | |||
- addSanitizerRunt | |||
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: | |||
if (NeedsSanitizerDe | if (NeedsSanitizerDe | ||
CmdArgs.push_back(ToolChain.getCompilerRTArg | CmdArgs.push_back(ToolChain.getCompilerRTArg | ||
- linkSanitizerRuntimeDeps(ToolChain, Args, | + linkSanitizerRuntimeDeps(ToolChain, Args, CmdArgs); | ||
} | } | ||
if (NeedsXRayDeps) { | if (NeedsXRayDeps) { | ||
CmdArgs.push_back(ToolChain.getCompilerRTArg | CmdArgs.push_back(ToolChain.getCompilerRTArg |
@@ -203,8 +203,7 @@ void solaris::Linker: | |||
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 | + bool NeedsSanitizerDe | ||
- bool NeedsSanitizerDe | |||
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA); | AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA); | ||
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlib | if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlib | ||
@@ -251,8 +250,9 @@ void solaris::Linker: | |||
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 | |||
if (NeedsSanitizerDe | if (NeedsSanitizerDe | ||
- linkSanitizerRuntimeDeps(ToolChain, Args, | + 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 |
@@ -1067,9 +1067,8 @@ void SymbolGraphSeria | |||
for (auto &ExtensionSGF : Serializer.ExtendedModules) { | for (auto &ExtensionSGF : Serializer.ExtendedModules) { | ||
if (auto ExtensionOS = | if (auto ExtensionOS = | ||
- CreateOutputStream( | + 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())); | ||
} | } | ||
} | } |
@@ -826,8 +826,10 @@ void ContinuationInde | |||
for (const auto *Prev = &Tok; Prev; Prev = Prev->Previous) { | for (const auto *Prev = &Tok; Prev; Prev = Prev->Previous) { | ||
if (Prev->is(TT_TemplateStrin | if (Prev->is(TT_TemplateStrin | ||
return true; | return true; | ||
- if (Prev->is(TT_TemplateStrin | + if (Prev->opensScope() || | ||
+ (Prev->is(TT_TemplateStrin | |||
break; | break; | ||
+ } | |||
} | } | ||
return false; | return false; | ||
}; | }; |
@@ -4257,6 +4257,7 @@ bool CompilerInvocati | |||
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 || |
@@ -752,6 +752,7 @@ static void InitializeCPlusP | |||
Builder.defineMacro("__cpp_if_constev | Builder.defineMacro("__cpp_if_constev | ||
Builder.defineMacro("__cpp_multidimen | Builder.defineMacro("__cpp_multidimen | ||
Builder.defineMacro("__cpp_auto_cast", "202110L"); | Builder.defineMacro("__cpp_auto_cast", "202110L"); | ||
+ Builder.defineMacro("__cpp_explicit_t | |||
} | } | ||
// 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 |
@@ -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_AVAILABILI | |||
+_HLSL_BUILTIN_AL | |||
+__attribute__((convergent)) bool WaveActiveAllTru | |||
+ | |||
/// \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. | ||
/// | /// |
@@ -998,17 +998,17 @@ Parser::OpenACCC | |||
// make sure we get the right differentiator. | // make sure we get the right differentiator. | ||
assert(DirKind == OpenACCDirective | assert(DirKind == OpenACCDirective | ||
[[fallthrough]]; | [[fallthrough]]; | ||
- case OpenACCClauseKin | |||
case OpenACCClauseKin | case OpenACCClauseKin | ||
case OpenACCClauseKin | case OpenACCClauseKin | ||
case OpenACCClauseKin | case OpenACCClauseKin | ||
case OpenACCClauseKin | case OpenACCClauseKin | ||
- case OpenACCClauseKin | |||
ParseOpenACCVarL | ParseOpenACCVarL | ||
break; | break; | ||
case OpenACCClauseKin | case OpenACCClauseKin | ||
+ case OpenACCClauseKin | |||
case OpenACCClauseKin | case OpenACCClauseKin | ||
case OpenACCClauseKin | case OpenACCClauseKin | ||
+ case OpenACCClauseKin | |||
ParsedClause.setVarListDetail | ParsedClause.setVarListDetail | ||
/*IsReadOnly=*/false, /*IsZero=*/false); | /*IsReadOnly=*/false, /*IsZero=*/false); | ||
break; | break; | ||
@@ -1512,8 +1512,8 @@ StmtResult Parser::ParseOpe | |||
ParsingOpenACCDi | ParsingOpenACCDi | ||
OpenACCDirective | OpenACCDirective | ||
- if (getActions().OpenACC().ActOnStartStmtDirective( | + if (getActions().OpenACC().ActOnStartStmtDirective( | ||
- DirInfo.StartLoc)) | + DirInfo.DirKind, DirInfo.StartLoc, DirInfo.Clauses)) | ||
return StmtError(); | return StmtError(); | ||
StmtResult AssocStmt; | StmtResult AssocStmt; |
@@ -191,6 +191,19 @@ public: | |||
return *this; | return *this; | ||
} | } | ||
+ BuiltinTypeDeclB | |||
+ if (Record->isCompleteDefini | |||
+ 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 CheckAccessFully | |||
+ addHandleAccessF | |||
+ | |||
+ return *this; | |||
+ } | |||
+ | |||
FieldDecl *getResourceHandl | FieldDecl *getResourceHandl | ||
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: | ||
~BuiltinTypeMetho | ~BuiltinTypeMetho | ||
+ BuiltinTypeMetho | |||
+ BuiltinTypeMetho | |||
+ operator=(const BuiltinTypeMetho | |||
+ | |||
Expr *getResourceHandl | Expr *getResourceHandl | ||
// 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 HLSLExternalSema | |||
ResourceKind::TypedBuffer, /*IsROV=*/false, | ResourceKind::TypedBuffer, /*IsROV=*/false, | ||
/*RawBuffer=*/false) | /*RawBuffer=*/false) | ||
.addArraySubscrip | .addArraySubscrip | ||
+ .addLoadMethods() | |||
.completeDefiniti | .completeDefiniti | ||
}); | }); | ||
@@ -933,6 +951,7 @@ void HLSLExternalSema | |||
ResourceKind::TypedBuffer, /*IsROV=*/true, | ResourceKind::TypedBuffer, /*IsROV=*/true, | ||
/*RawBuffer=*/false) | /*RawBuffer=*/false) | ||
.addArraySubscrip | .addArraySubscrip | ||
+ .addLoadMethods() | |||
.completeDefiniti | .completeDefiniti | ||
}); | }); | ||
@@ -11786,6 +11786,50 @@ static bool checkForArray(co | |||
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> isTautologicalBo | |||
+ const Expr *RHS, | |||
+ BinaryOperatorKi | |||
+ 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::isSameComparison | |||
+ Other = BO->getRHS(); | |||
+ else if (Expr::isSameComparison | |||
+ Other = BO->getLHS(); | |||
+ else | |||
+ return std::nullopt; | |||
+ | |||
+ if (!Other->getType()->isUnsignedIntege | |||
+ 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 diagnoseTautolog | static void diagnoseTautolog | ||
Expr *LHS, Expr *RHS, | Expr *LHS, Expr *RHS, | ||
@@ -11895,6 +11939,12 @@ static void diagnoseTautolog | |||
S.PDiag(diag::warn_comparison_ | S.PDiag(diag::warn_comparison_ | ||
<< 1 /*array comparison*/ | << 1 /*array comparison*/ | ||
<< Result); | << Result); | ||
+ } else if (std::optional<bool> Res = | |||
+ isTautologicalBo | |||
+ S.DiagRuntimeBehav | |||
+ S.PDiag(diag::warn_comparison_ | |||
+ << 2 /*pointer comparison*/ | |||
+ << (*Res ? AlwaysTrue : AlwaysFalse)); | |||
} | } | ||
} | } | ||
@@ -8201,7 +8201,7 @@ ExprResult Sema::BuildPseud | |||
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_ | Diag(OpLoc, diag::ext_pseudo_dtor_ | ||
else { | else { |
@@ -1003,15 +1003,6 @@ Sema::BuildMembe | |||
: !isDependentScope | : !isDependentScope | ||
"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 = TemporaryMateria | |||
- if (Converted.isInvalid()) | |||
- return ExprError(); | |||
- BaseExpr = Converted.get(); | |||
- } | |||
- | |||
const DeclarationNameI | const DeclarationNameI | ||
DeclarationName MemberName = MemberNameInfo.getName(); | DeclarationName MemberName = MemberNameInfo.getName(); | ||
SourceLocation MemberLoc = MemberNameInfo.getLoc(); | SourceLocation MemberLoc = MemberNameInfo.getLoc(); | ||
@@ -1128,26 +1119,68 @@ Sema::BuildMembe | |||
BaseExpr = BuildCXXThisExpr | BaseExpr = BuildCXXThisExpr | ||
} | } | ||
+ // 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 ConvertBaseExprT | |||
+ assert(getLangOpts().CPlusPlus && | |||
+ "Static member / member enumerator outside of C++"); | |||
+ if (IsArrow) | |||
+ return false; | |||
+ ExprResult Converted = IgnoredValueConv | |||
+ if (Converted.isInvalid()) | |||
+ return true; | |||
+ BaseExpr = Converted.get(); | |||
+ DiagnoseDiscarde | |||
+ return false; | |||
+ }; | |||
+ auto ConvertBaseExprT | |||
+ if (IsArrow || !BaseExpr->isPRValue()) | |||
+ return false; | |||
+ ExprResult Converted = TemporaryMateria | |||
+ if (Converted.isInvalid()) | |||
+ return true; | |||
+ BaseExpr = Converted.get(); | |||
+ return false; | |||
+ }; | |||
+ | |||
// Check the use of this member. | // Check the use of this member. | ||
if (DiagnoseUseOfDec | if (DiagnoseUseOfDec | ||
return ExprError(); | return ExprError(); | ||
- if (FieldDecl *FD = dyn_cast<FieldDecl>(MemberDecl)) | + if (FieldDecl *FD = dyn_cast<FieldDecl>(MemberDecl)) { | ||
+ if (ConvertBaseExprT | |||
+ return ExprError(); | |||
return BuildFieldRefere | return BuildFieldRefere | ||
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 BuildMSPropertyR | return BuildMSPropertyR | ||
MemberNameInfo); | MemberNameInfo); | ||
+ } | |||
- if (IndirectFieldDecl *FD = dyn_cast<IndirectFieldDecl>(MemberDecl)) | + if (IndirectFieldDecl *FD = dyn_cast<IndirectFieldDecl>(MemberDecl)) { | ||
+ if (ConvertBaseExprT | |||
+ 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 BuildAnonymousSt | return BuildAnonymousSt | ||
FoundDecl, BaseExpr, | FoundDecl, BaseExpr, | ||
OpLoc); | OpLoc); | ||
+ } | |||
+ // Static data member | |||
if (VarDecl *Var = dyn_cast<VarDecl>(MemberDecl)) { | if (VarDecl *Var = dyn_cast<VarDecl>(MemberDecl)) { | ||
+ if (ConvertBaseExprT | |||
+ return ExprError(); | |||
return BuildMemberExpr(BaseExpr, IsArrow, OpLoc, | return BuildMemberExpr(BaseExpr, IsArrow, OpLoc, | ||
SS.getWithLocInCont | SS.getWithLocInCont | ||
FoundDecl, /*HadMultipleCandi | FoundDecl, /*HadMultipleCandi | ||
@@ -1161,7 +1194,13 @@ Sema::BuildMembe | |||
if (MemberFn->isInstance()) { | if (MemberFn->isInstance()) { | ||
valueKind = VK_PRValue; | valueKind = VK_PRValue; | ||
type = Context.BoundMemberTy; | type = Context.BoundMemberTy; | ||
+ if (MemberFn->isImplicitObject | |||
+ ConvertBaseExprT | |||
+ return ExprError(); | |||
} else { | } else { | ||
+ // Static member function | |||
+ if (ConvertBaseExprT | |||
+ return ExprError(); | |||
valueKind = VK_LValue; | valueKind = VK_LValue; | ||
type = MemberFn->getType(); | type = MemberFn->getType(); | ||
} | } | ||
@@ -1174,6 +1213,8 @@ Sema::BuildMembe | |||
assert(!isa<FunctionDecl>(MemberDecl) && "member function not C++ method?"); | assert(!isa<FunctionDecl>(MemberDecl) && "member function not C++ method?"); | ||
if (EnumConstantDecl | if (EnumConstantDecl | ||
+ if (ConvertBaseExprT | |||
+ return ExprError(); | |||
return BuildMemberExpr( | return BuildMemberExpr( | ||
BaseExpr, IsArrow, OpLoc, SS.getWithLocInCont | BaseExpr, IsArrow, OpLoc, SS.getWithLocInCont | ||
TemplateKWLoc, Enum, FoundDecl, /*HadMultipleCandi | TemplateKWLoc, Enum, FoundDecl, /*HadMultipleCandi | ||
@@ -1181,6 +1222,8 @@ Sema::BuildMembe | |||
} | } | ||
if (VarTemplateDecl *VarTempl = dyn_cast<VarTemplateDecl>(MemberDecl)) { | if (VarTemplateDecl *VarTempl = dyn_cast<VarTemplateDecl>(MemberDecl)) { | ||
+ if (ConvertBaseExprT | |||
+ return ExprError(); | |||
if (!TemplateArgs) { | if (!TemplateArgs) { | ||
diagnoseMissingT | diagnoseMissingT | ||
SS, /*TemplateKeyword=*/TemplateKWLoc.isValid(), VarTempl, MemberLoc); | SS, /*TemplateKeyword=*/TemplateKWLoc.isValid(), VarTempl, MemberLoc); |
@@ -425,6 +425,15 @@ bool doesClauseApplyT | |||
return false; | return false; | ||
} | } | ||
} | } | ||
+ case OpenACCClauseKin | |||
+ switch (DirectiveKind) { | |||
+ case OpenACCDirective | |||
+ return true; | |||
+ default: | |||
+ return false; | |||
+ } | |||
+ } | |||
+ | |||
case OpenACCClauseKin | case OpenACCClauseKin | ||
switch (DirectiveKind) { | switch (DirectiveKind) { | ||
case OpenACCDirective | case OpenACCDirective | ||
@@ -433,6 +442,15 @@ bool doesClauseApplyT | |||
return false; | return false; | ||
} | } | ||
} | } | ||
+ | |||
+ case OpenACCClauseKin | |||
+ switch (DirectiveKind) { | |||
+ case OpenACCDirective | |||
+ return true; | |||
+ default: | |||
+ return false; | |||
+ } | |||
+ } | |||
} | } | ||
default: | default: | ||
@@ -1066,6 +1084,25 @@ OpenACCClause *SemaOpenACCClau | |||
Clause.getEndLoc()); | Clause.getEndLoc()); | ||
} | } | ||
+OpenACCClause *SemaOpenACCClaus | |||
+ SemaOpenACC::OpenACCParsedCla | |||
+ // 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 OpenACCDeleteCla | |||
+ Clause.getLParenLoc(), Clause.getVarList(), | |||
+ Clause.getEndLoc()); | |||
+} | |||
+ | |||
+OpenACCClause *SemaOpenACCClaus | |||
+ SemaOpenACC::OpenACCParsedCla | |||
+ // ActOnVar ensured that everything is a valid variable or array, so nothing | |||
+ // left to do here. | |||
+ return OpenACCUseDevice | |||
+ Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getVarList(), | |||
+ Clause.getEndLoc()); | |||
+} | |||
+ | |||
OpenACCClause *SemaOpenACCClaus | OpenACCClause *SemaOpenACCClaus | ||
SemaOpenACC::OpenACCParsedCla | SemaOpenACC::OpenACCParsedCla | ||
// Restrictions only properly implemented on 'compute'/'combined'/'data' | // Restrictions only properly implemented on 'compute'/'combined'/'data' | ||
@@ -2411,6 +2448,15 @@ bool SemaOpenACC::Che | |||
ExprResult SemaOpenACC::ActOnVar(OpenACCClauseKin | ExprResult SemaOpenACC::ActOnVar(OpenACCClauseKin | ||
Expr *CurVarExpr = VarExpr->IgnoreParenImpCa | Expr *CurVarExpr = VarExpr->IgnoreParenImpCa | ||
+ // '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 == OpenACCClauseKin | |||
+ isa<ArraySectionExpr | |||
+ Diag(VarExpr->getExprLoc(), diag::err_acc_not_a_va | |||
+ 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 | while (isa<ArraySectionExpr | ||
@@ -2431,16 +2477,20 @@ ExprResult SemaOpenACC::Act | |||
// 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 != OpenACCClauseKin | + // variable or array. | ||
+ // A MemberExpr that references a Field is valid for other clauses. | |||
+ if (CK != OpenACCClauseKin | |||
+ CK != OpenACCClauseKin | |||
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 | + // 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 != OpenACCClauseKin | |||
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::Act | |||
if (isa<RecoveryExpr>(CurVarExpr)) | if (isa<RecoveryExpr>(CurVarExpr)) | ||
return ExprError(); | return ExprError(); | ||
- Diag(VarExpr->getExprLoc(), diag::err_acc_not_a_va | + if (CK == OpenACCClauseKin | ||
- << (CK != OpenACCClauseKin | + Diag(VarExpr->getExprLoc(), diag::err_acc_not_a_va | ||
+ else | |||
+ Diag(VarExpr->getExprLoc(), diag::err_acc_not_a_va | |||
+ << (CK != OpenACCClauseKin | |||
return ExprError(); | return ExprError(); | ||
} | } | ||
@@ -3473,8 +3526,35 @@ void SemaOpenACC::Act | |||
} | } | ||
} | } | ||
-bool SemaOpenACC::ActOnStartStmtDi | +namespace { | ||
- SourceLocation StartLoc) { | +// Get a list of clause Kinds for diagnosing a list, joined by a commas and an | ||
+// 'or'. | |||
+std::string GetListOfClauses | |||
+ assert(!Clauses.empty() && "empty clause list not supported"); | |||
+ | |||
+ std::string Output; | |||
+ llvm::raw_string_ostre | |||
+ | |||
+ if (Clauses.size() == 1) { | |||
+ OS << '\'' << Clauses[0] << '\''; | |||
+ return Output; | |||
+ } | |||
+ | |||
+ llvm::ArrayRef<OpenACCClauseKin | |||
+ Clauses.end() - 1}; | |||
+ | |||
+ llvm::interleave( | |||
+ AllButLast, [&](OpenACCClauseKin | |||
+ [&] { OS << ", "; }); | |||
+ | |||
+ OS << " or \'" << Clauses.back() << '\''; | |||
+ return Output; | |||
+} | |||
+} // namespace | |||
+ | |||
+bool SemaOpenACC::ActOnStartStmtDi | |||
+ OpenACCDirective | |||
+ ArrayRef<const OpenACCClause *> Clauses) { | |||
SemaRef.DiscardCleanupsI | SemaRef.DiscardCleanupsI | ||
SemaRef.PopExpressionEva | SemaRef.PopExpressionEva | ||
@@ -3501,6 +3581,59 @@ bool SemaOpenACC::Act | |||
<< OpenACCClauseKin | << OpenACCClauseKin | ||
} | } | ||
+ // 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 == OpenACCDirective | |||
+ llvm::find_if(Clauses, | |||
+ llvm::IsaPred<OpenACCCopyClaus | |||
+ OpenACCCopyOutCl | |||
+ OpenACCNoCreateC | |||
+ OpenACCDevicePtr | |||
+ OpenACCDefaultCl | |||
+ return Diag(StartLoc, diag::err_acc_construc | |||
+ << K | |||
+ << GetListOfClauses | |||
+ {OpenACCClauseKin | |||
+ OpenACCClauseKin | |||
+ OpenACCClauseKin | |||
+ OpenACCClauseKin | |||
+ OpenACCClauseKin | |||
+ | |||
+ // OpenACC3.3 2.6.6: At least one copyin, create, or attach clause must appear | |||
+ // on an enter data directive. | |||
+ if (K == OpenACCDirective | |||
+ llvm::find_if(Clauses, | |||
+ llvm::IsaPred<OpenACCCopyInCla | |||
+ OpenACCAttachCla | |||
+ return Diag(StartLoc, diag::err_acc_construc | |||
+ << K | |||
+ << GetListOfClauses | |||
+ OpenACCClauseKin | |||
+ OpenACCClauseKin | |||
+ OpenACCClauseKin | |||
+ }); | |||
+ // OpenACC3.3 2.6.6: At least one copyout, delete, or detach clause must | |||
+ // appear on an exit data directive. | |||
+ if (K == OpenACCDirective | |||
+ llvm::find_if(Clauses, | |||
+ llvm::IsaPred<OpenACCCopyOutCl | |||
+ OpenACCDetachCla | |||
+ return Diag(StartLoc, diag::err_acc_construc | |||
+ << K | |||
+ << GetListOfClauses | |||
+ OpenACCClauseKin | |||
+ OpenACCClauseKin | |||
+ OpenACCClauseKin | |||
+ }); | |||
+ | |||
+ // OpenACC3.3 2.8: At least 'one use_device' clause must appear. | |||
+ if (K == OpenACCDirective | |||
+ llvm::find_if(Clauses, llvm::IsaPred<OpenACCUseDevice | |||
+ Clauses.end()) | |||
+ return Diag(StartLoc, diag::err_acc_construc | |||
+ << K << GetListOfClauses | |||
+ | |||
return diagnoseConstruc | return diagnoseConstruc | ||
} | } | ||
@@ -5933,7 +5933,9 @@ ExprResult Sema::PerformImp | |||
DestType = ImplicitParamRec | DestType = ImplicitParamRec | ||
FromClassificati | FromClassificati | ||
- // 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 = CreateMaterializ | From = CreateMaterializ | ||
Method->getRefQualifier() != | Method->getRefQualifier() != | ||
@@ -6464,11 +6466,6 @@ static Expr *GetExplicitObje | |||
VK_LValue, OK_Ordinary, SourceLocation(), | VK_LValue, OK_Ordinary, SourceLocation(), | ||
/*CanOverflow=*/false, FPOptionsOverrid | /*CanOverflow=*/false, FPOptionsOverrid | ||
} | } | ||
- if (Obj->Classify(S.getASTContext()).isPRValue()) { | |||
- Obj = S.CreateMaterializ | |||
- ObjType, Obj, | |||
- !Fun->getParamDecl(0)->getType()->isRValueReferenc | |||
- } | |||
return Obj; | return Obj; | ||
} | } | ||
@@ -15584,8 +15581,6 @@ ExprResult Sema::BuildCallT | |||
CurFPFeatureOver | CurFPFeatureOver | ||
} 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 = PerformImplicitO | ExprResult ObjectArg = PerformImplicitO | ||
MemExpr->getBase(), Qualifier, FoundDecl, Method); | MemExpr->getBase(), Qualifier, FoundDecl, Method); | ||
if (ObjectArg.isInvalid()) | if (ObjectArg.isInvalid()) |
@@ -226,17 +226,18 @@ static bool DiagnoseNoDiscar | |||
return S.Diag(Loc, diag::warn_unused_resu | return S.Diag(Loc, diag::warn_unused_resu | ||
} | } | ||
-void Sema::DiagnoseUnusedEx | +namespace { | ||
- if (const LabelStmt *Label = dyn_cast_or_null | |||
- return DiagnoseUnusedEx | |||
- const Expr *E = dyn_cast_or_null | +// Diagnoses unused expressions that call functions marked [[nodiscard]], | ||
- if (!E) | +// [[gnu::warn_unused_resu | ||
- 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->IgnoreParenImpCa | SourceLocation ExprLoc = E->IgnoreParenImpCa | ||
@@ -245,30 +246,31 @@ void Sema::DiagnoseUn | |||
// expression is a call to a function with the warn_unused_resu | // expression is a call to a function with the warn_unused_resu | ||
// 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.isMacroBodyExpan | + 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_PAR | + 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 (findMacroSpellin | + if (isa<StmtExpr>(E) && Loc.isMacroID()) | ||
return; | return; | ||
+ | |||
+ // Check if this is the UNREFERENCED_PAR | |||
+ // 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.findMacroSpellin | |||
+ 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::DiagnoseUn | |||
if (const CXXBindTemporary | if (const CXXBindTemporary | ||
E = TempExpr->getSubExpr(); | E = TempExpr->getSubExpr(); | ||
- if (DiagnoseUnusedComparison( | + if (DiagnoseUnusedComparison(S, E)) | ||
return; | return; | ||
E = WarnExpr; | E = WarnExpr; | ||
@@ -293,8 +295,8 @@ void Sema::DiagnoseUn | |||
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( | + if (DiagnoseNoDiscard(S, OffendingDecl, | ||
cast_or_null<WarnUnusedResult | cast_or_null<WarnUnusedResult | ||
/*isCtor=*/false)) | /*isCtor=*/false)) | ||
return; | return; | ||
@@ -307,11 +309,11 @@ void Sema::DiagnoseUn | |||
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::DiagnoseUn | |||
OffendingDecl = Ctor->getParent(); | OffendingDecl = Ctor->getParent(); | ||
A = OffendingDecl->getAttr<WarnUnusedResult | A = OffendingDecl->getAttr<WarnUnusedResult | ||
} | } | ||
- if (DiagnoseNoDiscard( | + 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( | + if (DiagnoseNoDiscard(S, TD, TD->getAttr<WarnUnusedResultAttr>(), Loc, R1, | ||
- | + R2, /*isCtor=*/false)) | ||
return; | return; | ||
} | } | ||
} else if (ShouldSuppress) | } else if (ShouldSuppress) | ||
@@ -339,23 +341,24 @@ void Sema::DiagnoseUn | |||
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( | + if (DiagnoseNoDiscard(S, nullptr, MD->getAttr<WarnUnusedResultAttr>(), | ||
- Loc, R1, R2, | + Loc, R1, R2, | ||
+ /*isCtor=*/false)) | |||
return; | return; | ||
} | } | ||
} else if (const PseudoObjectExpr | } else if (const PseudoObjectExpr | ||
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->getNumSemanticEx | POE->getNumSemanticEx | ||
isa<CallExpr>(POE->getSemanticExpr(0))) | isa<CallExpr>(POE->getSemanticExpr(0))) | ||
- return | + return DiagnoseUnused(S, POE->getSemanticExpr(0), DiagID); | ||
if (isa<ObjCSubscriptRef | if (isa<ObjCSubscriptRef | ||
DiagID = diag::warn_unused_cont | DiagID = diag::warn_unused_cont | ||
else if (isa<ObjCPropertyRefE | else if (isa<ObjCPropertyRefE | ||
@@ -372,17 +375,21 @@ void Sema::DiagnoseUn | |||
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". | ||
- | + if (const CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(E)) { | ||
TypeSourceInfo *TI = CE->getTypeInfoAsWri | TypeSourceInfo *TI = CE->getTypeInfoAsWri | ||
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()); | ||
return; | return; | ||
} | } | ||
} | } | ||
@@ -391,16 +398,34 @@ void Sema::DiagnoseUn | |||
// isn't an array. | // isn't an array. | ||
if (E->isGLValue() && E->getType().isVolatileQualif | if (E->isGLValue() && E->getType().isVolatileQualif | ||
!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 | + 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::DiagnoseDiscarde | |||
+ DiagnoseUnused(*this, E, std::nullopt); | |||
+} | |||
+ | |||
+void Sema::DiagnoseUnusedEx | |||
+ if (const LabelStmt *Label = dyn_cast_if_pres | |||
+ S = Label->getSubStmt(); | |||
+ | |||
+ const Expr *E = dyn_cast_if_pres | |||
+ if (!E) | |||
+ return; | |||
+ | |||
+ DiagnoseUnused(*this, E, DiagID); | |||
} | } | ||
void Sema::ActOnStartOfComp | void Sema::ActOnStartOfComp |
@@ -664,11 +664,16 @@ StmtResult Sema::ActOnGCCAs | |||
SmallerValueMent | SmallerValueMent | ||
} | } | ||
+ // 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 && | ||
OutputConstraint | OutputConstraint | ||
+ | |||
// 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() && |
@@ -2146,6 +2146,23 @@ Decl *TemplateDeclIns | |||
// Check whether there is already a function template specialization for | // Check whether there is already a function template specialization for | ||
// this declaration. | // this declaration. | ||
FunctionTemplate | FunctionTemplate | ||
+ bool isFriend; | |||
+ if (FunctionTemplate | |||
+ isFriend = (FunctionTemplate | |||
+ else | |||
+ isFriend = (D->getFriendObjectK | |||
+ | |||
+ // 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 | |||
+ } | |||
+ } | |||
+ | |||
if (FunctionTemplate | if (FunctionTemplate | ||
ArrayRef<TemplateArgument | ArrayRef<TemplateArgument | ||
@@ -2158,12 +2175,6 @@ Decl *TemplateDeclIns | |||
return SpecFunc; | return SpecFunc; | ||
} | } | ||
- bool isFriend; | |||
- if (FunctionTemplate | |||
- isFriend = (FunctionTemplate | |||
- else | |||
- isFriend = (D->getFriendObjectK | |||
- | |||
bool MergeWithParentS | bool MergeWithParentS | ||
Owner->isFunctionOrMeth | Owner->isFunctionOrMeth | ||
!(isa<Decl>(Owner) && | !(isa<Decl>(Owner) && | ||
@@ -4692,6 +4703,17 @@ bool Sema::Instantiat | |||
ParmVarDecl *Param) { | ParmVarDecl *Param) { | ||
assert(Param->hasUninstantiate | assert(Param->hasUninstantiate | ||
+ // 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->getFriendObjectK | |||
+ !FD->getTemplateInsta | |||
+ return true; | |||
+ | |||
// Instantiate the expression. | // Instantiate the expression. | ||
// | // | ||
// FIXME: Pass in a correct Pattern argument, otherwise | // FIXME: Pass in a correct Pattern argument, otherwise |
@@ -2312,6 +2312,17 @@ QualType Sema::BuildArray | |||
return T; | return T; | ||
} | } | ||
+static bool CheckBitIntEleme | |||
+ 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_in | |||
+ << 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::BuildVecto | |||
Diag(AttrLoc, diag::err_attribute_in | Diag(AttrLoc, diag::err_attribute_in | ||
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 && CheckBitIntEleme | ||
- if (!llvm::isPowerOf2_32(NumBits) || NumBits < 8) { | + return QualType(); | ||
- Diag(AttrLoc, diag::err_attribute_in | |||
- << (NumBits < 8); | |||
- return QualType(); | |||
- } | |||
- } | |||
if (SizeExpr->isTypeDependent() || SizeExpr->isValueDependent | if (SizeExpr->isTypeDependent() || SizeExpr->isValueDependent | ||
return Context.getDependentVect | return Context.getDependentVect | ||
@@ -2402,15 +2408,9 @@ QualType Sema::BuildExtVe | |||
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 && CheckBitIntEleme | ||
- unsigned NumBits = T->castAs<BitIntType>()->getNumBits(); | + return QualType(); | ||
- if (!llvm::isPowerOf2_32(NumBits) || NumBits < 8) { | |||
- Diag(AttrLoc, diag::err_attribute_in | |||
- << (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::BuildMatri | |||
return QualType(); | return QualType(); | ||
} | } | ||
+ if (const auto *BIT = ElementTy->getAs<BitIntType>(); | |||
+ BIT && | |||
+ CheckBitIntEleme | |||
+ return QualType(); | |||
+ | |||
if (NumRows->isTypeDependent() || NumCols->isTypeDependent() || | if (NumRows->isTypeDependent() || NumCols->isTypeDependent() || | ||
NumRows->isValueDependent | NumRows->isValueDependent | ||
return Context.getDependentSize | return Context.getDependentSize |
@@ -11777,6 +11777,28 @@ void OpenACCClauseTra | |||
ParsedClause.getEndLoc()); | ParsedClause.getEndLoc()); | ||
} | } | ||
+template <typename Derived> | |||
+void OpenACCClauseTra | |||
+ const OpenACCDeleteCla | |||
+ ParsedClause.setVarListDetail | |||
+ /*IsReadOnly=*/false, /*IsZero=*/false); | |||
+ NewClause = OpenACCDeleteCla | |||
+ Self.getSema().getASTContext(), ParsedClause.getBeginLoc(), | |||
+ ParsedClause.getLParenLoc(), ParsedClause.getVarList(), | |||
+ ParsedClause.getEndLoc()); | |||
+} | |||
+ | |||
+template <typename Derived> | |||
+void OpenACCClauseTra | |||
+ const OpenACCUseDevice | |||
+ ParsedClause.setVarListDetail | |||
+ /*IsReadOnly=*/false, /*IsZero=*/false); | |||
+ NewClause = OpenACCUseDevice | |||
+ Self.getSema().getASTContext(), ParsedClause.getBeginLoc(), | |||
+ ParsedClause.getLParenLoc(), ParsedClause.getVarList(), | |||
+ ParsedClause.getEndLoc()); | |||
+} | |||
+ | |||
template <typename Derived> | template <typename Derived> | ||
void OpenACCClauseTra | void OpenACCClauseTra | ||
const OpenACCDevicePtr | const OpenACCDevicePtr | ||
@@ -12156,8 +12178,8 @@ StmtResult TreeTransform<De | |||
getDerived().TransformOpenACC | getDerived().TransformOpenACC | ||
C->clauses()); | C->clauses()); | ||
- if (getSema().OpenACC().ActOnStartStmtDirective( | + if (getSema().OpenACC().ActOnStartStmtDirective( | ||
- C->getBeginLoc())) | + C->getDirectiveKind | ||
return StmtError(); | return StmtError(); | ||
// Transform Structured Block. | // Transform Structured Block. | ||
@@ -12183,8 +12205,8 @@ TreeTransform<De | |||
getDerived().TransformOpenACC | getDerived().TransformOpenACC | ||
C->clauses()); | C->clauses()); | ||
- if (getSema().OpenACC().ActOnStartStmtDirective( | + if (getSema().OpenACC().ActOnStartStmtDirective( | ||
- C->getBeginLoc())) | + C->getDirectiveKind | ||
return StmtError(); | return StmtError(); | ||
// Transform Loop. | // Transform Loop. | ||
@@ -12209,8 +12231,8 @@ StmtResult TreeTransform<De | |||
getDerived().TransformOpenACC | getDerived().TransformOpenACC | ||
C->clauses()); | C->clauses()); | ||
- if (getSema().OpenACC().ActOnStartStmtDirective( | + if (getSema().OpenACC().ActOnStartStmtDirective( | ||
- C->getBeginLoc())) | + C->getDirectiveKind | ||
return StmtError(); | return StmtError(); | ||
// Transform Loop. | // Transform Loop. | ||
@@ -12234,8 +12256,8 @@ TreeTransform<De | |||
llvm::SmallVector<OpenACCClause *> TransformedClaus | llvm::SmallVector<OpenACCClause *> TransformedClaus | ||
getDerived().TransformOpenACC | getDerived().TransformOpenACC | ||
C->clauses()); | C->clauses()); | ||
- if (getSema().OpenACC().ActOnStartStmtDirective( | + if (getSema().OpenACC().ActOnStartStmtDirective( | ||
- C->getBeginLoc())) | + C->getDirectiveKind | ||
return StmtError(); | return StmtError(); | ||
SemaOpenACC::AssociatedStmtRA | SemaOpenACC::AssociatedStmtRA | ||
@@ -12258,8 +12280,8 @@ StmtResult TreeTransform<De | |||
llvm::SmallVector<OpenACCClause *> TransformedClaus | llvm::SmallVector<OpenACCClause *> TransformedClaus | ||
getDerived().TransformOpenACC | getDerived().TransformOpenACC | ||
C->clauses()); | C->clauses()); | ||
- if (getSema().OpenACC().ActOnStartStmtDirective( | + if (getSema().OpenACC().ActOnStartStmtDirective( | ||
- C->getBeginLoc())) | + C->getDirectiveKind | ||
return StmtError(); | return StmtError(); | ||
return getDerived().RebuildOpenACCEn | return getDerived().RebuildOpenACCEn | ||
@@ -12275,8 +12297,8 @@ StmtResult TreeTransform<De | |||
llvm::SmallVector<OpenACCClause *> TransformedClaus | llvm::SmallVector<OpenACCClause *> TransformedClaus | ||
getDerived().TransformOpenACC | getDerived().TransformOpenACC | ||
C->clauses()); | C->clauses()); | ||
- if (getSema().OpenACC().ActOnStartStmtDirective( | + if (getSema().OpenACC().ActOnStartStmtDirective( | ||
- C->getBeginLoc())) | + C->getDirectiveKind | ||
return StmtError(); | return StmtError(); | ||
return getDerived().RebuildOpenACCEx | return getDerived().RebuildOpenACCEx | ||
@@ -12292,8 +12314,8 @@ StmtResult TreeTransform<De | |||
llvm::SmallVector<OpenACCClause *> TransformedClaus | llvm::SmallVector<OpenACCClause *> TransformedClaus | ||
getDerived().TransformOpenACC | getDerived().TransformOpenACC | ||
C->clauses()); | C->clauses()); | ||
- if (getSema().OpenACC().ActOnStartStmtDirective( | + if (getSema().OpenACC().ActOnStartStmtDirective( | ||
- C->getBeginLoc())) | + C->getDirectiveKind | ||
return StmtError(); | return StmtError(); | ||
SemaOpenACC::AssociatedStmtRA | SemaOpenACC::AssociatedStmtRA |
@@ -3963,14 +3963,14 @@ llvm::Error ASTReader::ReadA | |||
break; | break; | ||
} | } | ||
- case | + 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 | + auto &RelatedDecls = RelatedDeclsMap[ID]; | ||
unsigned NN = Record[I++]; | unsigned NN = Record[I++]; | ||
- | + RelatedDecls.reserve(NN); | ||
for (unsigned II = 0; II < NN; II++) | for (unsigned II = 0; II < NN; II++) | ||
- | + RelatedDecls.push_back(ReadDeclID(F, Record, I)); | ||
} | } | ||
break; | break; | ||
@@ -10278,19 +10278,6 @@ void ASTReader::finis | |||
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->isDependentConte | |||
- 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 | |||
return OpenACCDetachCla | return OpenACCDetachCla | ||
VarList, EndLoc); | VarList, EndLoc); | ||
} | } | ||
+ case OpenACCClauseKin | |||
+ SourceLocation LParenLoc = readSourceLocati | |||
+ llvm::SmallVector<Expr *> VarList = readOpenACCVarLi | |||
+ return OpenACCDeleteCla | |||
+ VarList, EndLoc); | |||
+ } | |||
+ case OpenACCClauseKin | |||
+ SourceLocation LParenLoc = readSourceLocati | |||
+ llvm::SmallVector<Expr *> VarList = readOpenACCVarLi | |||
+ return OpenACCUseDevice | |||
+ VarList, EndLoc); | |||
+ } | |||
case OpenACCClauseKin | case OpenACCClauseKin | ||
SourceLocation LParenLoc = readSourceLocati | SourceLocation LParenLoc = readSourceLocati | ||
llvm::SmallVector<Expr *> VarList = readOpenACCVarLi | llvm::SmallVector<Expr *> VarList = readOpenACCVarLi | ||
@@ -12590,8 +12589,6 @@ OpenACCClause *ASTRecordReader | |||
} | } | ||
case OpenACCClauseKin | case OpenACCClauseKin | ||
- case OpenACCClauseKin | |||
- case OpenACCClauseKin | |||
case OpenACCClauseKin | case OpenACCClauseKin | ||
case OpenACCClauseKin | case OpenACCClauseKin | ||
case OpenACCClauseKin | case OpenACCClauseKin |
@@ -4329,13 +4329,12 @@ void ASTReader::loadD | |||
DC->setHasExternalVi | DC->setHasExternalVi | ||
} | } | ||
- // Load any pending | + // Load any pending related decls. | ||
- if (auto *FD = dyn_cast<FunctionDecl>(D); FD && FD->isCanonicalDecl()) { | + if (D->isCanonicalDecl()) { | ||
- if (auto IT = FunctionToLambda | + if (auto IT = RelatedDeclsMap.find(ID); IT != RelatedDeclsMap.end()) { | ||
- IT != FunctionToLambda | |||
for (auto LID : IT->second) | for (auto LID : IT->second) | ||
GetDecl(LID); | GetDecl(LID); | ||
- | + RelatedDeclsMap.erase(IT); | ||
} | } | ||
} | } | ||
@@ -941,7 +941,7 @@ void ASTWriter::Write | |||
RECORD(PENDING_IMPLICIT | RECORD(PENDING_IMPLICIT | ||
RECORD(UPDATE_VISIBLE); | RECORD(UPDATE_VISIBLE); | ||
RECORD(DELAYED_NAMESPAC | RECORD(DELAYED_NAMESPAC | ||
- RECORD( | + RECORD(RELATED_DECLS_MAP); | ||
RECORD(DECL_UPDATE_OFFS | RECORD(DECL_UPDATE_OFFS | ||
RECORD(DECL_UPDATES); | RECORD(DECL_UPDATES); | ||
RECORD(CUDA_SPECIAL_DEC | RECORD(CUDA_SPECIAL_DEC | ||
@@ -5972,23 +5972,23 @@ void ASTWriter::Write | |||
Stream.EmitRecord(DELAYED_NAMESPAC | Stream.EmitRecord(DELAYED_NAMESPAC | ||
DelayedNamespace | DelayedNamespace | ||
- if ( | + if (!RelatedDeclsMap.empty()) { | ||
- // TODO: on disk hash table for | + // 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 | + RecordData RelatedDeclsMapRecord; | ||
- for (const auto &Pair : | + for (const auto &Pair : RelatedDeclsMap) { | ||
- | + RelatedDeclsMapRecord.push_back(Pair.first.getRawValue()); | ||
- | + RelatedDeclsMapRecord.push_back(Pair.second.size()); | ||
for (const auto &Lambda : Pair.second) | for (const auto &Lambda : Pair.second) | ||
- | + RelatedDeclsMapRecord.push_back(Lambda.getRawValue()); | ||
} | } | ||
auto Abv = std::make_shared<llvm::BitCodeAbbrev>(); | auto Abv = std::make_shared<llvm::BitCodeAbbrev>(); | ||
- Abv->Add(llvm::BitCodeAbbrevOp( | + 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 FunctionToLambda | unsigned FunctionToLambda | ||
- Stream.EmitRecord( | + Stream.EmitRecord(RELATED_DECLS_MAP, RelatedDeclsMapRecord, | ||
FunctionToLambda | FunctionToLambda | ||
} | } | ||
@@ -8362,6 +8362,18 @@ void ASTRecordWriter: | |||
writeOpenACCVarL | writeOpenACCVarL | ||
return; | return; | ||
} | } | ||
+ case OpenACCClauseKin | |||
+ const auto *DC = cast<OpenACCDeleteCla | |||
+ writeSourceLocat | |||
+ writeOpenACCVarL | |||
+ return; | |||
+ } | |||
+ case OpenACCClauseKin | |||
+ const auto *UDC = cast<OpenACCUseDevice | |||
+ writeSourceLocat | |||
+ writeOpenACCVarL | |||
+ return; | |||
+ } | |||
case OpenACCClauseKin | case OpenACCClauseKin | ||
const auto *DPC = cast<OpenACCDevicePtr | const auto *DPC = cast<OpenACCDevicePtr | ||
writeSourceLocat | writeSourceLocat | ||
@@ -8505,8 +8517,6 @@ void ASTRecordWriter: | |||
} | } | ||
case OpenACCClauseKin | case OpenACCClauseKin | ||
- case OpenACCClauseKin | |||
- case OpenACCClauseKin | |||
case OpenACCClauseKin | case OpenACCClauseKin | ||
case OpenACCClauseKin | case OpenACCClauseKin | ||
case OpenACCClauseKin | case OpenACCClauseKin |
@@ -798,6 +798,17 @@ void ASTDeclWriter::V | |||
} | } | ||
} | } | ||
+ if (D->getFriendObjectK | |||
+ // 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->isDependentConte | |||
+ 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::V | |||
// For lambdas inside canonical FunctionDecl remember the mapping. | // For lambdas inside canonical FunctionDecl remember the mapping. | ||
if (auto FD = llvm::dyn_cast_or_null | if (auto FD = llvm::dyn_cast_or_null | ||
FD && FD->isCanonicalDecl()) { | FD && FD->isCanonicalDecl()) { | ||
- Writer. | + Writer.RelatedDeclsMap[Writer.GetDeclRef(FD)].push_back( | ||
Writer.GetDeclRef(D)); | Writer.GetDeclRef(D)); | ||
} | } | ||
} else { | } else { |
@@ -40,6 +40,7 @@ public: | |||
struct LocalVisitor : DynamicRecursive | struct LocalVisitor : DynamicRecursive | ||
const UncountedLambdaC | const UncountedLambdaC | ||
llvm::DenseSet<const DeclRefExpr *> DeclRefExprsToIg | llvm::DenseSet<const DeclRefExpr *> DeclRefExprsToIg | ||
+ llvm::DenseSet<const LambdaExpr *> LambdasToIgnore; | |||
QualType ClsType; | QualType ClsType; | ||
explicit LocalVisitor(const UncountedLambdaC | explicit LocalVisitor(const UncountedLambdaC | ||
@@ -51,7 +52,7 @@ public: | |||
bool TraverseCXXMetho | bool TraverseCXXMetho | ||
llvm::SaveAndRestore SavedDecl(ClsType); | llvm::SaveAndRestore SavedDecl(ClsType); | ||
- if (CXXMD | + if (CXXMD->isInstance()) | ||
ClsType = CXXMD->getThisType(); | ClsType = CXXMD->getThisType(); | ||
return DynamicRecursive | return DynamicRecursive | ||
} | } | ||
@@ -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 | |||
+ if (!L) | |||
+ return true; | |||
+ LambdasToIgnore.insert(L); // Evaluate lambdas in VisitDeclRefExpr | |||
+ return true; | |||
+ } | |||
+ | |||
bool VisitDeclRefExpr | bool VisitDeclRefExpr | ||
if (DeclRefExprsToIg | if (DeclRefExprsToIg | ||
return true; | return true; | ||
@@ -73,6 +92,7 @@ public: | |||
auto *L = dyn_cast_or_null | auto *L = dyn_cast_or_null | ||
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>() && !TreatAllArgsAsNo | + if (auto *L = dyn_cast_or_null | ||
- if (auto *L = dyn_cast_or_null | + LambdasToIgnore.insert(L); | ||
+ if (!Param->hasAttr<NoEscapeAttr>() && !TreatAllArgsAsNo | |||
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 | |||
+ 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; | ||
DeclRefExprsToIg | DeclRefExprsToIg | ||
+ LambdasToIgnore.insert(L); | |||
Checker->visitLambdaExpr(L, shouldCheckThis(), | Checker->visitLambdaExpr(L, shouldCheckThis(), | ||
/* ignoreParamVarDe | /* ignoreParamVarDe | ||
} | } |
@@ -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_erro | |||
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_invocabl | |||
- | |||
// 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_expl | |||
-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>) |
@@ -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- | +// Generated from cppreference offline HTML book (modified on 2024-11-10). | ||
//===----------------------------------------------------------------------===// | //===----------------------------------------------------------------------===// | ||
SYMBOL(ATOMIC_BOOL_LOCK | SYMBOL(ATOMIC_BOOL_LOCK | ||
@@ -578,6 +578,7 @@ SYMBOL(add_point | |||
SYMBOL(add_pointer_t, std::, <type_traits>) | SYMBOL(add_pointer_t, std::, <type_traits>) | ||
SYMBOL(add_rvalue_refer | SYMBOL(add_rvalue_refer | ||
SYMBOL(add_rvalue_refer | SYMBOL(add_rvalue_refer | ||
+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_fe | |||
SYMBOL(atomic_fetch_add | SYMBOL(atomic_fetch_add | ||
SYMBOL(atomic_fetch_and | SYMBOL(atomic_fetch_and | ||
SYMBOL(atomic_fetch_and | SYMBOL(atomic_fetch_and | ||
+SYMBOL(atomic_fetch_max | |||
+SYMBOL(atomic_fetch_max | |||
+SYMBOL(atomic_fetch_min | |||
+SYMBOL(atomic_fetch_min | |||
SYMBOL(atomic_fetch_or, | SYMBOL(atomic_fetch_or, | ||
SYMBOL(atomic_fetch_or_ | SYMBOL(atomic_fetch_or_ | ||
SYMBOL(atomic_fetch_sub | SYMBOL(atomic_fetch_sub | ||
@@ -727,6 +732,8 @@ SYMBOL(atomic_si | |||
SYMBOL(atomic_store, std::, <atomic>) | SYMBOL(atomic_store, std::, <atomic>) | ||
SYMBOL(atomic_store_exp | SYMBOL(atomic_store_exp | ||
SYMBOL(atomic_thread_fe | SYMBOL(atomic_thread_fe | ||
+SYMBOL(atomic_wait, std::, <atomic>) | |||
+SYMBOL(atomic_wait_expl | |||
SYMBOL(atto, std::, <ratio>) | SYMBOL(atto, std::, <ratio>) | ||
SYMBOL(auto_ptr, std::, <memory>) | SYMBOL(auto_ptr, std::, <memory>) | ||
SYMBOL(back_insert_iter | SYMBOL(back_insert_iter | ||
@@ -829,6 +836,8 @@ SYMBOL(boolalpha | |||
SYMBOL(boolalpha, std::, <iostream>) | SYMBOL(boolalpha, std::, <iostream>) | ||
SYMBOL(boyer_moore_hors | SYMBOL(boyer_moore_hors | ||
SYMBOL(boyer_moore_sear | SYMBOL(boyer_moore_sear | ||
+SYMBOL(breakpoint, std::, <debugging>) | |||
+SYMBOL(breakpoint_if_de | |||
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_cons | |||
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_functio | |||
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, | |||
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_se | SYMBOL(disable_sized_se | ||
SYMBOL(discard_block_en | SYMBOL(discard_block_en | ||
SYMBOL(discrete_distrib | SYMBOL(discrete_distrib | ||
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_f | |||
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_nonlockin | |||
SYMBOL(enable_shared_fr | SYMBOL(enable_shared_fr | ||
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::, | +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_con | SYMBOL(format_parse_con | ||
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_resu | SYMBOL(format_to_n_resu | ||
+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, | SYMBOL(future_category, | ||
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_pro | |||
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_t | SYMBOL(input_iterator_t | ||
SYMBOL(input_or_output_ | SYMBOL(input_or_output_ | ||
@@ -1649,6 +1664,7 @@ SYMBOL(is_copy_a | |||
SYMBOL(is_copy_construc | SYMBOL(is_copy_construc | ||
SYMBOL(is_copy_construc | SYMBOL(is_copy_construc | ||
SYMBOL(is_corresponding | SYMBOL(is_corresponding | ||
+SYMBOL(is_debugger_pres | |||
SYMBOL(is_default_const | SYMBOL(is_default_const | ||
SYMBOL(is_default_const | SYMBOL(is_default_const | ||
SYMBOL(is_destructible, | SYMBOL(is_destructible, | ||
@@ -1790,6 +1806,8 @@ SYMBOL(is_union, | |||
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_ | |||
+SYMBOL(is_virtual_base_ | |||
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_padd | |||
SYMBOL(layout_right, std::, <mdspan>) | SYMBOL(layout_right, std::, <mdspan>) | ||
+SYMBOL(layout_right_pad | |||
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(moneypunc | |||
SYMBOL(moneypunct_bynam | SYMBOL(moneypunct_bynam | ||
SYMBOL(monostate, std::, <variant>) | SYMBOL(monostate, std::, <variant>) | ||
SYMBOL(movable, std::, <concepts>) | SYMBOL(movable, std::, <concepts>) | ||
+SYMBOL(move_backward, std::, <algorithm>) | |||
SYMBOL(move_constructib | SYMBOL(move_constructib | ||
SYMBOL(move_if_noexcept | SYMBOL(move_if_noexcept | ||
SYMBOL(move_iterator, std::, <iterator>) | SYMBOL(move_iterator, std::, <iterator>) | ||
@@ -2229,6 +2250,7 @@ SYMBOL(move_only | |||
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(noboolalp | |||
SYMBOL(noemit_on_flush, | SYMBOL(noemit_on_flush, | ||
SYMBOL(noemit_on_flush, | SYMBOL(noemit_on_flush, | ||
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_h | SYMBOL(noop_coroutine_h | ||
SYMBOL(noop_coroutine_p | SYMBOL(noop_coroutine_p | ||
@@ -2442,6 +2466,8 @@ SYMBOL(random_ac | |||
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, | |||
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_sea | |||
SYMBOL(regex_token_iter | SYMBOL(regex_token_iter | ||
SYMBOL(regex_traits, std::, <regex>) | SYMBOL(regex_traits, std::, <regex>) | ||
SYMBOL(regular, std::, <concepts>) | SYMBOL(regular, std::, <concepts>) | ||
+SYMBOL(regular_invocabl | |||
SYMBOL(reinterpret_poin | SYMBOL(reinterpret_poin | ||
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, | |||
SYMBOL(strftime, None, <time.h>) | SYMBOL(strftime, None, <time.h>) | ||
SYMBOL(strict, std::, <memory>) | SYMBOL(strict, std::, <memory>) | ||
SYMBOL(strict_weak_orde | SYMBOL(strict_weak_orde | ||
+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_distri | SYMBOL(student_t_distri | ||
SYMBOL(sub_match, std::, <regex>) | SYMBOL(sub_match, std::, <regex>) | ||
+SYMBOL(sub_sat, std::, <numeric>) | |||
+SYMBOL(submdspan_mappin | |||
SYMBOL(subtract_with_ca | SYMBOL(subtract_with_ca | ||
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_handle | SYMBOL(terminate_handle | ||
+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 | SYMBOL(visit_format_arg | ||
SYMBOL(void_t, std::, <type_traits>) | SYMBOL(void_t, std::, <type_traits>) | ||
SYMBOL(vprint_nonunicod | SYMBOL(vprint_nonunicod | ||
+SYMBOL(vprint_nonunicod | |||
SYMBOL(vprint_unicode, std::, <print>) | SYMBOL(vprint_unicode, std::, <print>) | ||
+SYMBOL(vprint_unicode_b | |||
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, | SYMBOL(wbuffer_convert, | ||
+SYMBOL(wbuffer_convert, | |||
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_orde | |||
SYMBOL(weak_ptr, std::, <memory>) | SYMBOL(weak_ptr, std::, <memory>) | ||
SYMBOL(weakly_increment | SYMBOL(weakly_increment | ||
SYMBOL(weibull_distribu | SYMBOL(weibull_distribu | ||
-SYMBOL(wfilebuf, std::, | +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, | SYMBOL(wformat_context, | ||
@@ -3348,6 +3383,7 @@ SYMBOL(wstreampo | |||
SYMBOL(wstreampos, std::, <iosfwd>) | SYMBOL(wstreampos, std::, <iosfwd>) | ||
SYMBOL(wstring, std::, <string>) | SYMBOL(wstring, std::, <string>) | ||
SYMBOL(wstring_convert, | SYMBOL(wstring_convert, | ||
+SYMBOL(wstring_convert, | |||
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_la | SYMBOL(month_weekday_la | ||
SYMBOL(nanoseconds, std::chrono::, <chrono>) | SYMBOL(nanoseconds, std::chrono::, <chrono>) | ||
SYMBOL(nonexistent_loca | SYMBOL(nonexistent_loca | ||
@@ -3605,6 +3642,7 @@ SYMBOL(chunk_vie | |||
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 | SYMBOL(const_iterator_t | ||
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_s | |||
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, | SYMBOL(drop_while_view, | ||
+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_ | SYMBOL(enable_borrowed_ | ||
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 | |||
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 | |||
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>) |
@@ -122,7 +122,7 @@ if(LLVM_BUILD_EX | |||
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_RUNT | foreach(runtime ${COMPILER_RT_RUNT | ||
get_ext_project_ | get_ext_project_ | ||
add_custom_targe | add_custom_targe |
@@ -507,3 +507,11 @@ typedef bool bool9 __attribute__((e | |||
// both-error@+2 {{constexpr variable 'bad_bool9_to_sho | // both-error@+2 {{constexpr variable 'bad_bool9_to_sho | ||
// 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_sho | constexpr unsigned short bad_bool9_to_sho | ||
+ | |||
+// 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 | |||
+// both-note@+1 {{read of temporary whose lifetime has ended}} | |||
+constexpr nullptr_t test_nullptr_bad |
@@ -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_wmemcm | |||
+ static_assert(__builtin_wmemcm | |||
+ static_assert(__builtin_wmemcm | |||
+#if __WCHAR_WIDTH__ == 32 | |||
+ static_assert(__builtin_wmemcm | |||
+ (wchar_t)-1U >> 31); | |||
+#endif | |||
+ static_assert(__builtin_wmemcm | |||
+ // both-note {{dereferenced one-past-the-end}} | |||
+ static_assert(__builtin_wmemcm | |||
+ static_assert(__builtin_wmemcm | |||
+ static_assert(__builtin_wmemcm | |||
+ static_assert(__builtin_wmemcm | |||
} | } |
@@ -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; // | + 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}} \ | ||
- // | + // both-note {{read of variable whose lifetime has ended}} | ||
} | } | ||
namespace VoidReturn { | namespace VoidReturn { |
@@ -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; // | + c = 1 << -1; // all-warning {{shift count is negative}} \ | ||
- // | + // 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; // | + c = 1 << (unsigned)-1; // all-warning {{shift count >= width of type}} \ | ||
- // | + // 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}} |
@@ -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 | // CHECK-NEXT: AlwaysInlineAttr | ||
+// 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_r | |||
+// CHECK-NEXT: MemberExpr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> '__hlsl_resource_ | |||
+// 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 | |||
+ | |||
// CHECK: ClassTemplateSpe | // CHECK: ClassTemplateSpe | ||
// CHECK: TemplateArgument | // CHECK: TemplateArgument |
@@ -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) | |||
+ ; | |||
} | } |
@@ -1,16 +1,72 @@ | |||
// RUN: %clang_analyze_cc | // RUN: %clang_analyze_cc | ||
-struct A { | +#include "mock-types.h" | ||
- static void b(); | + | ||
+namespace WTF { | |||
+ | |||
+namespace Detail { | |||
+ | |||
+template<typename Out, typename... In> | |||
+class CallableWrapperB | |||
+public: | |||
+ virtual ~CallableWrapperB | |||
+ virtual Out call(In...) = 0; | |||
+}; | |||
+ | |||
+template<typename, typename, typename...> class CallableWrapper; | |||
+ | |||
+template<typename CallableType, typename Out, typename... In> | |||
+class CallableWrapper : public CallableWrapperB | |||
+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::CallableWrapperB | |||
+ | |||
+template <typename Out, typename... In> | |||
+class Function<Out(In...)> { | |||
+public: | |||
+ using Impl = Detail::CallableWrapperB | |||
+ | |||
+ Function() = default; | |||
+ | |||
+ template<typename FunctionType> | |||
+ Function(FunctionType f) | |||
+ : m_callableWrappe | |||
+ | |||
+ Out operator()(In... in) const { return m_callableWrappe | |||
+ explicit operator bool() const { return !!m_callableWrappe | |||
+ | |||
+private: | |||
+ enum AdoptTag { Adopt }; | |||
+ Function(Impl* impl, AdoptTag) | |||
+ : m_callableWrappe | |||
+ { | |||
+ } | |||
+ | |||
+ friend Function adopt<Out, In...>(Impl*); | |||
+ | |||
+ std::unique_ptr<Impl> m_callableWrappe | |||
}; | }; | ||
-struct RefCountable { | +template<typename Out, typename... In> Function<Out(In...)> adopt(Detail::CallableWrapperB | ||
- 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 | |||
}; | }; | ||
trivial_lambda(1); | trivial_lambda(1); | ||
} | } | ||
+ | |||
+void callFunctionOpaq | |||
+void callFunction(WTF::Function<void()>&& function) { | |||
+ someFunction(); | |||
+ function(); | |||
+} | |||
+ | |||
+void lambda_converted | |||
+{ | |||
+ callFunction([&]() { | |||
+ obj->method(); | |||
+ // expected-warning@-1{{Implicitly captured raw-pointer 'obj' to ref-counted type or CheckedPtr-capable type is unsafe [webkit.UncountedLambdaC | |||
+ }); | |||
+ callFunctionOpaq | |||
+ obj->method(); | |||
+ // expected-warning@-1{{Implicitly captured raw-pointer 'obj' to ref-counted type or CheckedPtr-capable type is unsafe [webkit.UncountedLambdaC | |||
+ }); | |||
+} |
@@ -1,6 +1,7 @@ | |||
// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify=expected,cxx11,c | // RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify=expected,cxx11,c | ||
// 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 | |||
+struct X { | |||
+ union { | |||
+ int variant_member; | |||
+ }; | |||
+ struct { // expected-warning {{anonymous structs are a GNU extension}} | |||
+ int anonymous_struct | |||
+ }; | |||
+ int data_member; | |||
+ static int static_data_memb | |||
+ 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_ | |||
+ static void static_member_fu | |||
+#if __cplusplus >= 202302L | |||
+ void explicit_object_ | |||
+#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 | |||
+ (void) get_X().data_member; | |||
+ (void) get_X().static_data_memb | |||
+ // 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_ | |||
+ (void) get_X().static_member_fu | |||
+ // expected-warning@-1 {{ignoring return value of function declared with 'nodiscard' attribute}} | |||
+#if __cplusplus >= 202302L | |||
+ (void) get_X().explicit_object_ | |||
+#endif | |||
+} | |||
+} // namespace discarded_member |
@@ -30,7 +30,25 @@ using U2 = decltype(&main); | |||
#endif | #endif | ||
} // namespace cwg2811 | } // namespace cwg2811 | ||
-namespace | +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); |
@@ -185,3 +185,23 @@ template<typenam | |||
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 |
@@ -0,0 +1,316 @@ | |||
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_c | |||
+// 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,instcomb | |||
+// 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,instcomb | |||
+// RUN: %clang_cc1 -DSME_OVERLOADED_ | |||
+// RUN: %clang_cc1 -DSME_OVERLOADED_ | |||
+// 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_F | |||
+#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_ | |||
+// 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_l | |||
+// 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_ | |||
+ SME_ACLE_FUNC(svmla_lane_za16, | |||
+} | |||
+ | |||
+// CHECK-LABEL: define dso_local void @test_svmla_lane_ | |||
+// 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_l | |||
+// 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_ | |||
+ SME_ACLE_FUNC(svmla_lane_za16, | |||
+} | |||
+ | |||
+// CHECK-LABEL: define dso_local void @test_svmla_lane_ | |||
+// 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_l | |||
+// 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_ | |||
+ SME_ACLE_FUNC(svmla_lane_za16, | |||
+} | |||
+ | |||
+// FMLALL (indexed) | |||
+ | |||
+// CHECK-LABEL: define dso_local void @test_svmla_lane_ | |||
+// 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_l | |||
+// 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_ | |||
+ SME_ACLE_FUNC(svmla_lane_za32, | |||
+} | |||
+ | |||
+// CHECK-LABEL: define dso_local void @test_svmla_lane_ | |||
+// 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_l | |||
+// 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_ | |||
+ SME_ACLE_FUNC(svmla_lane_za32, | |||
+} | |||
+ | |||
+// CHECK-LABEL: define dso_local void @test_svmla_lane_ | |||
+// 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_l | |||
+// 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_ | |||
+ SME_ACLE_FUNC(svmla_lane_za32, | |||
+} | |||
+ | |||
+// FMLAL (single) | |||
+ | |||
+// CHECK-LABEL: define dso_local void @test_svmla_singl | |||
+// 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_s | |||
+// 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_singl | |||
+ SME_ACLE_FUNC(svmla,_single,_z | |||
+} | |||
+ | |||
+// CHECK-LABEL: define dso_local void @test_svmla_singl | |||
+// 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_s | |||
+// 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_singl | |||
+ SME_ACLE_FUNC(svmla,_single,_z | |||
+} | |||
+ | |||
+// CHECK-LABEL: define dso_local void @test_svmla_singl | |||
+// 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_s | |||
+// 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_singl | |||
+ SME_ACLE_FUNC(svmla,_single,_z | |||
+} | |||
+ | |||
+// FMLALL (single) | |||
+ | |||
+// CHECK-LABEL: define dso_local void @test_svmla_singl | |||
+// 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_s | |||
+// 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_singl | |||
+ SME_ACLE_FUNC(svmla,_single,_z | |||
+} | |||
+ | |||
+// CHECK-LABEL: define dso_local void @test_svmla_singl | |||
+// 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_s | |||
+// 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_singl | |||
+ SME_ACLE_FUNC(svmla,_single,_z | |||
+} | |||
+ | |||
+// CHECK-LABEL: define dso_local void @test_svmla_singl | |||
+// 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_s | |||
+// 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_singl | |||
+ SME_ACLE_FUNC(svmla,_single,_z | |||
+} | |||
+ | |||
+// FMLAL (multi) | |||
+ | |||
+// CHECK-LABEL: define dso_local void @test_svmla_multi | |||
+// 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_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 | |||
+ SME_ACLE_FUNC(svmla_za16,_mf8, | |||
+} | |||
+ | |||
+// CHECK-LABEL: define dso_local void @test_svmla_multi | |||
+// 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_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 | |||
+ SME_ACLE_FUNC(svmla_za16,_mf8, | |||
+} | |||
+ | |||
+// FMLALL (multi) | |||
+ | |||
+// CHECK-LABEL: define dso_local void @test_svmla_multi | |||
+// 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_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 | |||
+ SME_ACLE_FUNC(svmla_za32,_mf8, | |||
+} | |||
+ | |||
+// CHECK-LABEL: define dso_local void @test_svmla_multi | |||
+// 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_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 | |||
+ SME_ACLE_FUNC(svmla_za32,_mf8, | |||
+} |
@@ -1,18 +1,18 @@ | |||
// NOTE: Assertions have been autogenerated by utils/update_cc_test_c | // NOTE: Assertions have been autogenerated by utils/update_cc_test_c | ||
// 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,instcomb | // 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,instcomb | ||
// 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,instcomb | // 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,instcomb | ||
// RUN: %clang_cc1 -DSVE_OVERLOADED_ | // RUN: %clang_cc1 -DSVE_OVERLOADED_ | ||
// RUN: %clang_cc1 -DSVE_OVERLOADED_ | // RUN: %clang_cc1 -DSVE_OVERLOADED_ | ||
// 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_F | #ifdef SVE_OVERLOADED_F | ||
-#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_ | // CHECK-LABEL: define dso_local void @test_svdot_lane_ | ||
@@ -32,7 +32,7 @@ | |||
void test_svdot_lane_ | void test_svdot_lane_ | ||
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_ | // CHECK-LABEL: define dso_local void @test_svdot_lane_ | ||
@@ -52,7 +52,7 @@ void test_svdot_lane_ | |||
void test_svdot_lane_ | void test_svdot_lane_ | ||
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_ | // CHECK-LABEL: define dso_local void @test_svdot_lane_ | ||
@@ -72,7 +72,7 @@ void test_svdot_lane_ | |||
void test_svdot_lane_ | void test_svdot_lane_ | ||
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_ | // CHECK-LABEL: define dso_local void @test_svdot_lane_ | ||
@@ -92,5 +92,165 @@ void test_svdot_lane_ | |||
void test_svdot_lane_ | void test_svdot_lane_ | ||
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_singl | |||
+// 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_s | |||
+// 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_singl | |||
+ svmfloat8_t zm, fpm_t fpmr) | |||
+ __arm_streaming __arm_inout("za") { | |||
+ SVE_ACLE_FUNC(svdot,_single,_z | |||
+} | |||
+ | |||
+// CHECK-LABEL: define dso_local void @test_svdot_singl | |||
+// 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_s | |||
+// 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_singl | |||
+ svmfloat8_t zm, fpm_t fpmr) | |||
+ __arm_streaming __arm_inout("za") { | |||
+ SVE_ACLE_FUNC(svdot,_single,_z | |||
+} | |||
+ | |||
+// CHECK-LABEL: define dso_local void @test_svdot_multi | |||
+// 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_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 | |||
+ svmfloat8x2_t zm, fpm_t fpmr) | |||
+ __arm_streaming __arm_inout("za") { | |||
+ SVE_ACLE_FUNC(svdot,,_za32,_mf | |||
+} | |||
+ | |||
+// CHECK-LABEL: define dso_local void @test_svdot_multi | |||
+// 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_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 | |||
+ svmfloat8x4_t zm, fpm_t fpmr) | |||
+ __arm_streaming __arm_inout("za") { | |||
+ SVE_ACLE_FUNC(svdot,,_za32,_mf | |||
+} | |||
+ | |||
+// CHECK-LABEL: define dso_local void @test_svdot_singl | |||
+// 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_s | |||
+// 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_singl | |||
+ svmfloat8_t zm, fpm_t fpmr) | |||
+ __arm_streaming __arm_inout("za") { | |||
+ SVE_ACLE_FUNC(svdot,_single,_z | |||
+} | |||
+ | |||
+// CHECK-LABEL: define dso_local void @test_svdot_singl | |||
+// 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_s | |||
+// 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_singl | |||
+ svmfloat8_t zm, fpm_t fpmr) | |||
+ __arm_streaming __arm_inout("za") { | |||
+ SVE_ACLE_FUNC(svdot,_single,_z | |||
+} | |||
+ | |||
+// CHECK-LABEL: define dso_local void @test_svdot_multi | |||
+// 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_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 | |||
+ svmfloat8x2_t zm, fpm_t fpmr) | |||
+ __arm_streaming __arm_inout("za") { | |||
+ SVE_ACLE_FUNC(svdot,,_za16,_mf | |||
+} | |||
+ | |||
+// CHECK-LABEL: define dso_local void @test_svdot_multi | |||
+// 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_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 | |||
+ svmfloat8x4_t zm, fpm_t fpmr) | |||
+ __arm_streaming __arm_inout("za") { | |||
+ SVE_ACLE_FUNC(svdot,,_za16,_mf | |||
} | } |
@@ -0,0 +1,80 @@ | |||
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_c | |||
+ | |||
+// 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,instcomb | |||
+// 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,instcomb | |||
+// RUN: %clang_cc1 -DSVE_OVERLOADED_ | |||
+// RUN: %clang_cc1 -DSVE_OVERLOADED_ | |||
+// 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_F | |||
+#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 | |||
+// 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_ | |||
+// 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 | |||
+ svmfloat8_t zm, | |||
+ fpm_t fpmr) __arm_streaming | |||
+ __arm_inout("za") { | |||
+ SVE_ACLE_FUNC(svvdot_lane_za16 | |||
+} | |||
+ | |||
+// CHECK-LABEL: define dso_local void @test_svvdotb_lan | |||
+// 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 | |||
+// 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_lan | |||
+ svmfloat8_t zm, | |||
+ fpm_t fpmr) __arm_streaming | |||
+ __arm_inout("za") { | |||
+ SVE_ACLE_FUNC(svvdotb_lane_za3 | |||
+} | |||
+ | |||
+// CHECK-LABEL: define dso_local void @test_svvdott_lan | |||
+// 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 | |||
+// 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_lan | |||
+ svmfloat8_t zm, | |||
+ fpm_t fpmr) __arm_streaming | |||
+ __arm_inout("za") { | |||
+ SVE_ACLE_FUNC(svvdott_lane_za3 | |||
+} |
@@ -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 | +// 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 | +// 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]] |
@@ -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_globa | int __attribute__((no_sanitize("memtag"))) attributed_globa | ||
int __attribute__((disable_sanitize | int __attribute__((disable_sanitize | ||
int ignorelisted_glo | int ignorelisted_glo | ||
@@ -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_globa | // CHECK: @{{.*}}attributed_globa | ||
// CHECK-NOT: sanitize_memtag | // CHECK-NOT: sanitize_memtag | ||
// CHECK: @{{.*}}disable_instrume | // CHECK: @{{.*}}disable_instrume | ||
@@ -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"{{.*}} | +// 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 |
@@ -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- |
@@ -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 | |||
+int global1 = 0; | |||
+int global2 = *(int *)((char *)&global1 + 1); | |||
+// WITHOUT: @__cxx_global_var | |||
+// BL: @__cxx_global_var | |||
+// TYSAN: @__cxx_global_var | |||
+ | |||
+// 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 |
@@ -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 | +// 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 | +// 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 | +// 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 |
@@ -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_lambda | //CHECK: %call = call noundef i32 @"_ZZ11test_lambda | ||
//CHECK: ret void | //CHECK: ret void | ||
//CHECK: } | //CHECK: } |
@@ -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(); |
@@ -368,3 +368,36 @@ void test_use_matrix_ | |||
selector<2> r5 = use_matrix_3(m1); | selector<2> r5 = use_matrix_3(m1); | ||
} | } | ||
+ | |||
+// CHECK-LABEL: define void @_Z22test_pseudo_ | |||
+// 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_destr | |||
+// CHECK-NEXT: %1 = load <12 x float>, ptr %b, align 4 | |||
+// CHECK-NEXT: call void @_Z17pseudo_destr | |||
+// CHECK-NEXT: ret void | |||
+ | |||
+// CHECK-LABEL: define linkonce_odr void @_Z17pseudo_destr | |||
+// 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_destr | |||
+// 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_destructo | |||
+ t.~T(); | |||
+} | |||
+ | |||
+void test_pseudo_dest | |||
+ dx5x5_t a; | |||
+ fx3x4_t b; | |||
+ pseudo_destructo | |||
+ pseudo_destructo | |||
+} |
@@ -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_t | |||
+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_t | |||
+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_t | |||
+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; | |||
+} |
@@ -647,7 +647,7 @@ void (Multiple::*conv | |||
// CHECK: br i1 %{{.*}} label %{{.*}}, label %{{.*}} | // CHECK: br i1 %{{.*}} label %{{.*}}, label %{{.*}} | ||
// | // | ||
// memptr.convert: ; preds = %entry | // memptr.convert: ; preds = %entry | ||
-// CHECK: insertvalue { ptr, i32 } | +// 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 | |||
// 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 } | +// 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 |
@@ -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_ | |||
+// 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_ | |||
+// CHECK-DXIL-NEXT: store target("dx.TypedBuffer", float, 1, 0, 0) %Buf_h.i, ptr @Buf, align 4 | |||
+ | |||
+// CHECK-NEXT: ret void | |||
+} |
@@ -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_ | // CHECK: %[[INPTR:.*]] = call noundef nonnull align 4 dereferenceable(4) ptr @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_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_ | // CHECK: %[[OUTPTR:.*]] = call noundef nonnull align 4 dereferenceable(4) ptr @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_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_ | |||
+ // CHECK: %[[LOAD:.*]] = load i32, ptr %[[INPTR]] | |||
+ // CHECK: %[[OUTPTR:.*]] = call noundef nonnull align 4 dereferenceable(4) ptr @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_i32_ | |||
+ // CHECK: store i32 %[[LOAD]], ptr %[[OUTPTR]] | |||
+ Out[GI] = In.Load(GI); | |||
} | } |
@@ -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 WaveActiveAllTru | |||
+} |
@@ -73,3 +73,81 @@ kernel void foo_wo_pipe(writ | |||
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_ima | // CHECK-SPIR-LABEL: @{{_Z4bad114ocl_ima | ||
// CHECK-AMDGCN-LABEL: @{{_Z4bad114ocl_ima | // CHECK-AMDGCN-LABEL: @{{_Z4bad114ocl_ima | ||
+ | |||
+ | |||
+// CHECK-AMDGCN: define dso_local void @_Z20img_type_man | |||
+__attribute__((overloadable)) | |||
+void img_type_mangle_ | |||
+ | |||
+// CHECK-AMDGCN: define dso_local void @_Z20img_type_man | |||
+__attribute__((overloadable)) | |||
+void img_type_mangle_ | |||
+ | |||
+// CHECK-AMDGCN: define dso_local void @_Z20img_type_man | |||
+__attribute__((overloadable)) | |||
+void img_type_mangle_ | |||
+ | |||
+ | |||
+// CHECK-AMDGCN: define dso_local void @_Z20img_type_man | |||
+__attribute__((overloadable)) | |||
+void img_type_mangle_ | |||
+ | |||
+// CHECK-AMDGCN: define dso_local void @_Z20img_type_man | |||
+__attribute__((overloadable)) | |||
+void img_type_mangle_ | |||
+ | |||
+// CHECK-AMDGCN: define dso_local void @_Z20img_type_man | |||
+__attribute__((overloadable)) | |||
+void img_type_mangle_ | |||
+ | |||
+ | |||
+// CHECK-AMDGCN: define dso_local void @_Z20img_type_man | |||
+__attribute__((overloadable)) | |||
+void img_type_mangle_ | |||
+ | |||
+// CHECK-AMDGCN: define dso_local void @_Z20img_type_man | |||
+__attribute__((overloadable)) | |||
+void img_type_mangle_ | |||
+ | |||
+// CHECK-AMDGCN: define dso_local void @_Z20img_type_man | |||
+__attribute__((overloadable)) | |||
+void img_type_mangle_ | |||
+ | |||
+ | |||
+// CHECK-AMDGCN: define dso_local void @_Z20img_type_man | |||
+__attribute__((overloadable)) | |||
+void img_type_mangle_ | |||
+ | |||
+// CHECK-AMDGCN: define dso_local void @_Z20img_type_man | |||
+__attribute__((overloadable)) | |||
+void img_type_mangle_ | |||
+ | |||
+// CHECK-AMDGCN: define dso_local void @_Z20img_type_man | |||
+__attribute__((overloadable)) | |||
+void img_type_mangle_ | |||
+ | |||
+ | |||
+// CHECK-AMDGCN: define dso_local void @_Z20img_type_man | |||
+__attribute__((overloadable)) | |||
+void img_type_mangle_ | |||
+ | |||
+// CHECK-AMDGCN: define dso_local void @_Z20img_type_man | |||
+__attribute__((overloadable)) | |||
+void img_type_mangle_ | |||
+ | |||
+// CHECK-AMDGCN: define dso_local void @_Z20img_type_man | |||
+__attribute__((overloadable)) | |||
+void img_type_mangle_ | |||
+ | |||
+ | |||
+// CHECK-AMDGCN: define dso_local void @_Z20img_type_man | |||
+__attribute__((overloadable)) | |||
+void img_type_mangle_ | |||
+ | |||
+// CHECK-AMDGCN: define dso_local void @_Z20img_type_man | |||
+__attribute__((overloadable)) | |||
+void img_type_mangle_ | |||
+ | |||
+// CHECK-AMDGCN: define dso_local void @_Z20img_type_man | |||
+__attribute__((overloadable)) | |||
+void img_type_mangle_ |
@@ -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 | +// 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: |
@@ -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 | +// 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 | +// 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 | +// 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 | +// 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 | +// CHECK-NEXT: zvl1024b 1.0 'Zvl1024b' (Minimum Vector Length 1024) | ||
-// CHECK-NEXT: zvl128b 1.0 | +// CHECK-NEXT: zvl128b 1.0 'Zvl128b' (Minimum Vector Length 128) | ||
-// CHECK-NEXT: zvl16384b 1.0 | +// CHECK-NEXT: zvl16384b 1.0 'Zvl16384b' (Minimum Vector Length 16384) | ||
-// CHECK-NEXT: zvl2048b 1.0 | +// CHECK-NEXT: zvl2048b 1.0 'Zvl2048b' (Minimum Vector Length 2048) | ||
-// CHECK-NEXT: zvl256b 1.0 | +// CHECK-NEXT: zvl256b 1.0 'Zvl256b' (Minimum Vector Length 256) | ||
-// CHECK-NEXT: zvl32768b 1.0 | +// CHECK-NEXT: zvl32768b 1.0 'Zvl32768b' (Minimum Vector Length 32768) | ||
-// CHECK-NEXT: zvl32b 1.0 | +// CHECK-NEXT: zvl32b 1.0 'Zvl32b' (Minimum Vector Length 32) | ||
-// CHECK-NEXT: zvl4096b 1.0 | +// CHECK-NEXT: zvl4096b 1.0 'Zvl4096b' (Minimum Vector Length 4096) | ||
-// CHECK-NEXT: zvl512b 1.0 | +// CHECK-NEXT: zvl512b 1.0 'Zvl512b' (Minimum Vector Length 512) | ||
-// CHECK-NEXT: zvl64b 1.0 | +// CHECK-NEXT: zvl64b 1.0 'Zvl64b' (Minimum Vector Length 64) | ||
-// CHECK-NEXT: zvl65536b 1.0 | +// CHECK-NEXT: zvl65536b 1.0 'Zvl65536b' (Minimum Vector Length 65536) | ||
-// CHECK-NEXT: zvl8192b 1.0 | +// 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 | +// 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 | +// 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' | +// 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 | +// 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) |
@@ -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- | +// 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_d | // RUN: -resource-dir=%S/Inputs/empty_resource_d | ||
// 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_d | |||
+// 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- | +// 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- | +// CHECK-ASAN-LINUX-CXX-SAME: "--export-dynamic" | ||
-// CHECK-ASAN-LINUX- | +// CHECK-ASAN-LINUX-CXX-SAME: stdc++ | ||
-// CHECK-ASAN-LINUX-CXX- | +// 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_d | |||
+// 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_d | |||
+// 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_d | |||
+// 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_dynami | |||
+// 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- | +// 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 | // CHECK-UBSAN-LINUX-NOT: libclang_rt.ubsan_standalone | ||
// CHECK-UBSAN-LINUX-NOT: "-lstdc++" | // CHECK-UBSAN-LINUX-NOT: "-lstdc++" | ||
// CHECK-UBSAN-LINUX: "-lpthread" | // CHECK-UBSAN-LINUX: "-lpthread" | ||
-// CHECK-UBSAN- | +// 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- | +// 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- | +// 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- | +// CHECK-ASAN-UBSAN-LINUX: "-lresolv" | ||
// RUN: %clangxx -fsanitize=address,undefine | // RUN: %clangxx -fsanitize=address,undefine | ||
// 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- | +// CHECK-ASAN-UBSAN-LINUX-CXX: "-lresolv" | ||
// RUN: %clangxx -fsanitize=memory,undefined | // RUN: %clangxx -fsanitize=memory,undefined | ||
// 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- | +// 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- | +// 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- | +// 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- | +// 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 | // CHECK-UBSAN-COV-LINUX: "--whole-archive" "{{.*}}libclang_rt.ubsan_standalone | ||
// 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- | +// 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 | // CHECK-COV-LINUX: "--whole-archive" "{{.*}}libclang_rt.ubsan_standalone | ||
// CHECK-COV-LINUX-NOT: "-lstdc++" | // CHECK-COV-LINUX-NOT: "-lstdc++" | ||
// CHECK-COV-LINUX: "-lpthread" | // CHECK-COV-LINUX: "-lpthread" | ||
-// CHECK-COV- | +// 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- | +// 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- | +// 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- | +// 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- | +// 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 \ |
@@ -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' |
@@ -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/ | +// 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", |
@@ -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() |
@@ -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 | |||
+}; | |||
+ | |||
+template <class RequestType, class ResponseType> | |||
+class CallbackUnaryHan | |||
+ public: | |||
+ explicit CallbackUnaryHan | |||
+ | |||
+ void RunHandler(const HandlerParameter | |||
+ void *call = nullptr; | |||
+ (void)[call](bool){}; | |||
+ } | |||
+}; | |||
+ | |||
+//--- foo1.h | |||
+// expected-no-diagnostics | |||
+#pragma once | |||
+ | |||
+#include "functional" | |||
+ | |||
+#include "foo.h" | |||
+ | |||
+class A; | |||
+ | |||
+class ClientAsyncRespo | |||
+ 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]] CallbackUnaryHan | |||
+}; | |||
+ | |||
+//--- 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 CallbackUnaryHan | |||
+ | |||
+class s {}; | |||
+class hs final : public a<s> { | |||
+ explicit hs() {} | |||
+}; |
@@ -81,7 +81,7 @@ | |||
#error "wrong value for __cpp_named_char | #error "wrong value for __cpp_named_char | ||
#endif | #endif | ||
-#if check(explicit_this_parameter, 0, 0, 0, 0, 0, | +#if check(explicit_this_parameter, 0, 0, 0, 0, 0, 202110L, 202110L) | ||
#error "wrong value for __cpp_explicit_t | #error "wrong value for __cpp_explicit_t | ||
#endif | #endif | ||
@@ -75,7 +75,8 @@ int foo(ObjCClass *c) { | |||
// CHECK: !DICompositeType(tag: DW_TAG_structure | // CHECK: !DICompositeType(tag: DW_TAG_structure | ||
// 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 | // CHECK-NOT: !DICompositeType(tag: DW_TAG_structure | ||
// CHECK: !DICompositeType(tag: DW_TAG_enumerati | // CHECK: !DICompositeType(tag: DW_TAG_enumerati |
@@ -39,6 +39,7 @@ | |||
// CHECK: !DICompositeType(tag: DW_TAG_structure | // CHECK: !DICompositeType(tag: DW_TAG_structure | ||
// CHECK-SAME: scope: ![[MODULE]], | // CHECK-SAME: scope: ![[MODULE]], | ||
+// CHECK-SAME: runtimeLang: DW_LANG_ObjC | |||
// CHECK: !DICompositeType(tag: DW_TAG_structure | // CHECK: !DICompositeType(tag: DW_TAG_structure | ||
// CHECK-SAME: scope: ![[MODULE]], | // CHECK-SAME: scope: ![[MODULE]], |
@@ -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_IN | |||
+ | |||
+#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_IN | |||
+ | |||
+#endif | |||
+ | |||
+//--- internal.h | |||
+#ifndef INTERNAL_H | |||
+#define INTERNAL_H | |||
+ | |||
+#include "strong_int.h" | |||
+ | |||
+DEFINE_STRONG_IN | |||
+DEFINE_STRONG_IN | |||
+ | |||
+#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_IN | |||
+ struct type_name##_strong_int_tag_ | |||
+ typedef ::util_intops::StrongInt2<type_name##_strong_int_tag_ | |||
+ type_name; | |||
+ | |||
+#endif | |||
+ | |||
+//--- main.cc | |||
+// expected-no-diagnostics | |||
+#include "foo.h" | |||
+ | |||
+#include "strong_int.h" | |||
+ | |||
+DEFINE_STRONG_IN | |||
+void partial(ArchiveId2 id) { | |||
+ CALL_HASH(id); | |||
+} |
@@ -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; | |||
+} | |||
+ |
@@ -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 | +// 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 | +// 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]] |
@@ -201,9 +201,7 @@ void secondMapNameInC | |||
// DEBUG: store ptr @[[NAME:.offload_mapnames | // DEBUG: store ptr @[[NAME:.offload_mapnames | ||
// CHECK-NOT: store ptr @[[NAME:.offload_mapnames | // CHECK-NOT: store ptr @[[NAME:.offload_mapnames | ||
-// DEBUG: void @.omp_mapper._ZTS2S3.id(ptr {{.*}}, ptr {{.*}}, ptr {{.*}}, i64 {{.*}}, i64 {{.*}}, ptr noundef [[ | +// 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_mappe | // DEBUG: call void @__tgt_push_mappe | ||
#endif | #endif |
@@ -186,9 +186,7 @@ void secondMapNameInC | |||
// DEBUG: store ptr @[[NAME:.offload_mapnames | // DEBUG: store ptr @[[NAME:.offload_mapnames | ||
// CHECK-NOT: store ptr @[[NAME:.offload_mapnames | // CHECK-NOT: store ptr @[[NAME:.offload_mapnames | ||
-// DEBUG: void @.omp_mapper._ZTS2S3.id(ptr {{.*}}, ptr {{.*}}, ptr {{.*}}, i64 {{.*}}, i64 {{.*}}, ptr noundef [[ | +// 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_mappe | // DEBUG: call void @__tgt_push_mappe | ||
#endif | #endif |
@@ -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_IS | // CHECK-NEXT: [[OMP_ARRAYINIT_IS | ||
-// CHECK-NEXT: [[TMP14:%.*]] = and i64 [[ | +// CHECK-NEXT: [[TMP14:%.*]] = and i64 [[TMP4]], 8 | ||
-// CHECK-NEXT: [[TMP15:%.*]] = icmp ne ptr [[ | +// CHECK-NEXT: [[TMP15:%.*]] = icmp ne ptr [[TMP1]], [[TMP2]] | ||
-// CHECK-NEXT: [[TMP16:%.*]] = and i64 [[ | +// 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_IS | // CHECK-NEXT: [[TMP19:%.*]] = or i1 [[OMP_ARRAYINIT_IS | ||
@@ -141,15 +123,15 @@ void foo() { | |||
// CHECK-NEXT: br i1 [[TMP20]], label [[DOTOMP_ARRAY__IN | // CHECK-NEXT: br i1 [[TMP20]], label [[DOTOMP_ARRAY__IN | ||
// 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 [[ | +// 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 [[ | +// 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_HEA | // CHECK-NEXT: br label [[OMP_ARRAYMAP_HEA | ||
// CHECK: omp.arraymap.head: | // CHECK: omp.arraymap.head: | ||
-// CHECK-NEXT: [[OMP_ARRAYMAP_ISEMPTY:%.*]] = icmp eq ptr [[ | +// CHECK-NEXT: [[OMP_ARRAYMAP_ISEMPTY:%.*]] = icmp eq ptr [[TMP2]], [[TMP11]] | ||
// CHECK-NEXT: br i1 [[OMP_ARRAYMAP_ISE | // CHECK-NEXT: br i1 [[OMP_ARRAYMAP_ISE | ||
// CHECK: omp.arraymap.body: | // CHECK: omp.arraymap.body: | ||
-// CHECK-NEXT: [[OMP_ARRAYMAP_PTRCURRENT:%.*]] = phi ptr [ [[ | +// 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_PTR | // CHECK-NEXT: [[E:%.*]] = getelementptr inbounds nuw [[STRUCT_D]], ptr [[OMP_ARRAYMAP_PTR | ||
// CHECK-NEXT: [[F:%.*]] = getelementptr inbounds nuw [[STRUCT_D]], ptr [[OMP_ARRAYMAP_PTR | // CHECK-NEXT: [[F:%.*]] = getelementptr inbounds nuw [[STRUCT_D]], ptr [[OMP_ARRAYMAP_PTR | ||
// CHECK-NEXT: [[H:%.*]] = getelementptr inbounds nuw [[STRUCT_D]], ptr [[OMP_ARRAYMAP_PTR | // CHECK-NEXT: [[H:%.*]] = getelementptr inbounds nuw [[STRUCT_D]], ptr [[OMP_ARRAYMAP_PTR | ||
@@ -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 [[ | +// 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 [[ | +// 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_E | // CHECK-NEXT: br i1 [[TMP33]], label [[OMP_TYPE_ALLOC:%.*]], label [[OMP_TYPE_ALLOC_E | ||
// 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 [[ | +// 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, | // CHECK-NEXT: [[TMP39:%.*]] = add nuw i64 281474976711171, | ||
-// CHECK-NEXT: [[TMP40:%.*]] = and i64 [[ | +// 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_E | // CHECK-NEXT: br i1 [[TMP41]], label [[OMP_TYPE_ALLOC6:%.*]], label [[OMP_TYPE_ALLOC_E | ||
-// CHECK: omp.type. | +// 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. | +// 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_ELSE | // CHECK-NEXT: br i1 [[TMP43]], label [[OMP_TYPE_TO8:%.*]], label [[OMP_TYPE_TO_ELSE | ||
-// CHECK: omp.type. | +// 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. | +// 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. | +// 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. | +// 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_ELSE | // CHECK-NEXT: [[OMP_MAPTYPE12:%.*]] = phi i64 [ [[TMP42]], [[OMP_TYPE_ALLOC6]] ], [ [[TMP44]], [[OMP_TYPE_TO8]] ], [ [[TMP46]], [[OMP_TYPE_FROM10]] ], [ [[TMP39]], [[OMP_TYPE_TO_ELSE | ||
-// CHECK-NEXT: call void @__tgt_push_mapper_component(ptr [[ | +// 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, | // CHECK-NEXT: [[TMP47:%.*]] = add nuw i64 281474976711171, | ||
-// CHECK-NEXT: [[TMP48:%.*]] = and i64 [[ | +// 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 | // CHECK-NEXT: br i1 [[TMP49]], label [[OMP_TYPE_ALLOC13 | ||
-// CHECK: omp.type. | +// 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. | +// 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_ELSE | // CHECK-NEXT: br i1 [[TMP51]], label [[OMP_TYPE_TO15:%.*]], label [[OMP_TYPE_TO_ELSE | ||
-// CHECK: omp.type. | +// 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. | +// 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. | +// 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. | +// CHECK: omp.type.end13: | ||
// CHECK-NEXT: [[OMP_MAPTYPE19:%.*]] = phi i64 [ [[TMP50]], [[OMP_TYPE_ALLOC13 | // CHECK-NEXT: [[OMP_MAPTYPE19:%.*]] = phi i64 [ [[TMP50]], [[OMP_TYPE_ALLOC13 | ||
-// CHECK-NEXT: call void @.omp_mapper._ZTS1C.default(ptr [[ | +// 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, | // CHECK-NEXT: [[TMP55:%.*]] = add nuw i64 281474976711171, | ||
-// CHECK-NEXT: [[TMP56:%.*]] = and i64 [[ | +// 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 | // CHECK-NEXT: br i1 [[TMP57]], label [[OMP_TYPE_ALLOC20 | ||
-// CHECK: omp.type. | +// 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. | +// 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_ELSE | // CHECK-NEXT: br i1 [[TMP59]], label [[OMP_TYPE_TO22:%.*]], label [[OMP_TYPE_TO_ELSE | ||
-// CHECK: omp.type. | +// 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. | +// 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. | +// 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. | +// CHECK: omp.type.end20: | ||
// CHECK-NEXT: [[OMP_MAPTYPE26:%.*]] = phi i64 [ [[TMP58]], [[OMP_TYPE_ALLOC20 | // CHECK-NEXT: [[OMP_MAPTYPE26:%.*]] = phi i64 [ [[TMP58]], [[OMP_TYPE_ALLOC20 | ||
-// CHECK-NEXT: call void @__tgt_push_mapper_component(ptr [[ | +// 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_NEX | // CHECK-NEXT: [[OMP_ARRAYMAP_NEX | ||
// CHECK-NEXT: [[OMP_ARRAYMAP_ISD | // CHECK-NEXT: [[OMP_ARRAYMAP_ISD | ||
// CHECK-NEXT: br i1 [[OMP_ARRAYMAP_ISD | // CHECK-NEXT: br i1 [[OMP_ARRAYMAP_ISD | ||
// CHECK: omp.arraymap.exit: | // CHECK: omp.arraymap.exit: | ||
// CHECK-NEXT: [[OMP_ARRAYINIT_IS | // CHECK-NEXT: [[OMP_ARRAYINIT_IS | ||
-// CHECK-NEXT: [[TMP63:%.*]] = and i64 [[ | +// CHECK-NEXT: [[TMP63:%.*]] = and i64 [[TMP4]], 8 | ||
// CHECK-NEXT: [[DOTOMP_ARRAY__DE | // CHECK-NEXT: [[DOTOMP_ARRAY__DE | ||
// CHECK-NEXT: [[TMP64:%.*]] = and i1 [[OMP_ARRAYINIT_IS | // CHECK-NEXT: [[TMP64:%.*]] = and i1 [[OMP_ARRAYINIT_IS | ||
// CHECK-NEXT: br i1 [[TMP64]], label [[DOTOMP_ARRAY__DE | // CHECK-NEXT: br i1 [[TMP64]], label [[DOTOMP_ARRAY__DE | ||
// 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 [[ | +// 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 [[ | +// 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: [[ | +// 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_IS | // CHECK-NEXT: [[OMP_ARRAYINIT_IS | ||
-// CHECK-NEXT: [[TMP14:%.*]] = and i64 [[ | +// CHECK-NEXT: [[TMP14:%.*]] = and i64 [[TMP4]], 8 | ||
-// CHECK-NEXT: [[TMP15:%.*]] = icmp ne ptr [[ | +// CHECK-NEXT: [[TMP15:%.*]] = icmp ne ptr [[TMP1]], [[TMP2]] | ||
-// CHECK-NEXT: [[TMP16:%.*]] = and i64 [[ | +// 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_IS | // CHECK-NEXT: [[TMP19:%.*]] = or i1 [[OMP_ARRAYINIT_IS | ||
@@ -302,20 +266,20 @@ void foo() { | |||
// CHECK-NEXT: br i1 [[TMP20]], label [[DOTOMP_ARRAY__IN | // CHECK-NEXT: br i1 [[TMP20]], label [[DOTOMP_ARRAY__IN | ||
// 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 [[ | +// 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 [[ | +// 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_HEA | // CHECK-NEXT: br label [[OMP_ARRAYMAP_HEA | ||
// CHECK: omp.arraymap.head: | // CHECK: omp.arraymap.head: | ||
-// CHECK-NEXT: [[OMP_ARRAYMAP_ISEMPTY:%.*]] = icmp eq ptr [[ | +// CHECK-NEXT: [[OMP_ARRAYMAP_ISEMPTY:%.*]] = icmp eq ptr [[TMP2]], [[TMP11]] | ||
// CHECK-NEXT: br i1 [[OMP_ARRAYMAP_ISE | // CHECK-NEXT: br i1 [[OMP_ARRAYMAP_ISE | ||
// CHECK: omp.arraymap.body: | // CHECK: omp.arraymap.body: | ||
-// CHECK-NEXT: [[OMP_ARRAYMAP_PTRCURRENT:%.*]] = phi ptr [ [[ | +// 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_PTR | // CHECK-NEXT: [[A:%.*]] = getelementptr inbounds nuw [[STRUCT_C]], ptr [[OMP_ARRAYMAP_PTR | ||
-// CHECK-NEXT: [[TMP24:%.*]] = call i64 @__tgt_mapper_num_components(ptr [[ | +// 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 [[ | +// 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_E | // CHECK-NEXT: br i1 [[TMP28]], label [[OMP_TYPE_ALLOC:%.*]], label [[OMP_TYPE_ALLOC_E | ||
// 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 [[ | +// 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_NEX | // CHECK-NEXT: [[OMP_ARRAYMAP_NEX | ||
// CHECK-NEXT: [[OMP_ARRAYMAP_ISD | // CHECK-NEXT: [[OMP_ARRAYMAP_ISD | ||
// CHECK-NEXT: br i1 [[OMP_ARRAYMAP_ISD | // CHECK-NEXT: br i1 [[OMP_ARRAYMAP_ISD | ||
// CHECK: omp.arraymap.exit: | // CHECK: omp.arraymap.exit: | ||
// CHECK-NEXT: [[OMP_ARRAYINIT_IS | // CHECK-NEXT: [[OMP_ARRAYINIT_IS | ||
-// CHECK-NEXT: [[TMP34:%.*]] = and i64 [[ | +// CHECK-NEXT: [[TMP34:%.*]] = and i64 [[TMP4]], 8 | ||
// CHECK-NEXT: [[DOTOMP_ARRAY__DE | // CHECK-NEXT: [[DOTOMP_ARRAY__DE | ||
// CHECK-NEXT: [[TMP35:%.*]] = and i1 [[OMP_ARRAYINIT_IS | // CHECK-NEXT: [[TMP35:%.*]] = and i1 [[OMP_ARRAYINIT_IS | ||
// CHECK-NEXT: br i1 [[TMP35]], label [[DOTOMP_ARRAY__DE | // CHECK-NEXT: br i1 [[TMP35]], label [[DOTOMP_ARRAY__DE | ||
// 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 [[ | +// 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 [[ | +// 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 |
@@ -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 | +#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@+ | + // 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 |
@@ -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) | |||
; | ; | ||
} | } | ||
@@ -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(;;){} |
@@ -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 |
@@ -16,3 +16,37 @@ void test_svmopa(svbo | |||
// 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_ | svmopa_za32_mf8_ | ||
} | } | ||
+ | |||
+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 1844674407370955 | |||
+ svmla_lane_za16_ | |||
+ // expected-error@+1 {{argument value 16 is outside the valid range [0, 15]}} | |||
+ svmla_lane_za16_ | |||
+ | |||
+ // expected-error@+1 {{argument value 1844674407370955 | |||
+ svmla_lane_za16_ | |||
+ // expected-error@+1 {{argument value 16 is outside the valid range [0, 15]}} | |||
+ svmla_lane_za16_ | |||
+ | |||
+ // expected-error@+1 {{argument value 1844674407370955 | |||
+ svmla_lane_za16_ | |||
+ // expected-error@+1 {{argument value 16 is outside the valid range [0, 15]}} | |||
+ svmla_lane_za16_ | |||
+ | |||
+ // expected-error@+1 {{argument value 1844674407370955 | |||
+ svmla_lane_za32_ | |||
+ // expected-error@+1 {{argument value 16 is outside the valid range [0, 15]}} | |||
+ svmla_lane_za32_ | |||
+ | |||
+ // expected-error@+1 {{argument value 1844674407370955 | |||
+ svmla_lane_za32_ | |||
+ // expected-error@+1 {{argument value 16 is outside the valid range [0, 15]}} | |||
+ svmla_lane_za32_ | |||
+ | |||
+ // expected-error@+1 {{argument value 1844674407370955 | |||
+ svmla_lane_za32_ | |||
+ // expected-error@+1 {{argument value 16 is outside the valid range [0, 15]}} | |||
+ svmla_lane_za32_ | |||
+ | |||
+} |
@@ -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_ | |||
+ svmla_lane_za16_ | |||
+ | |||
+ // expected-error@+1 {{'svmla_lane_za16_ | |||
+ svmla_lane_za16_ | |||
+ | |||
+ // expected-error@+1 {{'svmla_lane_za16_ | |||
+ svmla_lane_za16_ | |||
+ | |||
+ // expected-error@+1 {{'svmla_lane_za32_ | |||
+ svmla_lane_za32_ | |||
+ | |||
+ // expected-error@+1 {{'svmla_lane_za32_ | |||
+ svmla_lane_za32_ | |||
+ | |||
+ // expected-error@+1 {{'svmla_lane_za32_ | |||
+ svmla_lane_za32_ | |||
+ | |||
+ // expected-error@+1 {{'svmla_single_za1 | |||
+ svmla_single_za1 | |||
+ | |||
+ // expected-error@+1 {{'svmla_single_za1 | |||
+ svmla_single_za1 | |||
+ | |||
+ // expected-error@+1 {{'svmla_single_za1 | |||
+ svmla_single_za1 | |||
+ | |||
+ // expected-error@+1 {{'svmla_single_za3 | |||
+ svmla_single_za3 | |||
+ | |||
+ // expected-error@+1 {{'svmla_single_za3 | |||
+ svmla_single_za3 | |||
+ | |||
+ // expected-error@+1 {{'svmla_single_za3 | |||
+ svmla_single_za3 | |||
+ | |||
+ // expected-error@+1 {{'svmla_za16_mf8_v | |||
+ svmla_za16_mf8_v | |||
+ | |||
+ // expected-error@+1 {{'svmla_za16_mf8_v | |||
+ svmla_za16_mf8_v | |||
+ | |||
+ // expected-error@+1 {{'svmla_za32_mf8_v | |||
+ svmla_za32_mf8_v | |||
+ | |||
+ // expected-error@+1 {{'svmla_za32_mf8_v | |||
+ svmla_za32_mf8_v | |||
+} |
@@ -14,6 +14,22 @@ void test_features(ui | |||
svdot_lane_za16_ | svdot_lane_za16_ | ||
[diff truncated] |