diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index 0e24d6132b4cb032d66f505941f1057bf47b527f..74b1e9240d43421dc8d742c2ec2357216b069b48 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -67,3 +67,6 @@ f6d557ee34b6bbdb1dc32f29e34b4a4a8ad35e81 # [libc++] Rename _LIBCPP_INLINE_VISIBILITY to _LIBCPP_HIDE_FROM_ABI 4c198542226223f6a5c5511a1f89b37d15ee10b9 + +# [libc++] Replace uses of _VSTD:: by std:: (#74331) +77a00c0d546cd4aa8311b5b9031ae9ea8cdb050c diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index b9a28edc9daf45097d539c0bcc706df89c44e25b..8afd2b9ce4a1c14e02ae36f66af2cd2e59c9d623 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -33,26 +33,42 @@ /lldb/ @JDevlieghere -/mlir/include/mlir/Interfaces/TilingInterface.* @MaheshRavishankar +# Linalg in MLIR. +/mlir/include/mlir/Dialect/Linalg @dcaballe @nicolasvasilache +/mlir/lib/Dialect/Linalg @dcaballe @nicolasvasilache -/mlir/lib/Dialect/Linalg/Transforms/DecomposeLinalgOps.cpp @MaheshRavishankar -/mlir/lib/Dialect/Linalg/Transforms/DropUnitDims.cpp @MaheshRavishankar -/mlir/lib/Dialect/Linalg/Transforms/ElementwiseOpFusion.cpp @MaheshRavishankar -/mlir/lib/Dialect/MemRef/Transforms/EmulateNarrowType.cpp @MaheshRavishankar -/mlir/lib/Dialect/Vector/Transforms/VectorEmulateNarrowType.cpp @MaheshRavishankar -/mlir/lib/Interfaces/TilingInterface.* @MaheshRavishankar +# Vector in MLIR. +/mlir/**/*AMX* @dcaballe +/mlir/**/*Neon* @banach-space @dcaballe @nicolasvasilache +/mlir/**/*SME* @banach-space @dcaballe @nicolasvasilache +/mlir/**/*SVE* @banach-space @dcaballe @nicolasvasilache +/mlir/**/*VectorInterfaces* @dcaballe @nicolasvasilache +/mlir/**/*VectorToSCF* @banach-space @dcaballe @nicolasvasilache +/mlir/**/*VectorToLLVM* @banach-space @dcaballe @nicolasvasilache +/mlir/**/*X86Vector* @dcaballe @nicolasvasilache +/mlir/include/mlir/Dialect/Vector @dcaballe @nicolasvasilache +/mlir/lib/Dialect/Vector @dcaballe @nicolasvasilache + +/mlir/include/mlir/Interfaces/TilingInterface.* @MaheshRavishankar @nicolasvasilache + +/mlir/lib/Dialect/Linalg/Transforms/DecomposeLinalgOps.cpp @MaheshRavishankar @nicolasvasilache +/mlir/lib/Dialect/Linalg/Transforms/DropUnitDims.cpp @MaheshRavishankar @nicolasvasilache +/mlir/lib/Dialect/Linalg/Transforms/ElementwiseOpFusion.cpp @MaheshRavishankar @nicolasvasilache +/mlir/lib/Dialect/MemRef/Transforms/EmulateNarrowType.cpp @MaheshRavishankar @nicolasvasilache +/mlir/lib/Dialect/Vector/Transforms/VectorEmulateNarrowType.cpp @MaheshRavishankar @nicolasvasilache +/mlir/lib/Interfaces/TilingInterface.* @MaheshRavishankar @nicolasvasilache /mlir/**/*EmulateNarrowType* @hanhanW -/mlir/lib/Dialect/Linalg/Transforms/DataLayoutPropagation.cpp @hanhanW -/mlir/lib/Dialect/Linalg/Transforms/Transforms.cpp @hanhanW -/mlir/lib/Dialect/Linalg/Transforms/Vectorization.cpp @hanhanW -/mlir/lib/Dialect/Tensor/IR/TensorTilingInterfaceImpl.cpp @hanhanW -/mlir/lib/Dialect/Tensor/Transforms/FoldIntoPackAndUnpackPatterns.cpp @hanhanW -/mlir/lib/Dialect/Vector/Transforms/* @hanhanW +/mlir/lib/Dialect/Linalg/Transforms/DataLayoutPropagation.cpp @hanhanW @nicolasvasilache +/mlir/lib/Dialect/Linalg/Transforms/Transforms.cpp @hanhanW @nicolasvasilache +/mlir/lib/Dialect/Linalg/Transforms/Vectorization.cpp @hanhanW @nicolasvasilache +/mlir/lib/Dialect/Tensor/IR/TensorTilingInterfaceImpl.cpp @hanhanW @nicolasvasilache +/mlir/lib/Dialect/Tensor/Transforms/FoldIntoPackAndUnpackPatterns.cpp @hanhanW @nicolasvasilache +/mlir/lib/Dialect/Vector/Transforms/* @hanhanW @nicolasvasilache # Transform Dialect in MLIR. -/mlir/include/mlir/Dialect/Transform/* @ftynse -/mlir/lib/Dialect/Transform/* @ftynse +/mlir/include/mlir/Dialect/Transform/* @ftynse @nicolasvasilache +/mlir/lib/Dialect/Transform/* @ftynse @nicolasvasilache # SPIR-V in MLIR. /mlir/**/SPIRV/ @antiagainst @kuhar diff --git a/.github/workflows/libcxx-build-and-test.yaml b/.github/workflows/libcxx-build-and-test.yaml index 83786052a53910668410cd2087d80a5267193d2b..370cf830a60cf8f0a0558503422e4f14c441fdd4 100644 --- a/.github/workflows/libcxx-build-and-test.yaml +++ b/.github/workflows/libcxx-build-and-test.yaml @@ -53,7 +53,7 @@ jobs: runs-on: libcxx-runners-8-set continue-on-error: false strategy: - fail-fast: true + fail-fast: false matrix: config: [ 'generic-cxx03', @@ -92,7 +92,7 @@ jobs: needs: [ stage1 ] continue-on-error: false strategy: - fail-fast: true + fail-fast: false matrix: config: [ 'generic-cxx11', @@ -160,6 +160,7 @@ jobs: 'generic-no-tzdb', 'generic-no-unicode', 'generic-no-wide-characters', + 'generic-no-rtti', 'generic-static', 'generic-with_llvm_unwinder', # TODO Find a better place for the benchmark and bootstrapping builds to live. They're either very expensive diff --git a/.github/workflows/llvm-project-tests.yml b/.github/workflows/llvm-project-tests.yml index 996cfe41f047f679651b39d29af67b3dd851a1b5..02b1ab75e960eced4a74e9604bf11b0e01e06d04 100644 --- a/.github/workflows/llvm-project-tests.yml +++ b/.github/workflows/llvm-project-tests.yml @@ -10,6 +10,11 @@ on: required: false projects: required: false + extra_cmake_args: + required: false + os_list: + required: false + default: '["ubuntu-latest", "windows-2019", "macOS-11"]' workflow_call: inputs: build_target: @@ -20,6 +25,19 @@ on: required: true type: string + extra_cmake_args: + required: false + type: string + + os_list: + required: false + type: string + # Use windows-2019 due to: + # https://developercommunity.visualstudio.com/t/Prev-Issue---with-__assume-isnan-/1597317 + # We're using a specific version of macOS due to: + # https://github.com/actions/virtual-environments/issues/5900 + default: '["ubuntu-latest", "windows-2019", "macOS-11"]' + concurrency: # Skip intermediate builds: always. # Cancel intermediate builds: only if it is a pull request build. @@ -35,14 +53,7 @@ jobs: strategy: fail-fast: false matrix: - os: - - ubuntu-latest - # Use windows-2019 due to: - # https://developercommunity.visualstudio.com/t/Prev-Issue---with-__assume-isnan-/1597317 - - windows-2019 - # We're using a specific version of macOS due to: - # https://github.com/actions/virtual-environments/issues/5900 - - macOS-11 + os: ${{ fromJSON(inputs.os_list) }} steps: - name: Setup Windows if: startsWith(matrix.os, 'windows') @@ -85,7 +96,7 @@ jobs: # This should be a no-op for non-mac OSes PKG_CONFIG_PATH: /usr/local/Homebrew/Library/Homebrew/os/mac/pkgconfig//12 with: - cmake_args: '-GNinja -DLLVM_ENABLE_PROJECTS="${{ inputs.projects }}" -DCMAKE_BUILD_TYPE=Release -DLLDB_INCLUDE_TESTS=OFF -DCMAKE_C_COMPILER_LAUNCHER=sccache -DCMAKE_CXX_COMPILER_LAUNCHER=sccache' + cmake_args: '-GNinja -DLLVM_ENABLE_PROJECTS="${{ inputs.projects }}" -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_ASSERTIONS=ON -DLLDB_INCLUDE_TESTS=OFF -DCMAKE_C_COMPILER_LAUNCHER=sccache -DCMAKE_CXX_COMPILER_LAUNCHER=sccache ${{ inputs.extra_cmake_args }}' build_target: '${{ inputs.build_target }}' - name: Build and Test libclc diff --git a/.github/workflows/new-prs.yml b/.github/workflows/new-prs.yml index 9ba55d59ff15b4c754a8e45610c2d79e92bea2e2..23fab598fc77db7a210874a6d55feb96cd1fa1a6 100644 --- a/.github/workflows/new-prs.yml +++ b/.github/workflows/new-prs.yml @@ -15,16 +15,50 @@ on: - synchronize jobs: - automate-prs-labels: + greeter: + runs-on: ubuntu-latest permissions: pull-requests: write + # Only comment on PRs that have been opened for the first time, by someone + # new to LLVM or to GitHub as a whole. Ideally we'd look for FIRST_TIMER + # or FIRST_TIME_CONTRIBUTOR, but this does not appear to work. Instead check + # that we do not have any of the other author associations. + # See https://docs.github.com/en/webhooks/webhook-events-and-payloads?actionType=opened#pull_request + # for all the possible values. + if: >- + (github.repository == 'llvm/llvm-project') && + (github.event.action == 'opened') && + (github.event.pull_request.author_association != 'COLLABORATOR') && + (github.event.pull_request.author_association != 'CONTRIBUTOR') && + (github.event.pull_request.author_association != 'MANNEQUIN') && + (github.event.pull_request.author_association != 'MEMBER') && + (github.event.pull_request.author_association != 'OWNER') + steps: + - name: Setup Automation Script + run: | + curl -O -L --fail https://raw.githubusercontent.com/"$GITHUB_REPOSITORY"/main/llvm/utils/git/github-automation.py + curl -O -L --fail https://raw.githubusercontent.com/"$GITHUB_REPOSITORY"/main/llvm/utils/git/requirements.txt + chmod a+x github-automation.py + pip install -r requirements.txt + + - name: Greet Author + run: | + ./github-automation.py \ + --token '${{ secrets.GITHUB_TOKEN }}' \ + pr-greeter \ + --issue-number "${{ github.event.pull_request.number }}" + + automate-prs-labels: + # Greet first so that only the author gets that notification. + needs: greeter runs-on: ubuntu-latest # Ignore PRs with more than 10 commits. Pull requests with a lot of # commits tend to be accidents usually when someone made a mistake while trying # to rebase. We want to ignore these pull requests to avoid excessive # notifications. + # always() means that even if greeter is skipped, this job will run. if: > - github.repository == 'llvm/llvm-project' && + always() && github.repository == 'llvm/llvm-project' && github.event.pull_request.draft == false && github.event.pull_request.commits < 10 steps: diff --git a/.github/workflows/pr-code-format.yml b/.github/workflows/pr-code-format.yml index c27c282eb2a19ae5215c9af41eb348006b927c2f..5223089ee8a93d8751fcfc38ff40ff2f51c7c46c 100644 --- a/.github/workflows/pr-code-format.yml +++ b/.github/workflows/pr-code-format.yml @@ -67,10 +67,14 @@ jobs: START_REV: ${{ github.event.pull_request.base.sha }} END_REV: ${{ github.event.pull_request.head.sha }} CHANGED_FILES: ${{ steps.changed-files.outputs.all_changed_files }} + # TODO(boomanaiden154): Once clang v18 is released, we should be able + # to take advantage of the new --diff_from_common_commit option + # explicitly in code-format-helper.py and not have to diff starting at + # the merge base. run: | python ./code-format-tools/llvm/utils/git/code-format-helper.py \ --token ${{ secrets.GITHUB_TOKEN }} \ --issue-number $GITHUB_PR_NUMBER \ - --start-rev $START_REV \ + --start-rev $(git merge-base $START_REV $END_REV) \ --end-rev $END_REV \ --changed-files "$CHANGED_FILES" diff --git a/.github/workflows/spirv-tests.yml b/.github/workflows/spirv-tests.yml new file mode 100644 index 0000000000000000000000000000000000000000..0e1d0caca410cfe966351206c8d6b95cb19680f1 --- /dev/null +++ b/.github/workflows/spirv-tests.yml @@ -0,0 +1,29 @@ +name: SPIR-V Tests + +permissions: + contents: read + +on: + workflow_dispatch: + pull_request: + paths: + - 'llvm/lib/Target/SPIRV/**' + - 'llvm/test/CodeGen/SPIRV/**' + - '.github/workflows/spirv-tests.yml' + +concurrency: + # Skip intermediate builds: always. + # Cancel intermediate builds: only if it is a pull request build. + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }} + +jobs: + check_spirv: + if: github.repository_owner == 'llvm' + name: Test SPIR-V + uses: ./.github/workflows/llvm-project-tests.yml + with: + build_target: check-llvm-codegen-spirv + projects: + extra_cmake_args: '-DLLVM_TARGETS_TO_BUILD="" -DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD="SPIRV"' + os_list: '["ubuntu-latest"]' diff --git a/.mailmap b/.mailmap index f4d7ffe3013818c430331c665a77093718bcb8d0..d5464cf9e81529d0fc28e440c16e9ae7980755d5 100644 --- a/.mailmap +++ b/.mailmap @@ -33,6 +33,8 @@ +Jianjian GUAN +Jianjian GUAN Jon Roelofs Jon Roelofs Jonathan Thackray diff --git a/bolt/include/bolt/Core/BinaryFunction.h b/bolt/include/bolt/Core/BinaryFunction.h index 182d5ff049c3762d08f95c8c62d69f4ec5ba7784..3a1eae3311bd7623d1263d7627720259e28f83ca 100644 --- a/bolt/include/bolt/Core/BinaryFunction.h +++ b/bolt/include/bolt/Core/BinaryFunction.h @@ -75,6 +75,14 @@ enum IndirectCallPromotionType : char { ICP_ALL /// Perform ICP on calls and jump tables. }; +/// Hash functions supported for BF/BB hashing. +enum class HashFunction : char { + StdHash, /// std::hash, implementation is platform-dependent. Provided for + /// backwards compatibility. + XXH3, /// llvm::xxh3_64bits, the default. + Default = XXH3, +}; + /// Information on a single indirect call to a particular callee. struct IndirectCallProfile { MCSymbol *Symbol; @@ -2234,18 +2242,21 @@ public: /// /// If \p UseDFS is set, process basic blocks in DFS order. Otherwise, use /// the existing layout order. + /// \p HashFunction specifies which function is used for BF hashing. /// /// By default, instruction operands are ignored while calculating the hash. /// The caller can change this via passing \p OperandHashFunc function. /// The return result of this function will be mixed with internal hash. size_t computeHash( - bool UseDFS = false, + bool UseDFS = false, HashFunction HashFunction = HashFunction::Default, OperandHashFuncTy OperandHashFunc = [](const MCOperand &) { return std::string(); }) const; /// Compute hash values for each block of the function. - void computeBlockHashes() const; + /// \p HashFunction specifies which function is used for BB hashing. + void + computeBlockHashes(HashFunction HashFunction = HashFunction::Default) const; void setDWARFUnit(DWARFUnit *Unit) { DwarfUnit = Unit; } diff --git a/bolt/include/bolt/Core/DebugData.h b/bolt/include/bolt/Core/DebugData.h index 23430cc36167c827bcca7470ce5fa68e3709e04a..9f0dd88b115fcc41ab88e1ad25e9f2a39874d3d7 100644 --- a/bolt/include/bolt/Core/DebugData.h +++ b/bolt/include/bolt/Core/DebugData.h @@ -459,8 +459,6 @@ private: std::unique_ptr StrOffsetsStream; std::map IndexToAddressMap; std::unordered_map ProcessedBaseOffsets; - // Section size not including header. - uint32_t CurrentSectionSize{0}; bool StrOffsetSectionWasModified = false; }; diff --git a/bolt/include/bolt/Profile/ProfileYAMLMapping.h b/bolt/include/bolt/Profile/ProfileYAMLMapping.h index 2218a167a74ec09efaa29021cee59341f0596aca..548b528ae2d6534d96cbcea298f9b283c79385f6 100644 --- a/bolt/include/bolt/Profile/ProfileYAMLMapping.h +++ b/bolt/include/bolt/Profile/ProfileYAMLMapping.h @@ -178,6 +178,14 @@ template <> struct ScalarBitSetTraits { } }; +template <> struct ScalarEnumerationTraits { + using HashFunction = llvm::bolt::HashFunction; + static void enumeration(IO &io, HashFunction &value) { + io.enumCase(value, "std-hash", HashFunction::StdHash); + io.enumCase(value, "xxh3", HashFunction::XXH3); + } +}; + namespace bolt { struct BinaryProfileHeader { uint32_t Version{1}; @@ -188,6 +196,7 @@ struct BinaryProfileHeader { std::string Origin; // How the profile was obtained. std::string EventNames; // Events used for sample profile. bool IsDFSOrder{true}; // Whether using DFS block order in function profile + llvm::bolt::HashFunction HashFunction; // Hash used for BB/BF hashing }; } // end namespace bolt @@ -200,6 +209,8 @@ template <> struct MappingTraits { YamlIO.mapOptional("profile-origin", Header.Origin); YamlIO.mapOptional("profile-events", Header.EventNames); YamlIO.mapOptional("dfs-order", Header.IsDFSOrder); + YamlIO.mapOptional("hash-func", Header.HashFunction, + llvm::bolt::HashFunction::StdHash); } }; diff --git a/bolt/lib/Core/BinaryFunction.cpp b/bolt/lib/Core/BinaryFunction.cpp index be033cf07668801fffc5ed6e8c7e609ba3824ec5..0ac47a53a446775e536ec6b502601169477b07a4 100644 --- a/bolt/lib/Core/BinaryFunction.cpp +++ b/bolt/lib/Core/BinaryFunction.cpp @@ -3633,7 +3633,7 @@ BinaryFunction::BasicBlockListType BinaryFunction::dfs() const { return DFS; } -size_t BinaryFunction::computeHash(bool UseDFS, +size_t BinaryFunction::computeHash(bool UseDFS, HashFunction HashFunction, OperandHashFuncTy OperandHashFunc) const { if (size() == 0) return 0; @@ -3652,7 +3652,13 @@ size_t BinaryFunction::computeHash(bool UseDFS, for (const BinaryBasicBlock *BB : Order) HashString.append(hashBlock(BC, *BB, OperandHashFunc)); - return Hash = llvm::xxh3_64bits(HashString); + switch (HashFunction) { + case HashFunction::StdHash: + return Hash = std::hash{}(HashString); + case HashFunction::XXH3: + return Hash = llvm::xxh3_64bits(HashString); + } + llvm_unreachable("Unhandled HashFunction"); } void BinaryFunction::insertBasicBlocks( diff --git a/bolt/lib/Core/BinaryFunctionProfile.cpp b/bolt/lib/Core/BinaryFunctionProfile.cpp index 0d705cd82f5df6c1f23ad29184954e8a102a74c2..55ebe5fc900e65102ccb22a364bbc9262ebce124 100644 --- a/bolt/lib/Core/BinaryFunctionProfile.cpp +++ b/bolt/lib/Core/BinaryFunctionProfile.cpp @@ -225,6 +225,7 @@ void BinaryFunction::mergeProfileDataInto(BinaryFunction &BF) const { for (const BinaryBasicBlock *BBSucc : BB->successors()) { (void)BBSucc; assert(getIndex(BBSucc) == BF.getIndex(*BBMergeSI)); + (void)BBMergeSI; // At this point no branch count should be set to COUNT_NO_PROFILE. assert(BII->Count != BinaryBasicBlock::COUNT_NO_PROFILE && diff --git a/bolt/lib/Core/DebugData.cpp b/bolt/lib/Core/DebugData.cpp index 9061d4f0e197aec1a69fbdc6461be9ef5b0149a7..dcf3a36e35e3fcfc3b773054fba1ad05faa29167 100644 --- a/bolt/lib/Core/DebugData.cpp +++ b/bolt/lib/Core/DebugData.cpp @@ -889,8 +889,10 @@ void DebugStrOffsetsWriter::finalizeSection(DWARFUnit &Unit, // Handling re-use of str-offsets section. if (RetVal == ProcessedBaseOffsets.end() || StrOffsetSectionWasModified) { // Writing out the header for each section. - support::endian::write(*StrOffsetsStream, CurrentSectionSize + 4, - llvm::endianness::little); + support::endian::write( + *StrOffsetsStream, + static_cast(IndexToAddressMap.size() * 4 + 4), + llvm::endianness::little); support::endian::write(*StrOffsetsStream, static_cast(5), llvm::endianness::little); support::endian::write(*StrOffsetsStream, static_cast(0), diff --git a/bolt/lib/Core/Exceptions.cpp b/bolt/lib/Core/Exceptions.cpp index 993f3a7770aa8178eb4d25d8e0beac55529dda20..ab1885f6bb5851fb5a9f4d006460dce6570be8a8 100644 --- a/bolt/lib/Core/Exceptions.cpp +++ b/bolt/lib/Core/Exceptions.cpp @@ -108,7 +108,8 @@ void BinaryFunction::parseLSDA(ArrayRef LSDASectionData, DWARFDataExtractor Data( StringRef(reinterpret_cast(LSDASectionData.data()), LSDASectionData.size()), - BC.DwCtx->getDWARFObj().isLittleEndian(), 8); + BC.DwCtx->getDWARFObj().isLittleEndian(), + BC.DwCtx->getDWARFObj().getAddressSize()); uint64_t Offset = getLSDAAddress() - LSDASectionAddress; assert(Data.isValidOffset(Offset) && "wrong LSDA address"); diff --git a/bolt/lib/Passes/IdenticalCodeFolding.cpp b/bolt/lib/Passes/IdenticalCodeFolding.cpp index b4ec89ca8fd79fe51bdecf68b9780b1e77cff8c7..dfbc72e48e5d285b1e38814d0531d0628615b1b0 100644 --- a/bolt/lib/Passes/IdenticalCodeFolding.cpp +++ b/bolt/lib/Passes/IdenticalCodeFolding.cpp @@ -360,9 +360,9 @@ void IdenticalCodeFolding::runOnFunctions(BinaryContext &BC) { // Pre-compute hash before pushing into hashtable. // Hash instruction operands to minimize hash collisions. - BF.computeHash(opts::ICFUseDFS, [&BC](const MCOperand &Op) { - return hashInstOperand(BC, Op); - }); + BF.computeHash( + opts::ICFUseDFS, HashFunction::Default, + [&BC](const MCOperand &Op) { return hashInstOperand(BC, Op); }); }; ParallelUtilities::PredicateTy SkipFunc = [&](const BinaryFunction &BF) { diff --git a/bolt/lib/Passes/IndirectCallPromotion.cpp b/bolt/lib/Passes/IndirectCallPromotion.cpp index 8b084c3b63d565a090293b76b86cb1e1c7a5c141..f40f5e7acbf3b8bf0b5aae459011f7f60efeb591 100644 --- a/bolt/lib/Passes/IndirectCallPromotion.cpp +++ b/bolt/lib/Passes/IndirectCallPromotion.cpp @@ -158,6 +158,7 @@ static cl::opt ICPPeelForInline( } // namespace opts +#ifndef NDEBUG static bool verifyProfile(std::map &BFs) { bool IsValid = true; for (auto &BFI : BFs) { @@ -182,6 +183,7 @@ static bool verifyProfile(std::map &BFs) { } return IsValid; } +#endif namespace llvm { namespace bolt { @@ -1467,7 +1469,6 @@ void IndirectCallPromotion::runOnFunctions(BinaryContext &BC) { std::max(TotalIndexBasedCandidates, 1)) << "%\n"; - (void)verifyProfile; #ifndef NDEBUG verifyProfile(BFs); #endif diff --git a/bolt/lib/Passes/LongJmp.cpp b/bolt/lib/Passes/LongJmp.cpp index a81689bc37469a43877afe948a07ed6049fc2b12..ded0db2cd30b611199c02a2263069d848402e43d 100644 --- a/bolt/lib/Passes/LongJmp.cpp +++ b/bolt/lib/Passes/LongJmp.cpp @@ -202,10 +202,23 @@ LongJmpPass::replaceTargetWithStub(BinaryBasicBlock &BB, MCInst &Inst, } } else if (LocalStubsIter != Stubs.end() && LocalStubsIter->second.count(TgtBB)) { - // If we are replacing a local stub (because it is now out of range), - // use its target instead of creating a stub to jump to another stub + // The TgtBB and TgtSym now are the local out-of-range stub and its label. + // So, we are attempting to restore BB to its previous state without using + // this stub. TgtSym = BC.MIB->getTargetSymbol(*TgtBB->begin()); - TgtBB = BB.getSuccessor(TgtSym, BI); + assert(TgtSym && + "First instruction is expected to contain a target symbol."); + BinaryBasicBlock *TgtBBSucc = TgtBB->getSuccessor(TgtSym, BI); + + // TgtBB might have no successor. e.g. a stub for a function call. + if (TgtBBSucc) { + BB.replaceSuccessor(TgtBB, TgtBBSucc, BI.Count, BI.MispredictedCount); + assert(TgtBB->getExecutionCount() >= BI.Count && + "At least equal or greater than the branch count."); + TgtBB->setExecutionCount(TgtBB->getExecutionCount() - BI.Count); + } + + TgtBB = TgtBBSucc; } BinaryBasicBlock *StubBB = lookupLocalStub(BB, Inst, TgtSym, DotAddress); diff --git a/bolt/lib/Passes/ReorderAlgorithm.cpp b/bolt/lib/Passes/ReorderAlgorithm.cpp index 3c3365e1d3d711321c3eda520012d5cbb64e0507..c112e1a8dcea737a2c07565c4d8fbedece98e69e 100644 --- a/bolt/lib/Passes/ReorderAlgorithm.cpp +++ b/bolt/lib/Passes/ReorderAlgorithm.cpp @@ -20,7 +20,7 @@ #include #include -#undef DEBUG_TYPE +#undef DEBUG_TYPE #define DEBUG_TYPE "bolt" using namespace llvm; @@ -425,7 +425,7 @@ void TSPReorderAlgorithm::reorderBasicBlocks(BinaryFunction &BF, } std::vector> DP; - DP.resize(1 << N); + DP.resize(static_cast(1) << N); for (std::vector &Elmt : DP) Elmt.resize(N, -1); diff --git a/bolt/lib/Passes/VeneerElimination.cpp b/bolt/lib/Passes/VeneerElimination.cpp index eadbfc17fb9748f3a71a6beeed438c2bcb21b9ae..929c7360b7ffafd36da4cc6561bc5448afa15e6d 100644 --- a/bolt/lib/Passes/VeneerElimination.cpp +++ b/bolt/lib/Passes/VeneerElimination.cpp @@ -89,6 +89,7 @@ void VeneerElimination::runOnFunctions(BinaryContext &BC) { LLVM_DEBUG( dbgs() << "BOLT-INFO: number of linker-inserted veneers call sites: " << VeneerCallers << "\n"); + (void)VeneerCallers; } } // namespace bolt diff --git a/bolt/lib/Profile/StaleProfileMatching.cpp b/bolt/lib/Profile/StaleProfileMatching.cpp index 6fb6f380f71eecd8551d0168641627195bfc179e..26180f1321477972124360473a35f097780b2368 100644 --- a/bolt/lib/Profile/StaleProfileMatching.cpp +++ b/bolt/lib/Profile/StaleProfileMatching.cpp @@ -225,7 +225,7 @@ private: std::unordered_map> OpHashToBlocks; }; -void BinaryFunction::computeBlockHashes() const { +void BinaryFunction::computeBlockHashes(HashFunction HashFunction) const { if (size() == 0) return; @@ -241,12 +241,26 @@ void BinaryFunction::computeBlockHashes() const { // Hashing complete instructions. std::string InstrHashStr = hashBlock( BC, *BB, [&](const MCOperand &Op) { return hashInstOperand(BC, Op); }); - uint64_t InstrHash = llvm::xxh3_64bits(InstrHashStr); - BlendedHashes[I].InstrHash = (uint16_t)InstrHash; + if (HashFunction == HashFunction::StdHash) { + uint64_t InstrHash = std::hash{}(InstrHashStr); + BlendedHashes[I].InstrHash = (uint16_t)hash_value(InstrHash); + } else if (HashFunction == HashFunction::XXH3) { + uint64_t InstrHash = llvm::xxh3_64bits(InstrHashStr); + BlendedHashes[I].InstrHash = (uint16_t)InstrHash; + } else { + llvm_unreachable("Unhandled HashFunction"); + } // Hashing opcodes. std::string OpcodeHashStr = hashBlockLoose(BC, *BB); - OpcodeHashes[I] = llvm::xxh3_64bits(OpcodeHashStr); - BlendedHashes[I].OpcodeHash = (uint16_t)OpcodeHashes[I]; + if (HashFunction == HashFunction::StdHash) { + OpcodeHashes[I] = std::hash{}(OpcodeHashStr); + BlendedHashes[I].OpcodeHash = (uint16_t)hash_value(OpcodeHashes[I]); + } else if (HashFunction == HashFunction::XXH3) { + OpcodeHashes[I] = llvm::xxh3_64bits(OpcodeHashStr); + BlendedHashes[I].OpcodeHash = (uint16_t)OpcodeHashes[I]; + } else { + llvm_unreachable("Unhandled HashFunction"); + } } // Initialize neighbor hash. @@ -258,7 +272,12 @@ void BinaryFunction::computeBlockHashes() const { uint64_t SuccHash = OpcodeHashes[SuccBB->getIndex()]; Hash = hashing::detail::hash_16_bytes(Hash, SuccHash); } - BlendedHashes[I].SuccHash = (uint8_t)Hash; + if (HashFunction == HashFunction::StdHash) { + // Compatibility with old behavior. + BlendedHashes[I].SuccHash = (uint8_t)hash_value(Hash); + } else { + BlendedHashes[I].SuccHash = (uint8_t)Hash; + } // Append hashes of predecessors. Hash = 0; @@ -266,7 +285,12 @@ void BinaryFunction::computeBlockHashes() const { uint64_t PredHash = OpcodeHashes[PredBB->getIndex()]; Hash = hashing::detail::hash_16_bytes(Hash, PredHash); } - BlendedHashes[I].PredHash = (uint8_t)Hash; + if (HashFunction == HashFunction::StdHash) { + // Compatibility with old behavior. + BlendedHashes[I].PredHash = (uint8_t)hash_value(Hash); + } else { + BlendedHashes[I].PredHash = (uint8_t)Hash; + } } // Assign hashes. @@ -682,7 +706,7 @@ bool YAMLProfileReader::inferStaleProfile( << "\"" << BF.getPrintName() << "\"\n"); // Make sure that block hashes are up to date. - BF.computeBlockHashes(); + BF.computeBlockHashes(YamlBP.Header.HashFunction); const BinaryFunction::BasicBlockOrderType BlockOrder( BF.getLayout().block_begin(), BF.getLayout().block_end()); diff --git a/bolt/lib/Profile/YAMLProfileReader.cpp b/bolt/lib/Profile/YAMLProfileReader.cpp index 079cb352d36e77c9fdac1f79a42322cab1bb3635..ade562ef6fb11162cc52eda683ab3c8179dcfa5c 100644 --- a/bolt/lib/Profile/YAMLProfileReader.cpp +++ b/bolt/lib/Profile/YAMLProfileReader.cpp @@ -83,6 +83,7 @@ bool YAMLProfileReader::parseFunctionProfile( BinaryContext &BC = BF.getBinaryContext(); const bool IsDFSOrder = YamlBP.Header.IsDFSOrder; + const HashFunction HashFunction = YamlBP.Header.HashFunction; bool ProfileMatched = true; uint64_t MismatchedBlocks = 0; uint64_t MismatchedCalls = 0; @@ -98,7 +99,8 @@ bool YAMLProfileReader::parseFunctionProfile( FuncRawBranchCount += YamlSI.Count; BF.setRawBranchCount(FuncRawBranchCount); - if (!opts::IgnoreHash && YamlBF.Hash != BF.computeHash(IsDFSOrder)) { + if (!opts::IgnoreHash && + YamlBF.Hash != BF.computeHash(IsDFSOrder, HashFunction)) { if (opts::Verbosity >= 1) errs() << "BOLT-WARNING: function hash mismatch\n"; ProfileMatched = false; @@ -326,6 +328,17 @@ bool YAMLProfileReader::mayHaveProfileData(const BinaryFunction &BF) { } Error YAMLProfileReader::readProfile(BinaryContext &BC) { + if (opts::Verbosity >= 1) { + outs() << "BOLT-INFO: YAML profile with hash: "; + switch (YamlBP.Header.HashFunction) { + case HashFunction::StdHash: + outs() << "std::hash\n"; + break; + case HashFunction::XXH3: + outs() << "xxh3\n"; + break; + } + } YamlProfileToFunction.resize(YamlBP.Functions.size() + 1); auto profileMatches = [](const yaml::bolt::BinaryFunctionProfile &Profile, @@ -348,7 +361,8 @@ Error YAMLProfileReader::readProfile(BinaryContext &BC) { // Recompute hash once per function. if (!opts::IgnoreHash) - Function.computeHash(YamlBP.Header.IsDFSOrder); + Function.computeHash(YamlBP.Header.IsDFSOrder, + YamlBP.Header.HashFunction); if (profileMatches(YamlBF, Function)) matchProfileToFunction(YamlBF, Function); diff --git a/bolt/lib/Profile/YAMLProfileWriter.cpp b/bolt/lib/Profile/YAMLProfileWriter.cpp index 3326d1d8f55965b23f8619d100e725a82666a231..dffd851a1d6f7743bdbf520306b01926e7102384 100644 --- a/bolt/lib/Profile/YAMLProfileWriter.cpp +++ b/bolt/lib/Profile/YAMLProfileWriter.cpp @@ -189,6 +189,7 @@ std::error_code YAMLProfileWriter::writeProfile(const RewriteInstance &RI) { BP.Header.Id = BuildID ? std::string(*BuildID) : ""; BP.Header.Origin = std::string(RI.getProfileReader()->getReaderName()); BP.Header.IsDFSOrder = opts::ProfileUseDFS; + BP.Header.HashFunction = HashFunction::Default; StringSet<> EventNames = RI.getProfileReader()->getEventNames(); if (!EventNames.empty()) { diff --git a/bolt/lib/Rewrite/DWARFRewriter.cpp b/bolt/lib/Rewrite/DWARFRewriter.cpp index 5580d85e3fa7716f6b47ea1ea8cd5f286fc95e0d..1cc07c1cc9f76a21d90ddfe048636968f3ff6d2c 100644 --- a/bolt/lib/Rewrite/DWARFRewriter.cpp +++ b/bolt/lib/Rewrite/DWARFRewriter.cpp @@ -696,8 +696,9 @@ void DWARFRewriter::updateDebugInfo() { std::optional SplitCU; std::optional RangesBase; std::optional DWOId = Unit->getDWOId(); - StrOffstsWriter->initialize(Unit->getStringOffsetSection(), - Unit->getStringOffsetsTableContribution()); + if (Unit->getVersion() >= 5) + StrOffstsWriter->initialize(Unit->getStringOffsetSection(), + Unit->getStringOffsetsTableContribution()); if (DWOId) SplitCU = BC.getDWOCU(*DWOId); DebugLocWriter *DebugLocWriter = createRangeLocList(*Unit); diff --git a/bolt/lib/Rewrite/RewriteInstance.cpp b/bolt/lib/Rewrite/RewriteInstance.cpp index 8cda0b7fcca9f8438708f9ede6fe5e8b6570d6e5..1e8ca569682f712cd4a2ad3cbabda406d8b4f277 100644 --- a/bolt/lib/Rewrite/RewriteInstance.cpp +++ b/bolt/lib/Rewrite/RewriteInstance.cpp @@ -623,7 +623,9 @@ void RewriteInstance::parseBuildID() { // Reading notes section (see Portable Formats Specification, Version 1.1, // pg 2-5, section "Note Section"). - DataExtractor DE = DataExtractor(Buf, true, 8); + DataExtractor DE = + DataExtractor(Buf, + /*IsLittleEndian=*/true, InputFile->getBytesInAddress()); uint64_t Offset = 0; if (!DE.isValidOffset(Offset)) return; diff --git a/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp b/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp index b852b9fbc9c52f4d47d986a60e2501b388c636d2..d90512e2122580788a25b9cffe50f571894e40c4 100644 --- a/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp +++ b/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp @@ -314,6 +314,12 @@ public: bool isRegToRegMove(const MCInst &Inst, MCPhysReg &From, MCPhysReg &To) const override { + if (Inst.getOpcode() == AArch64::FMOVDXr) { + From = Inst.getOperand(1).getReg(); + To = Inst.getOperand(0).getReg(); + return true; + } + if (Inst.getOpcode() != AArch64::ORRXrs) return false; if (Inst.getOperand(1).getReg() != AArch64::XZR) diff --git a/bolt/test/AArch64/fp-reg-spill.s b/bolt/test/AArch64/fp-reg-spill.s new file mode 100644 index 0000000000000000000000000000000000000000..65523148edd3fc122f09b6fe24111dada322816c --- /dev/null +++ b/bolt/test/AArch64/fp-reg-spill.s @@ -0,0 +1,19 @@ +# Check that we correctly handle arm64 fp register spills in +# bolt when we are processing jump tables. +# REQUIRES: system-linux +# RUN: llvm-mc -filetype=obj -triple=aarch64 %s -o %t.o +# RUN: ld.lld --emit-relocs %t.o -o %t.elf +# RUN: llvm-bolt --jump-tables=move %t.elf -o %t.bolt + +.globl _foo, _start + +_foo: + ret + +_start: + adr x6, _foo + fmov d18,x6 + fmov x5,d18 + ldrb w5, [x5, w1, uxtw] + add x5, x6, w5, sxtb #2 + br x5 diff --git a/bolt/test/X86/Inputs/blarge_profile_stale.std-hash.yaml b/bolt/test/X86/Inputs/blarge_profile_stale.std-hash.yaml new file mode 100644 index 0000000000000000000000000000000000000000..d520a0d242bf02f6cd1e5cfd379cea0f06df2ee3 --- /dev/null +++ b/bolt/test/X86/Inputs/blarge_profile_stale.std-hash.yaml @@ -0,0 +1,56 @@ +--- +header: + profile-version: 1 + binary-name: 'reader-yaml.test.tmp.exe' + binary-build-id: '' + profile-flags: [ lbr ] + profile-origin: branch profile reader + profile-events: '' + dfs-order: false +functions: + - name: SolveCubic + fid: 6 + hash: 0xC6E9098E973BBE19 + exec: 151 + nblocks: 18 + blocks: + - bid: 0 + insns: 43 + hash: 0xed4db287e71c0000 + exec: 151 + succ: [ { bid: 1, cnt: 151, mis: 2 }, { bid: 7, cnt: 0 } ] + - bid: 1 + insns: 7 + hash: 0x39330000e4560088 + succ: [ { bid: 13, cnt: 151 }, { bid: 2, cnt: 0 } ] + - bid: 13 + insns: 26 + hash: 0xa9700000fe202a7 + succ: [ { bid: 3, cnt: 89 }, { bid: 2, cnt: 10 } ] + - bid: 3 + insns: 9 + hash: 0x62391dad18a700a0 + succ: [ { bid: 5, cnt: 151 } ] + - bid: 5 + insns: 9 + hash: 0x4d906d19ecec0111 + - name: usqrt + fid: 7 + hash: 0x8B62B1F9AD81EA35 + exec: 20 + nblocks: 6 + blocks: + - bid: 0 + insns: 4 + hash: 0x1111111111111111 + exec: 20 + succ: [ { bid: 1, cnt: 0 } ] + - bid: 1 + insns: 9 + hash: 0x27e43a5e10cd0010 + succ: [ { bid: 3, cnt: 320, mis: 171 }, { bid: 2, cnt: 0 } ] + - bid: 3 + insns: 2 + hash: 0x4db935b6471e0039 + succ: [ { bid: 1, cnt: 300, mis: 33 }, { bid: 4, cnt: 20 } ] +... diff --git a/bolt/test/X86/Inputs/blarge_profile_stale.yaml b/bolt/test/X86/Inputs/blarge_profile_stale.yaml index 43b75c99656f1884a4af03c0f07d6d0b7bed2be1..ac46b37b56a121ca6aa3614fab292c83fd714e0a 100644 --- a/bolt/test/X86/Inputs/blarge_profile_stale.yaml +++ b/bolt/test/X86/Inputs/blarge_profile_stale.yaml @@ -7,6 +7,7 @@ header: profile-origin: branch profile reader profile-events: '' dfs-order: false + hash-func: xxh3 functions: - name: SolveCubic fid: 6 diff --git a/bolt/test/X86/dwarf5-two-cu-str-offset-table.test b/bolt/test/X86/dwarf5-two-cu-str-offset-table.test new file mode 100644 index 0000000000000000000000000000000000000000..20503951df4e18fdebc38f2429941c73875cc696 --- /dev/null +++ b/bolt/test/X86/dwarf5-two-cu-str-offset-table.test @@ -0,0 +1,66 @@ +# REQUIRES: system-linux + +# RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf5_main.s -o %tmain.o +# RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf5_helper.s -o %thelper.o +# RUN: %clang %cflags -dwarf-5 %tmain.o %thelper.o -o %t.exe -Wl,-q +# RUN: llvm-bolt %t.exe -o %t.bolt --update-debug-sections +# RUN: llvm-dwarfdump --show-form --verbose --debug-str-offsets %t.exe > %t.txt +# RUN: llvm-dwarfdump --show-form --verbose --debug-str-offsets %t.bolt >> %t.txt +# RUN: cat %t.txt | FileCheck --check-prefix=CHECK %s + +## This test checks we correclty re-renerate .debug_str_offsets. + +# CHECK: .debug_str_offsets contents +# CHECK-NEXT: 0x00000000: Contribution size = 52, Format = DWARF32, Version = 5 +# CHECK-NEXT: "clang version 15.0.0" +# CHECK-NEXT: "main.cpp" +# CHECK-NEXT: "/testLocListMultiple" +# CHECK-NEXT: "_Z3usePiS_" +# CHECK-NEXT: "use" +# CHECK-NEXT: "main" +# CHECK-NEXT: "int" +# CHECK-NEXT: "x" +# CHECK-NEXT: "y" +# CHECK-NEXT: "argc" +# CHECK-NEXT: "argv" +# CHECK-NEXT: "char" +# CHECK-NEXT: 0x00000038: Contribution size = 48, Format = DWARF32, Version = 5 +# CHECK-NEXT: "clang version 15.0.0)" +# CHECK-NEXT: "foo.cpp" +# CHECK-NEXT: "/testLocListMultiple" +# CHECK-NEXT: "fooVar" +# CHECK-NEXT: "int" +# CHECK-NEXT: "_Z6useFooPi" +# CHECK-NEXT: "useFoo" +# CHECK-NEXT: "x" +# CHECK-NEXT: "_Z3fooi" +# CHECK-NEXT: "foo" +# CHECK-NEXT: "argc" + +## Checking post bolt +# CHECK: .debug_str_offsets contents +# CHECK-NEXT: 0x00000000: Contribution size = 52, Format = DWARF32, Version = 5 +# CHECK-NEXT: "clang version 15.0.0" +# CHECK-NEXT: "main.cpp" +# CHECK-NEXT: "/testLocListMultiple" +# CHECK-NEXT: "_Z3usePiS_" +# CHECK-NEXT: "use" +# CHECK-NEXT: "main" +# CHECK-NEXT: "int" +# CHECK-NEXT: "x" +# CHECK-NEXT: "y" +# CHECK-NEXT: "argc" +# CHECK-NEXT: "argv" +# CHECK-NEXT: "char" +# CHECK-NEXT: 0x00000038: Contribution size = 48, Format = DWARF32, Version = 5 +# CHECK-NEXT: "clang version 15.0.0)" +# CHECK-NEXT: "foo.cpp" +# CHECK-NEXT: "/testLocListMultiple" +# CHECK-NEXT: "fooVar" +# CHECK-NEXT: "int" +# CHECK-NEXT: "_Z6useFooPi" +# CHECK-NEXT: "useFoo" +# CHECK-NEXT: "x" +# CHECK-NEXT: "_Z3fooi" +# CHECK-NEXT: "foo" +# CHECK-NEXT: "argc" diff --git a/bolt/test/X86/reader-stale-yaml-std.test b/bolt/test/X86/reader-stale-yaml-std.test new file mode 100644 index 0000000000000000000000000000000000000000..e0b6ca0645e1954c84258d356dd114985e2ec493 --- /dev/null +++ b/bolt/test/X86/reader-stale-yaml-std.test @@ -0,0 +1,68 @@ +# This script checks that YamlProfileReader in llvm-bolt is reading data +# correctly and stale data is corrected by profile inference. + +RUN: yaml2obj %p/Inputs/blarge.yaml &> %t.exe +RUN: llvm-bolt %t.exe -o %t.null -b %p/Inputs/blarge_profile_stale.std-hash.yaml \ +RUN: --print-cfg --print-only=usqrt,SolveCubic --infer-stale-profile=1 -v=1 \ +RUN: 2>&1 | FileCheck %s + +# Verify that yaml reader works as expected. +CHECK: pre-processing profile using YAML profile reader +CHECK: BOLT-INFO: YAML profile with hash: std::hash + +# Function "SolveCubic" has stale profile, since there is one jump in the +# profile (from bid=13 to bid=2) which is not in the CFG in the binary. The test +# verifies that the inference is able to match two blocks (bid=1 and bid=13) +# using "loose" hashes and then correctly propagate the counts. + +CHECK: Binary Function "SolveCubic" after building cfg { +CHECK: State : CFG constructed +CHECK: Address : 0x400e00 +CHECK: Size : 0x368 +CHECK: Section : .text +CHECK: IsSimple : 1 +CHECK: BB Count : 18 +CHECK: Exec Count : 151 +CHECK: Branch Count: 552 +CHECK: } +# Verify block counts. +CHECK: .LBB00 (43 instructions, align : 1) +CHECK: Successors: .Ltmp[[#BB07:]] (mispreds: 0, count: 0), .LFT[[#BB01:]] (mispreds: 0, count: 151) +CHECK: .LFT[[#BB01:]] (5 instructions, align : 1) +CHECK: Successors: .Ltmp[[#BB013:]] (mispreds: 0, count: 151), .LFT[[#BB02:]] (mispreds: 0, count: 0) +CHECK: .Ltmp[[#BB03:]] (26 instructions, align : 1) +CHECK: Successors: .Ltmp[[#BB05:]] (mispreds: 0, count: 151), .LFT[[#BB04:]] (mispreds: 0, count: 0) +CHECK: .Ltmp[[#BB05:]] (9 instructions, align : 1) +CHECK: .Ltmp[[#BB013:]] (12 instructions, align : 1) +CHECK: Successors: .Ltmp[[#BB03:]] (mispreds: 0, count: 151) +CHECK: End of Function "SolveCubic" + +# Function "usqrt" has stale profile, since the number of blocks in the profile +# (nblocks=6) does not match the size of the CFG in the binary. The entry +# block (bid=0) has an incorrect (missing) count, which should be inferred by +# the algorithm. + +CHECK: Binary Function "usqrt" after building cfg { +CHECK: State : CFG constructed +CHECK: Address : 0x401170 +CHECK: Size : 0x43 +CHECK: Section : .text +CHECK: IsSimple : 1 +CHECK: BB Count : 5 +CHECK: Exec Count : 20 +CHECK: Branch Count: 640 +CHECK: } +# Verify block counts. +CHECK: .LBB01 (4 instructions, align : 1) +CHECK: Successors: .Ltmp[[#BB113:]] (mispreds: 0, count: 20) +CHECK: .Ltmp[[#BB113:]] (9 instructions, align : 1) +CHECK: Successors: .Ltmp[[#BB112:]] (mispreds: 0, count: 320), .LFT[[#BB10:]] (mispreds: 0, count: 0) +CHECK: .LFT[[#BB10:]] (2 instructions, align : 1) +CHECK: Successors: .Ltmp[[#BB112:]] (mispreds: 0, count: 0) +CHECK: .Ltmp[[#BB112:]] (2 instructions, align : 1) +CHECK: Successors: .Ltmp[[#BB113:]] (mispreds: 0, count: 300), .LFT[[#BB11:]] (mispreds: 0, count: 20) +CHECK: .LFT[[#BB11:]] (2 instructions, align : 1) +CHECK: End of Function "usqrt" +# Check the overall inference stats. +CHECK: 2 out of 7 functions in the binary (28.6%) have non-empty execution profile +CHECK: inferred profile for 2 (100.00% of profiled, 100.00% of stale) functions responsible for {{.*}} samples ({{.*}} out of {{.*}}) diff --git a/bolt/test/runtime/AArch64/instrumentation-ind-call.c b/bolt/test/runtime/AArch64/instrumentation-ind-call.c index 76ee8c05dd2998dd708bb719f82dda4e1fb8115c..f9056da333b4e88723a32669cc03b102ddb45f07 100644 --- a/bolt/test/runtime/AArch64/instrumentation-ind-call.c +++ b/bolt/test/runtime/AArch64/instrumentation-ind-call.c @@ -14,7 +14,7 @@ int main() { /* REQUIRES: system-linux,bolt-runtime -RUN: %clang %cflags %s -o %t.exe -Wl,-q -nopie -fpie +RUN: %clang %cflags %s -o %t.exe -Wl,-q -no-pie -fpie RUN: llvm-bolt %t.exe --instrument --instrumentation-file=%t.fdata \ RUN: -o %t.instrumented diff --git a/clang-tools-extra/clang-doc/Mapper.cpp b/clang-tools-extra/clang-doc/Mapper.cpp index 5264417748a12bd04df57fc46efa2f2de2834541..bb8b7952980ac69e14347441bb108e3c013c3147 100644 --- a/clang-tools-extra/clang-doc/Mapper.cpp +++ b/clang-tools-extra/clang-doc/Mapper.cpp @@ -103,7 +103,7 @@ llvm::SmallString<128> MapASTVisitor::getFile(const NamedDecl *D, .getPresumedLoc(D->getBeginLoc()) .getFilename()); IsFileInRootDir = false; - if (RootDir.empty() || !File.startswith(RootDir)) + if (RootDir.empty() || !File.starts_with(RootDir)) return File; IsFileInRootDir = true; llvm::SmallString<128> Prefix(RootDir); diff --git a/clang-tools-extra/clang-tidy/ClangTidy.cpp b/clang-tools-extra/clang-tidy/ClangTidy.cpp index 4b1a67b6dd98a94ce891230347cc26f903bf856d..565f044778c946397261584fde73454c9549715a 100644 --- a/clang-tools-extra/clang-tidy/ClangTidy.cpp +++ b/clang-tools-extra/clang-tidy/ClangTidy.cpp @@ -147,7 +147,8 @@ public: Files.makeAbsolutePath(FixAbsoluteFilePath); tooling::Replacement R(FixAbsoluteFilePath, Repl.getOffset(), Repl.getLength(), Repl.getReplacementText()); - Replacements &Replacements = FileReplacements[R.getFilePath()]; + auto &Entry = FileReplacements[R.getFilePath()]; + Replacements &Replacements = Entry.Replaces; llvm::Error Err = Replacements.add(R); if (Err) { // FIXME: Implement better conflict handling. @@ -174,6 +175,7 @@ public: } FixLoc = getLocation(FixAbsoluteFilePath, Repl.getOffset()); FixLocations.push_back(std::make_pair(FixLoc, CanBeApplied)); + Entry.BuildDir = Error.BuildDirectory; } } } @@ -189,9 +191,14 @@ public: void finish() { if (TotalFixes > 0) { - Rewriter Rewrite(SourceMgr, LangOpts); + auto &VFS = Files.getVirtualFileSystem(); + auto OriginalCWD = VFS.getCurrentWorkingDirectory(); + bool AnyNotWritten = false; + for (const auto &FileAndReplacements : FileReplacements) { + Rewriter Rewrite(SourceMgr, LangOpts); StringRef File = FileAndReplacements.first(); + VFS.setCurrentWorkingDirectory(FileAndReplacements.second.BuildDir); llvm::ErrorOr> Buffer = SourceMgr.getFileManager().getBufferForFile(File); if (!Buffer) { @@ -208,8 +215,8 @@ public: continue; } llvm::Expected Replacements = - format::cleanupAroundReplacements(Code, FileAndReplacements.second, - *Style); + format::cleanupAroundReplacements( + Code, FileAndReplacements.second.Replaces, *Style); if (!Replacements) { llvm::errs() << llvm::toString(Replacements.takeError()) << "\n"; continue; @@ -226,13 +233,18 @@ public: if (!tooling::applyAllReplacements(Replacements.get(), Rewrite)) { llvm::errs() << "Can't apply replacements for file " << File << "\n"; } + AnyNotWritten &= Rewrite.overwriteChangedFiles(); } - if (Rewrite.overwriteChangedFiles()) { + + if (AnyNotWritten) { llvm::errs() << "clang-tidy failed to apply suggested fixes.\n"; } else { llvm::errs() << "clang-tidy applied " << AppliedFixes << " of " << TotalFixes << " suggested fixes.\n"; } + + if (OriginalCWD) + VFS.setCurrentWorkingDirectory(*OriginalCWD); } } @@ -289,13 +301,18 @@ private: return CharSourceRange::getCharRange(BeginLoc, EndLoc); } + struct ReplacementsWithBuildDir { + StringRef BuildDir; + Replacements Replaces; + }; + FileManager Files; LangOptions LangOpts; // FIXME: use langopts from each original file IntrusiveRefCntPtr DiagOpts; DiagnosticConsumer *DiagPrinter; DiagnosticsEngine Diags; SourceManager SourceMgr; - llvm::StringMap FileReplacements; + llvm::StringMap FileReplacements; ClangTidyContext &Context; FixBehaviour ApplyFixes; unsigned TotalFixes = 0U; diff --git a/clang-tools-extra/clang-tidy/ExpandModularHeadersPPCallbacks.cpp b/clang-tools-extra/clang-tidy/ExpandModularHeadersPPCallbacks.cpp index 52cc2e6569b0520638126a4a72bc403e752c5bcb..0b1e9f59e1a70c7c27edbd005f6747ceb441bea6 100644 --- a/clang-tools-extra/clang-tidy/ExpandModularHeadersPPCallbacks.cpp +++ b/clang-tools-extra/clang-tidy/ExpandModularHeadersPPCallbacks.cpp @@ -171,7 +171,7 @@ void ExpandModularHeadersPPCallbacks::InclusionDirective( if (Imported) { serialization::ModuleFile *MF = Compiler.getASTReader()->getModuleManager().lookup( - Imported->getASTFile()); + *Imported->getASTFile()); handleModuleFile(MF); } parseToLocation(DirectiveLoc); diff --git a/clang-tools-extra/clang-tidy/bugprone/UnusedReturnValueCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/UnusedReturnValueCheck.cpp index 6bc9f2dd367dcbd978d9658cc10bad500b9ea78f..05012c7df6a97585762f1777f319bfd1f762aa27 100644 --- a/clang-tools-extra/clang-tidy/bugprone/UnusedReturnValueCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/UnusedReturnValueCheck.cpp @@ -133,6 +133,21 @@ UnusedReturnValueCheck::UnusedReturnValueCheck(llvm::StringRef Name, "::boost::system::error_code"))), AllowCastToVoid(Options.get("AllowCastToVoid", false)) {} +UnusedReturnValueCheck::UnusedReturnValueCheck(llvm::StringRef Name, + ClangTidyContext *Context, + std::string CheckedFunctions) + : UnusedReturnValueCheck(Name, Context, std::move(CheckedFunctions), {}, + false) {} + +UnusedReturnValueCheck::UnusedReturnValueCheck( + llvm::StringRef Name, ClangTidyContext *Context, + std::string CheckedFunctions, std::vector CheckedReturnTypes, + bool AllowCastToVoid) + : ClangTidyCheck(Name, Context), + CheckedFunctions(std::move(CheckedFunctions)), + CheckedReturnTypes(std::move(CheckedReturnTypes)), + AllowCastToVoid(AllowCastToVoid) {} + void UnusedReturnValueCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { Options.store(Opts, "CheckedFunctions", CheckedFunctions); Options.store(Opts, "CheckedReturnTypes", diff --git a/clang-tools-extra/clang-tidy/bugprone/UnusedReturnValueCheck.h b/clang-tools-extra/clang-tidy/bugprone/UnusedReturnValueCheck.h index b4356f8379fdc85fab5116717a10453a38378429..ab2cc691b894f7b08442d9d3d6410f0b3a70502a 100644 --- a/clang-tools-extra/clang-tidy/bugprone/UnusedReturnValueCheck.h +++ b/clang-tools-extra/clang-tidy/bugprone/UnusedReturnValueCheck.h @@ -31,7 +31,15 @@ public: private: std::string CheckedFunctions; const std::vector CheckedReturnTypes; - const bool AllowCastToVoid; + +protected: + UnusedReturnValueCheck(StringRef Name, ClangTidyContext *Context, + std::string CheckedFunctions); + UnusedReturnValueCheck(StringRef Name, ClangTidyContext *Context, + std::string CheckedFunctions, + std::vector CheckedReturnTypes, + bool AllowCastToVoid); + bool AllowCastToVoid; }; } // namespace clang::tidy::bugprone diff --git a/clang-tools-extra/clang-tidy/hicpp/CMakeLists.txt b/clang-tools-extra/clang-tidy/hicpp/CMakeLists.txt index d12ca275d39647f66038a340e2b4a182fe7e084b..132fbaccccf8a9c59c1effd0cd674a6bc650b6e2 100644 --- a/clang-tools-extra/clang-tidy/hicpp/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/hicpp/CMakeLists.txt @@ -6,6 +6,7 @@ set(LLVM_LINK_COMPONENTS add_clang_library(clangTidyHICPPModule ExceptionBaseclassCheck.cpp HICPPTidyModule.cpp + IgnoredRemoveResultCheck.cpp MultiwayPathsCoveredCheck.cpp NoAssemblerCheck.cpp SignedBitwiseCheck.cpp diff --git a/clang-tools-extra/clang-tidy/hicpp/HICPPTidyModule.cpp b/clang-tools-extra/clang-tidy/hicpp/HICPPTidyModule.cpp index 3749796877120ed0538f8680829291ddda51978d..daa9f398a740ed2624fd9be29f25208b21d5b95d 100644 --- a/clang-tools-extra/clang-tidy/hicpp/HICPPTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/hicpp/HICPPTidyModule.cpp @@ -37,6 +37,7 @@ #include "../readability/NamedParameterCheck.h" #include "../readability/UppercaseLiteralSuffixCheck.h" #include "ExceptionBaseclassCheck.h" +#include "IgnoredRemoveResultCheck.h" #include "MultiwayPathsCoveredCheck.h" #include "NoAssemblerCheck.h" #include "SignedBitwiseCheck.h" @@ -57,6 +58,8 @@ public: "hicpp-deprecated-headers"); CheckFactories.registerCheck( "hicpp-exception-baseclass"); + CheckFactories.registerCheck( + "hicpp-ignored-remove-result"); CheckFactories.registerCheck( "hicpp-multiway-paths-covered"); CheckFactories.registerCheck("hicpp-signed-bitwise"); diff --git a/clang-tools-extra/clang-tidy/hicpp/IgnoredRemoveResultCheck.cpp b/clang-tools-extra/clang-tidy/hicpp/IgnoredRemoveResultCheck.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3410559d435f6385633d5394dad0ec19c5484212 --- /dev/null +++ b/clang-tools-extra/clang-tidy/hicpp/IgnoredRemoveResultCheck.cpp @@ -0,0 +1,28 @@ +//===--- IgnoredRemoveResultCheck.cpp - clang-tidy ------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "IgnoredRemoveResultCheck.h" + +namespace clang::tidy::hicpp { + +IgnoredRemoveResultCheck::IgnoredRemoveResultCheck(llvm::StringRef Name, + ClangTidyContext *Context) + : UnusedReturnValueCheck(Name, Context, + "::std::remove;" + "::std::remove_if;" + "::std::unique") { + // The constructor for ClangTidyCheck needs to have been called + // before we can access options via Options.get(). + AllowCastToVoid = Options.get("AllowCastToVoid", true); +} + +void IgnoredRemoveResultCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { + Options.store(Opts, "AllowCastToVoid", AllowCastToVoid); +} + +} // namespace clang::tidy::hicpp diff --git a/clang-tools-extra/clang-tidy/hicpp/IgnoredRemoveResultCheck.h b/clang-tools-extra/clang-tidy/hicpp/IgnoredRemoveResultCheck.h new file mode 100644 index 0000000000000000000000000000000000000000..48354c34a8581a49ce5a91d741a3751c4bfcfaf9 --- /dev/null +++ b/clang-tools-extra/clang-tidy/hicpp/IgnoredRemoveResultCheck.h @@ -0,0 +1,29 @@ +//===--- IgnoredRemoveResultCheck.h - clang-tidy ----------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_HICPP_IGNOREDREMOVERESULTCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_HICPP_IGNOREDREMOVERESULTCHECK_H + +#include "../bugprone/UnusedReturnValueCheck.h" + +namespace clang::tidy::hicpp { + +/// Ensure that the result of std::remove, std::remove_if and std::unique +/// are not ignored according to rule 17.5.1. +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/hicpp/ignored-remove-result.html +class IgnoredRemoveResultCheck : public bugprone::UnusedReturnValueCheck { +public: + IgnoredRemoveResultCheck(StringRef Name, ClangTidyContext *Context); + void storeOptions(ClangTidyOptions::OptionMap &Opts) override; +}; + +} // namespace clang::tidy::hicpp + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_HICPP_IGNOREDREMOVERESULTCHECK_H diff --git a/clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp b/clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp index e336ba1ee1fa729af884b48d3be63607f918c506..5ae6caedb7f4c0368c755ae9d9dc89d1b6f8400a 100644 --- a/clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp +++ b/clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp @@ -124,7 +124,7 @@ void IncludeCleanerCheck::check(const MatchFinder::MatchResult &Result) { MainFileDecls.push_back(D); } llvm::DenseSet SeenSymbols; - const DirectoryEntry *ResourceDir = + OptionalDirectoryEntryRef ResourceDir = PP->getHeaderSearchInfo().getModuleMap().getBuiltinDir(); // FIXME: Find a way to have less code duplication between include-cleaner // analysis implementation and the below code. diff --git a/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt index c40065358d2dc3d70a71eb8e21110a100990bc9e..28ca52f46943a84de51946ec9660a0ee55be9a90 100644 --- a/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt @@ -39,6 +39,7 @@ add_clang_library(clangTidyModernizeModule UseNullptrCheck.cpp UseOverrideCheck.cpp UseStartsEndsWithCheck.cpp + UseStdNumbersCheck.cpp UseStdPrintCheck.cpp UseTrailingReturnTypeCheck.cpp UseTransparentFunctorsCheck.cpp diff --git a/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp b/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp index e994ffd2a75c857b895f1c765128aa44ae748edc..654f4bd0c6ba47275f4053e5cff5abac017cba48 100644 --- a/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp @@ -40,6 +40,7 @@ #include "UseNullptrCheck.h" #include "UseOverrideCheck.h" #include "UseStartsEndsWithCheck.h" +#include "UseStdNumbersCheck.h" #include "UseStdPrintCheck.h" #include "UseTrailingReturnTypeCheck.h" #include "UseTransparentFunctorsCheck.h" @@ -69,6 +70,8 @@ public: CheckFactories.registerCheck("modernize-pass-by-value"); CheckFactories.registerCheck( "modernize-use-starts-ends-with"); + CheckFactories.registerCheck( + "modernize-use-std-numbers"); CheckFactories.registerCheck("modernize-use-std-print"); CheckFactories.registerCheck( "modernize-raw-string-literal"); diff --git a/clang-tools-extra/clang-tidy/modernize/UseStdNumbersCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseStdNumbersCheck.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b299afd540b9a3cf4a71babcc04e8077988ef235 --- /dev/null +++ b/clang-tools-extra/clang-tidy/modernize/UseStdNumbersCheck.cpp @@ -0,0 +1,448 @@ +//===--- UseStdNumbersCheck.cpp - clang_tidy ------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX_License_Identifier: Apache_2.0 WITH LLVM_exception +// +//===----------------------------------------------------------------------===// + +#include "UseStdNumbersCheck.h" +#include "../ClangTidyDiagnosticConsumer.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/Decl.h" +#include "clang/AST/Expr.h" +#include "clang/AST/Stmt.h" +#include "clang/AST/Type.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/ASTMatchers/ASTMatchers.h" +#include "clang/ASTMatchers/ASTMatchersInternal.h" +#include "clang/ASTMatchers/ASTMatchersMacros.h" +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/LangOptions.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Basic/SourceManager.h" +#include "clang/Lex/Lexer.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/FormatVariadic.h" +#include "llvm/Support/MathExtras.h" +#include +#include +#include +#include +#include +#include +#include + +namespace { +using namespace clang::ast_matchers; +using clang::ast_matchers::internal::Matcher; +using llvm::StringRef; + +AST_MATCHER_P2(clang::FloatingLiteral, near, double, Value, double, + DiffThreshold) { + return std::abs(Node.getValueAsApproximateDouble() - Value) < DiffThreshold; +} + +AST_MATCHER_P(clang::QualType, hasCanonicalTypeUnqualified, + Matcher, InnerMatcher) { + return !Node.isNull() && + InnerMatcher.matches(Node->getCanonicalTypeUnqualified(), Finder, + Builder); +} + +AST_MATCHER(clang::QualType, isArithmetic) { + return !Node.isNull() && Node->isArithmeticType(); +} +AST_MATCHER(clang::QualType, isFloating) { + return !Node.isNull() && Node->isFloatingType(); +} + +AST_MATCHER_P(clang::Expr, anyOfExhaustive, std::vector>, + Exprs) { + bool FoundMatch = false; + for (const auto &InnerMatcher : Exprs) { + clang::ast_matchers::internal::BoundNodesTreeBuilder Result = *Builder; + if (InnerMatcher.matches(Node, Finder, &Result)) { + *Builder = std::move(Result); + FoundMatch = true; + } + } + return FoundMatch; +} + +// Using this struct to store the 'DiffThreshold' config value to create the +// matchers without the need to pass 'DiffThreshold' into every matcher. +// 'DiffThreshold' is needed in the 'near' matcher, which is used for matching +// the literal of every constant and for formulas' subexpressions that look at +// literals. +struct MatchBuilder { + auto + ignoreParenAndArithmeticCasting(const Matcher Matcher) const { + return expr(hasType(qualType(isArithmetic())), ignoringParenCasts(Matcher)); + } + + auto ignoreParenAndFloatingCasting(const Matcher Matcher) const { + return expr(hasType(qualType(isFloating())), ignoringParenCasts(Matcher)); + } + + auto matchMathCall(const StringRef FunctionName, + const Matcher ArgumentMatcher) const { + return expr(ignoreParenAndFloatingCasting( + callExpr(callee(functionDecl(hasName(FunctionName), + hasParameter(0, hasType(isArithmetic())))), + hasArgument(0, ArgumentMatcher)))); + } + + auto matchSqrt(const Matcher ArgumentMatcher) const { + return matchMathCall("sqrt", ArgumentMatcher); + } + + // Used for top-level matchers (i.e. the match that replaces Val with its + // constant). + // + // E.g. The matcher of `std::numbers::pi` uses this matcher to look for + // floatLiterals that have the value of pi. + // + // If the match is for a top-level match, we only care about the literal. + auto matchFloatLiteralNear(const StringRef Constant, const double Val) const { + return expr(ignoreParenAndFloatingCasting( + floatLiteral(near(Val, DiffThreshold)).bind(Constant))); + } + + // Used for non-top-level matchers (i.e. matchers that are used as inner + // matchers for top-level matchers). + // + // E.g.: The matcher of `std::numbers::log2e` uses this matcher to check if + // `e` of `log2(e)` is declared constant and initialized with the value for + // eulers number. + // + // Here, we do care about literals and about DeclRefExprs to variable + // declarations that are constant and initialized with `Val`. This allows + // top-level matchers to see through declared constants for their inner + // matches like the `std::numbers::log2e` matcher. + auto matchFloatValueNear(const double Val) const { + const auto Float = floatLiteral(near(Val, DiffThreshold)); + + const auto Dref = declRefExpr( + to(varDecl(hasType(qualType(isConstQualified(), isFloating())), + hasInitializer(ignoreParenAndFloatingCasting(Float))))); + return expr(ignoreParenAndFloatingCasting(anyOf(Float, Dref))); + } + + auto matchValue(const int64_t ValInt) const { + const auto Int = + expr(ignoreParenAndArithmeticCasting(integerLiteral(equals(ValInt)))); + const auto Float = expr(ignoreParenAndFloatingCasting( + matchFloatValueNear(static_cast(ValInt)))); + const auto Dref = declRefExpr(to(varDecl( + hasType(qualType(isConstQualified(), isArithmetic())), + hasInitializer(expr(anyOf(ignoringImplicit(Int), + ignoreParenAndFloatingCasting(Float))))))); + return expr(anyOf(Int, Float, Dref)); + } + + auto match1Div(const Matcher Match) const { + return binaryOperator(hasOperatorName("/"), hasLHS(matchValue(1)), + hasRHS(Match)); + } + + auto matchEuler() const { + return expr(anyOf(matchFloatValueNear(llvm::numbers::e), + matchMathCall("exp", matchValue(1)))); + } + auto matchEulerTopLevel() const { + return expr(anyOf(matchFloatLiteralNear("e_literal", llvm::numbers::e), + matchMathCall("exp", matchValue(1)).bind("e_pattern"))) + .bind("e"); + } + + auto matchLog2Euler() const { + return expr( + anyOf( + matchFloatLiteralNear("log2e_literal", llvm::numbers::log2e), + matchMathCall("log2", matchEuler()).bind("log2e_pattern"))) + .bind("log2e"); + } + + auto matchLog10Euler() const { + return expr( + anyOf( + matchFloatLiteralNear("log10e_literal", + llvm::numbers::log10e), + matchMathCall("log10", matchEuler()).bind("log10e_pattern"))) + .bind("log10e"); + } + + auto matchPi() const { return matchFloatValueNear(llvm::numbers::pi); } + auto matchPiTopLevel() const { + return matchFloatLiteralNear("pi_literal", llvm::numbers::pi).bind("pi"); + } + + auto matchEgamma() const { + return matchFloatLiteralNear("egamma_literal", llvm::numbers::egamma) + .bind("egamma"); + } + + auto matchInvPi() const { + return expr(anyOf(matchFloatLiteralNear("inv_pi_literal", + llvm::numbers::inv_pi), + match1Div(matchPi()).bind("inv_pi_pattern"))) + .bind("inv_pi"); + } + + auto matchInvSqrtPi() const { + return expr(anyOf( + matchFloatLiteralNear("inv_sqrtpi_literal", + llvm::numbers::inv_sqrtpi), + match1Div(matchSqrt(matchPi())).bind("inv_sqrtpi_pattern"))) + .bind("inv_sqrtpi"); + } + + auto matchLn2() const { + return expr(anyOf(matchFloatLiteralNear("ln2_literal", llvm::numbers::ln2), + matchMathCall("log", matchValue(2)).bind("ln2_pattern"))) + .bind("ln2"); + } + + auto machterLn10() const { + return expr( + anyOf(matchFloatLiteralNear("ln10_literal", llvm::numbers::ln10), + matchMathCall("log", matchValue(10)).bind("ln10_pattern"))) + .bind("ln10"); + } + + auto matchSqrt2() const { + return expr(anyOf(matchFloatLiteralNear("sqrt2_literal", + llvm::numbers::sqrt2), + matchSqrt(matchValue(2)).bind("sqrt2_pattern"))) + .bind("sqrt2"); + } + + auto matchSqrt3() const { + return expr(anyOf(matchFloatLiteralNear("sqrt3_literal", + llvm::numbers::sqrt3), + matchSqrt(matchValue(3)).bind("sqrt3_pattern"))) + .bind("sqrt3"); + } + + auto matchInvSqrt3() const { + return expr(anyOf(matchFloatLiteralNear("inv_sqrt3_literal", + llvm::numbers::inv_sqrt3), + match1Div(matchSqrt(matchValue(3))) + .bind("inv_sqrt3_pattern"))) + .bind("inv_sqrt3"); + } + + auto matchPhi() const { + const auto PhiFormula = binaryOperator( + hasOperatorName("/"), + hasLHS(binaryOperator( + hasOperatorName("+"), hasEitherOperand(matchValue(1)), + hasEitherOperand(matchMathCall("sqrt", matchValue(5))))), + hasRHS(matchValue(2))); + return expr(anyOf(PhiFormula.bind("phi_pattern"), + matchFloatLiteralNear("phi_literal", llvm::numbers::phi))) + .bind("phi"); + } + + double DiffThreshold; +}; + +std::string getCode(const StringRef Constant, const bool IsFloat, + const bool IsLongDouble) { + if (IsFloat) { + return ("std::numbers::" + Constant + "_v").str(); + } + if (IsLongDouble) { + return ("std::numbers::" + Constant + "_v").str(); + } + return ("std::numbers::" + Constant).str(); +} + +bool isRangeOfCompleteMacro(const clang::SourceRange &Range, + const clang::SourceManager &SM, + const clang::LangOptions &LO) { + if (!Range.getBegin().isMacroID()) { + return false; + } + if (!clang::Lexer::isAtStartOfMacroExpansion(Range.getBegin(), SM, LO)) { + return false; + } + + if (!Range.getEnd().isMacroID()) { + return false; + } + + if (!clang::Lexer::isAtEndOfMacroExpansion(Range.getEnd(), SM, LO)) { + return false; + } + + return true; +} + +} // namespace + +namespace clang::tidy::modernize { +UseStdNumbersCheck::UseStdNumbersCheck(const StringRef Name, + ClangTidyContext *const Context) + : ClangTidyCheck(Name, Context), + IncludeInserter(Options.getLocalOrGlobal("IncludeStyle", + utils::IncludeSorter::IS_LLVM), + areDiagsSelfContained()), + DiffThresholdString{Options.get("DiffThreshold", "0.001")} { + if (DiffThresholdString.getAsDouble(DiffThreshold)) { + configurationDiag( + "Invalid DiffThreshold config value: '%0', expected a double") + << DiffThresholdString; + DiffThreshold = 0.001; + } +} + +void UseStdNumbersCheck::registerMatchers(MatchFinder *const Finder) { + const auto Matches = MatchBuilder{DiffThreshold}; + std::vector> ConstantMatchers = { + Matches.matchLog2Euler(), Matches.matchLog10Euler(), + Matches.matchEulerTopLevel(), Matches.matchEgamma(), + Matches.matchInvSqrtPi(), Matches.matchInvPi(), + Matches.matchPiTopLevel(), Matches.matchLn2(), + Matches.machterLn10(), Matches.matchSqrt2(), + Matches.matchInvSqrt3(), Matches.matchSqrt3(), + Matches.matchPhi(), + }; + + Finder->addMatcher( + expr( + anyOfExhaustive(std::move(ConstantMatchers)), + unless(hasParent(explicitCastExpr(hasDestinationType(isFloating())))), + hasType(qualType(hasCanonicalTypeUnqualified( + anyOf(qualType(asString("float")).bind("float"), + qualType(asString("double")), + qualType(asString("long double")).bind("long double")))))), + this); +} + +void UseStdNumbersCheck::check(const MatchFinder::MatchResult &Result) { + /* + List of all math constants in the `` header + + e + + log2e + + log10e + + pi + + inv_pi + + inv_sqrtpi + + ln2 + + ln10 + + sqrt2 + + sqrt3 + + inv_sqrt3 + + egamma + + phi + */ + + // The ordering determines what constants are looked at first. + // E.g. look at 'inv_sqrt3' before 'sqrt3' to be able to replace the larger + // expression + constexpr auto Constants = std::array, 13>{ + std::pair{StringRef{"log2e"}, llvm::numbers::log2e}, + std::pair{StringRef{"log10e"}, llvm::numbers::log10e}, + std::pair{StringRef{"e"}, llvm::numbers::e}, + std::pair{StringRef{"egamma"}, llvm::numbers::egamma}, + std::pair{StringRef{"inv_sqrtpi"}, llvm::numbers::inv_sqrtpi}, + std::pair{StringRef{"inv_pi"}, llvm::numbers::inv_pi}, + std::pair{StringRef{"pi"}, llvm::numbers::pi}, + std::pair{StringRef{"ln2"}, llvm::numbers::ln2}, + std::pair{StringRef{"ln10"}, llvm::numbers::ln10}, + std::pair{StringRef{"sqrt2"}, llvm::numbers::sqrt2}, + std::pair{StringRef{"inv_sqrt3"}, llvm::numbers::inv_sqrt3}, + std::pair{StringRef{"sqrt3"}, llvm::numbers::sqrt3}, + std::pair{StringRef{"phi"}, llvm::numbers::phi}, + }; + + auto MatchedLiterals = + llvm::SmallVector>{}; + + const auto &SM = *Result.SourceManager; + const auto &LO = Result.Context->getLangOpts(); + + const auto IsFloat = Result.Nodes.getNodeAs("float") != nullptr; + const auto IsLongDouble = + Result.Nodes.getNodeAs("long double") != nullptr; + + for (const auto &[ConstantName, ConstantValue] : Constants) { + const auto *const Match = Result.Nodes.getNodeAs(ConstantName); + if (Match == nullptr) { + continue; + } + + const auto Range = Match->getSourceRange(); + + const auto IsMacro = Range.getBegin().isMacroID(); + + // We do not want to emit a diagnostic when we are matching a macro, but the + // match inside of the macro does not cover the whole macro. + if (IsMacro && !isRangeOfCompleteMacro(Range, SM, LO)) { + continue; + } + + if (const auto PatternBindString = (ConstantName + "_pattern").str(); + Result.Nodes.getNodeAs(PatternBindString) != nullptr) { + const auto Code = getCode(ConstantName, IsFloat, IsLongDouble); + diag(Range.getBegin(), "prefer '%0' to this %select{formula|macro}1") + << Code << IsMacro << FixItHint::CreateReplacement(Range, Code); + return; + } + + const auto LiteralBindString = (ConstantName + "_literal").str(); + if (const auto *const Literal = + Result.Nodes.getNodeAs(LiteralBindString)) { + MatchedLiterals.emplace_back( + ConstantName, + std::abs(Literal->getValueAsApproximateDouble() - ConstantValue), + Match); + } + } + + // We may have had no matches with literals, but a match with a pattern that + // was a part of a macro which was therefore skipped. + if (MatchedLiterals.empty()) { + return; + } + + llvm::sort(MatchedLiterals, [](const auto &LHS, const auto &RHS) { + return std::get<1>(LHS) < std::get<1>(RHS); + }); + + const auto &[Constant, Diff, Node] = MatchedLiterals.front(); + + const auto Range = Node->getSourceRange(); + const auto IsMacro = Range.getBegin().isMacroID(); + + // We do not want to emit a diagnostic when we are matching a macro, but the + // match inside of the macro does not cover the whole macro. + if (IsMacro && !isRangeOfCompleteMacro(Range, SM, LO)) { + return; + } + + const auto Code = getCode(Constant, IsFloat, IsLongDouble); + diag(Range.getBegin(), + "prefer '%0' to this %select{literal|macro}1, differs by '%2'") + << Code << IsMacro << llvm::formatv("{0:e2}", Diff).str() + << FixItHint::CreateReplacement(Range, Code) + << IncludeInserter.createIncludeInsertion( + Result.SourceManager->getFileID(Range.getBegin()), ""); +} + +void UseStdNumbersCheck::registerPPCallbacks( + const SourceManager &SM, Preprocessor *const PP, + Preprocessor *const ModuleExpanderPP) { + IncludeInserter.registerPreprocessor(PP); +} + +void UseStdNumbersCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { + Options.store(Opts, "IncludeStyle", IncludeInserter.getStyle()); + Options.store(Opts, "DiffThreshold", DiffThresholdString); +} +} // namespace clang::tidy::modernize diff --git a/clang-tools-extra/clang-tidy/modernize/UseStdNumbersCheck.h b/clang-tools-extra/clang-tidy/modernize/UseStdNumbersCheck.h new file mode 100644 index 0000000000000000000000000000000000000000..05fc5ada14b87a15d96e5d31a3d482364f147040 --- /dev/null +++ b/clang-tools-extra/clang-tidy/modernize/UseStdNumbersCheck.h @@ -0,0 +1,49 @@ +//===--- UseStdNumbersCheck.h - clang-tidy ----------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USESTDNUMBERSCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USESTDNUMBERSCHECK_H + +#include "../ClangTidyCheck.h" +#include "../utils/IncludeInserter.h" + +namespace clang::tidy::modernize { + +/// Finds constants and function calls to math functions that can be replaced +/// with c++20's mathematical constants from the ``numbers`` header and +/// offers fix-it hints. +/// Does not match the use of variables with that value, and instead, +/// offers a replacement at the definition of those variables. +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/modernize/use-std-numbers.html +class UseStdNumbersCheck : public ClangTidyCheck { +public: + UseStdNumbersCheck(StringRef Name, ClangTidyContext *Context); + + bool isLanguageVersionSupported(const LangOptions &LangOpts) const override { + return LangOpts.CPlusPlus20; + } + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; + void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP, + Preprocessor *ModuleExpanderPP) override; + void storeOptions(ClangTidyOptions::OptionMap &Opts) override; + std::optional getCheckTraversalKind() const override { + return TK_IgnoreUnlessSpelledInSource; + } + +private: + utils::IncludeInserter IncludeInserter; + StringRef DiffThresholdString; + double DiffThreshold; +}; + +} // namespace clang::tidy::modernize + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USESTDNUMBERSCHECK_H diff --git a/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp b/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp index 990e20400fbfcd2beabc009601fc9f2c12b030e4..dfe12c5b6007da5b52640e9c623897e7dd98dce0 100644 --- a/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp +++ b/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp @@ -15,6 +15,7 @@ #include "clang/AST/Decl.h" #include "clang/Basic/Diagnostic.h" #include +#include namespace clang::tidy::performance { namespace { @@ -263,19 +264,25 @@ void UnnecessaryCopyInitialization::registerMatchers(MatchFinder *Finder) { void UnnecessaryCopyInitialization::check( const MatchFinder::MatchResult &Result) { - const auto *NewVar = Result.Nodes.getNodeAs("newVarDecl"); + const auto &NewVar = *Result.Nodes.getNodeAs("newVarDecl"); + const auto &BlockStmt = *Result.Nodes.getNodeAs("blockStmt"); + const auto &VarDeclStmt = *Result.Nodes.getNodeAs("declStmt"); + // Do not propose fixes if the DeclStmt has multiple VarDecls or in + // macros since we cannot place them correctly. + const bool IssueFix = + VarDeclStmt.isSingleDecl() && !NewVar.getLocation().isMacroID(); + const bool IsVarUnused = isVariableUnused(NewVar, BlockStmt, *Result.Context); + const bool IsVarOnlyUsedAsConst = + isOnlyUsedAsConst(NewVar, BlockStmt, *Result.Context); + const CheckContext Context{ + NewVar, BlockStmt, VarDeclStmt, *Result.Context, + IssueFix, IsVarUnused, IsVarOnlyUsedAsConst}; const auto *OldVar = Result.Nodes.getNodeAs(OldVarDeclId); const auto *ObjectArg = Result.Nodes.getNodeAs(ObjectArgId); - const auto *BlockStmt = Result.Nodes.getNodeAs("blockStmt"); const auto *CtorCall = Result.Nodes.getNodeAs("ctorCall"); - const auto *Stmt = Result.Nodes.getNodeAs("declStmt"); TraversalKindScope RAII(*Result.Context, TK_AsIs); - // Do not propose fixes if the DeclStmt has multiple VarDecls or in macros - // since we cannot place them correctly. - bool IssueFix = Stmt->isSingleDecl() && !NewVar->getLocation().isMacroID(); - // A constructor that looks like T(const T& t, bool arg = false) counts as a // copy only when it is called with default arguments for the arguments after // the first. @@ -289,74 +296,71 @@ void UnnecessaryCopyInitialization::check( // instantiations where the types differ and rely on implicit conversion would // no longer compile if we switched to a reference. if (differentReplacedTemplateParams( - NewVar->getType(), constructorArgumentType(OldVar, Result.Nodes), + Context.Var.getType(), constructorArgumentType(OldVar, Result.Nodes), *Result.Context)) return; if (OldVar == nullptr) { - handleCopyFromMethodReturn(*NewVar, *BlockStmt, *Stmt, IssueFix, ObjectArg, - *Result.Context); + // `auto NewVar = functionCall();` + handleCopyFromMethodReturn(Context, ObjectArg); } else { - handleCopyFromLocalVar(*NewVar, *OldVar, *BlockStmt, *Stmt, IssueFix, - *Result.Context); + // `auto NewVar = OldVar;` + handleCopyFromLocalVar(Context, *OldVar); } } void UnnecessaryCopyInitialization::handleCopyFromMethodReturn( - const VarDecl &Var, const Stmt &BlockStmt, const DeclStmt &Stmt, - bool IssueFix, const VarDecl *ObjectArg, ASTContext &Context) { - bool IsConstQualified = Var.getType().isConstQualified(); - if (!IsConstQualified && !isOnlyUsedAsConst(Var, BlockStmt, Context)) + const CheckContext &Ctx, const VarDecl *ObjectArg) { + bool IsConstQualified = Ctx.Var.getType().isConstQualified(); + if (!IsConstQualified && !Ctx.IsVarOnlyUsedAsConst) return; if (ObjectArg != nullptr && - !isInitializingVariableImmutable(*ObjectArg, BlockStmt, Context, + !isInitializingVariableImmutable(*ObjectArg, Ctx.BlockStmt, Ctx.ASTCtx, ExcludedContainerTypes)) return; - if (isVariableUnused(Var, BlockStmt, Context)) { - auto Diagnostic = - diag(Var.getLocation(), - "the %select{|const qualified }0variable %1 is copy-constructed " - "from a const reference but is never used; consider " - "removing the statement") - << IsConstQualified << &Var; - if (IssueFix) - recordRemoval(Stmt, Context, Diagnostic); - } else { - auto Diagnostic = - diag(Var.getLocation(), - "the %select{|const qualified }0variable %1 is copy-constructed " - "from a const reference%select{ but is only used as const " - "reference|}0; consider making it a const reference") - << IsConstQualified << &Var; - if (IssueFix) - recordFixes(Var, Context, Diagnostic); - } + diagnoseCopyFromMethodReturn(Ctx); } void UnnecessaryCopyInitialization::handleCopyFromLocalVar( - const VarDecl &NewVar, const VarDecl &OldVar, const Stmt &BlockStmt, - const DeclStmt &Stmt, bool IssueFix, ASTContext &Context) { - if (!isOnlyUsedAsConst(NewVar, BlockStmt, Context) || - !isInitializingVariableImmutable(OldVar, BlockStmt, Context, + const CheckContext &Ctx, const VarDecl &OldVar) { + if (!Ctx.IsVarOnlyUsedAsConst || + !isInitializingVariableImmutable(OldVar, Ctx.BlockStmt, Ctx.ASTCtx, ExcludedContainerTypes)) return; + diagnoseCopyFromLocalVar(Ctx, OldVar); +} - if (isVariableUnused(NewVar, BlockStmt, Context)) { - auto Diagnostic = diag(NewVar.getLocation(), - "local copy %0 of the variable %1 is never modified " - "and never used; " - "consider removing the statement") - << &NewVar << &OldVar; - if (IssueFix) - recordRemoval(Stmt, Context, Diagnostic); - } else { - auto Diagnostic = - diag(NewVar.getLocation(), - "local copy %0 of the variable %1 is never modified; " - "consider avoiding the copy") - << &NewVar << &OldVar; - if (IssueFix) - recordFixes(NewVar, Context, Diagnostic); +void UnnecessaryCopyInitialization::diagnoseCopyFromMethodReturn( + const CheckContext &Ctx) { + auto Diagnostic = + diag(Ctx.Var.getLocation(), + "the %select{|const qualified }0variable %1 is " + "copy-constructed " + "from a const reference%select{%select{ but is only used as const " + "reference|}0| but is never used}2; consider " + "%select{making it a const reference|removing the statement}2") + << Ctx.Var.getType().isConstQualified() << &Ctx.Var << Ctx.IsVarUnused; + maybeIssueFixes(Ctx, Diagnostic); +} + +void UnnecessaryCopyInitialization::diagnoseCopyFromLocalVar( + const CheckContext &Ctx, const VarDecl &OldVar) { + auto Diagnostic = + diag(Ctx.Var.getLocation(), + "local copy %1 of the variable %0 is never modified%select{" + "| and never used}2; consider %select{avoiding the copy|removing " + "the statement}2") + << &OldVar << &Ctx.Var << Ctx.IsVarUnused; + maybeIssueFixes(Ctx, Diagnostic); +} + +void UnnecessaryCopyInitialization::maybeIssueFixes( + const CheckContext &Ctx, DiagnosticBuilder &Diagnostic) { + if (Ctx.IssueFix) { + if (Ctx.IsVarUnused) + recordRemoval(Ctx.VarDeclStmt, Ctx.ASTCtx, Diagnostic); + else + recordFixes(Ctx.Var, Ctx.ASTCtx, Diagnostic); } } diff --git a/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.h b/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.h index ea009ba9979de97249cd20550d83b73519f13019..ab0f1ecf61063be5b621efcf4a530487d4b82876 100644 --- a/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.h +++ b/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.h @@ -32,14 +32,32 @@ public: void check(const ast_matchers::MatchFinder::MatchResult &Result) override; void storeOptions(ClangTidyOptions::OptionMap &Opts) override; +protected: + // A helper to manipulate the state common to + // `CopyFromMethodReturn` and `CopyFromLocalVar`. + struct CheckContext { + const VarDecl &Var; + const Stmt &BlockStmt; + const DeclStmt &VarDeclStmt; + clang::ASTContext &ASTCtx; + const bool IssueFix; + const bool IsVarUnused; + const bool IsVarOnlyUsedAsConst; + }; + + // Create diagnostics. These are virtual so that derived classes can change + // behaviour. + virtual void diagnoseCopyFromMethodReturn(const CheckContext &Ctx); + virtual void diagnoseCopyFromLocalVar(const CheckContext &Ctx, + const VarDecl &OldVar); + private: - void handleCopyFromMethodReturn(const VarDecl &Var, const Stmt &BlockStmt, - const DeclStmt &Stmt, bool IssueFix, - const VarDecl *ObjectArg, - ASTContext &Context); - void handleCopyFromLocalVar(const VarDecl &NewVar, const VarDecl &OldVar, - const Stmt &BlockStmt, const DeclStmt &Stmt, - bool IssueFix, ASTContext &Context); + void handleCopyFromMethodReturn(const CheckContext &Ctx, + const VarDecl *ObjectArg); + void handleCopyFromLocalVar(const CheckContext &Ctx, const VarDecl &OldVar); + + void maybeIssueFixes(const CheckContext &Ctx, DiagnosticBuilder &Diagnostic); + const std::vector AllowedTypes; const std::vector ExcludedContainerTypes; }; diff --git a/clang-tools-extra/clang-tidy/readability/FunctionCognitiveComplexityCheck.cpp b/clang-tools-extra/clang-tidy/readability/FunctionCognitiveComplexityCheck.cpp index 831614148c7c25a354b22242e7592aa4f896eb65..759cdd44fd6581c3f2abcdd61b53967f8fd63a61 100644 --- a/clang-tools-extra/clang-tidy/readability/FunctionCognitiveComplexityCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/FunctionCognitiveComplexityCheck.cpp @@ -20,6 +20,7 @@ #include "clang/Basic/DiagnosticIDs.h" #include "clang/Basic/LLVM.h" #include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/STLForwardCompat.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Casting.h" #include "llvm/Support/ErrorHandling.h" @@ -167,15 +168,13 @@ static const std::array Msgs = {{ // Criteria is a bitset, thus a few helpers are needed. CognitiveComplexity::Criteria operator|(CognitiveComplexity::Criteria LHS, CognitiveComplexity::Criteria RHS) { - return static_cast( - static_cast>(LHS) | - static_cast>(RHS)); + return static_cast(llvm::to_underlying(LHS) | + llvm::to_underlying(RHS)); } CognitiveComplexity::Criteria operator&(CognitiveComplexity::Criteria LHS, CognitiveComplexity::Criteria RHS) { - return static_cast( - static_cast>(LHS) & - static_cast>(RHS)); + return static_cast(llvm::to_underlying(LHS) & + llvm::to_underlying(RHS)); } CognitiveComplexity::Criteria &operator|=(CognitiveComplexity::Criteria &LHS, CognitiveComplexity::Criteria RHS) { diff --git a/clang-tools-extra/clangd/IncludeCleaner.cpp b/clang-tools-extra/clangd/IncludeCleaner.cpp index b0a3c290bad660483327438404f8852783675e06..dda7c9f581f69c7b03517416b2ce2f08cb279d79 100644 --- a/clang-tools-extra/clangd/IncludeCleaner.cpp +++ b/clang-tools-extra/clangd/IncludeCleaner.cpp @@ -397,10 +397,10 @@ IncludeCleanerFindings computeIncludeCleanerFindings(ParsedAST &AST) { std::vector MissingIncludes; llvm::DenseSet Used; trace::Span Tracer("include_cleaner::walkUsed"); - const DirectoryEntry *ResourceDir = AST.getPreprocessor() - .getHeaderSearchInfo() - .getModuleMap() - .getBuiltinDir(); + OptionalDirectoryEntryRef ResourceDir = AST.getPreprocessor() + .getHeaderSearchInfo() + .getModuleMap() + .getBuiltinDir(); include_cleaner::walkUsed( AST.getLocalTopLevelDecls(), /*MacroRefs=*/Macros, AST.getPragmaIncludes().get(), AST.getPreprocessor(), diff --git a/clang-tools-extra/clangd/SemanticHighlighting.cpp b/clang-tools-extra/clangd/SemanticHighlighting.cpp index 49e479abf456210a90b1c596fd786477eb8c0498..37939d36425a970465fa66863e68dce74e13bc02 100644 --- a/clang-tools-extra/clangd/SemanticHighlighting.cpp +++ b/clang-tools-extra/clangd/SemanticHighlighting.cpp @@ -418,7 +418,8 @@ class HighlightingsBuilder { public: HighlightingsBuilder(const ParsedAST &AST, const HighlightingFilter &Filter) : TB(AST.getTokens()), SourceMgr(AST.getSourceManager()), - LangOpts(AST.getLangOpts()), Filter(Filter) {} + LangOpts(AST.getLangOpts()), Filter(Filter), + Resolver(AST.getHeuristicResolver()) {} HighlightingToken &addToken(SourceLocation Loc, HighlightingKind Kind) { auto Range = getRangeForSourceLocation(Loc); @@ -589,7 +590,7 @@ private: HighlightingFilter Filter; std::vector Tokens; std::map> ExtraModifiers; - const HeuristicResolver *Resolver = nullptr; + const HeuristicResolver *Resolver; // returned from addToken(InvalidLoc) HighlightingToken InvalidHighlightingToken; }; diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 4ff4494cef5624153b84a63c63bbacffcb19a640..6d91748e4cef18c7329b2ded0e68125500f44847 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -174,6 +174,12 @@ New checks Flags coroutines that suspend while a lock guard is in scope at the suspension point. +- New :doc:`hicpp-ignored-remove-result + ` check. + + Ensure that the result of ``std::remove``, ``std::remove_if`` and + ``std::unique`` are not ignored according to rule 17.5.1. + - New :doc:`misc-coroutine-hostile-raii ` check. @@ -193,6 +199,13 @@ New checks replacing with ``starts_with`` when the method exists in the class. Notably, this will work with ``std::string`` and ``std::string_view``. +- New :doc:`modernize-use-std-numbers + ` check. + + Finds constants and function calls to math functions that can be replaced + with C++20's mathematical constants from the ``numbers`` header and + offers fix-it hints. + - New :doc:`performance-enum-size ` check. diff --git a/clang-tools-extra/docs/clang-tidy/checks/hicpp/ignored-remove-result.rst b/clang-tools-extra/docs/clang-tidy/checks/hicpp/ignored-remove-result.rst new file mode 100644 index 0000000000000000000000000000000000000000..6ca704ae3e66c71d2b7c1352a7fa164b0195cd70 --- /dev/null +++ b/clang-tools-extra/docs/clang-tidy/checks/hicpp/ignored-remove-result.rst @@ -0,0 +1,24 @@ +.. title:: clang-tidy - hicpp-ignored-remove-result + +hicpp-ignored-remove-result +=========================== + +Ensure that the result of ``std::remove``, ``std::remove_if`` and ``std::unique`` +are not ignored according to +`rule 17.5.1 `_. + +The mutating algorithms ``std::remove``, ``std::remove_if`` and both overloads +of ``std::unique`` operate by swapping or moving elements of the range they are +operating over. On completion, they return an iterator to the last valid +element. In the majority of cases the correct behavior is to use this result as +the first operand in a call to ``std::erase``. + +This check is a subset of :doc:`bugprone-unused-return-value <../bugprone/unused-return-value>` +and depending on used options it can be superfluous to enable both checks. + +Options +------- + +.. option:: AllowCastToVoid + + Controls whether casting return values to ``void`` is permitted. Default: `true`. diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst index df2d5d15238d63c6ecb74f1c1e83eea2df030b5f..31f0e090db1d7de7d39a540e50a0131f96b9db91 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/list.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst @@ -226,6 +226,7 @@ Clang-Tidy Checks :doc:`google-runtime-operator `, :doc:`google-upgrade-googletest-case `, "Yes" :doc:`hicpp-exception-baseclass `, + :doc:`hicpp-ignored-remove-result `, :doc:`hicpp-multiway-paths-covered `, :doc:`hicpp-no-assembler `, :doc:`hicpp-signed-bitwise `, @@ -293,6 +294,7 @@ Clang-Tidy Checks :doc:`modernize-use-nullptr `, "Yes" :doc:`modernize-use-override `, "Yes" :doc:`modernize-use-starts-ends-with `, "Yes" + :doc:`modernize-use-std-numbers `, "Yes" :doc:`modernize-use-std-print `, "Yes" :doc:`modernize-use-trailing-return-type `, "Yes" :doc:`modernize-use-transparent-functors `, "Yes" diff --git a/clang-tools-extra/docs/clang-tidy/checks/modernize/use-std-numbers.rst b/clang-tools-extra/docs/clang-tidy/checks/modernize/use-std-numbers.rst new file mode 100644 index 0000000000000000000000000000000000000000..207e9c00e74ba0f7771c0d7c639e71e56708be72 --- /dev/null +++ b/clang-tools-extra/docs/clang-tidy/checks/modernize/use-std-numbers.rst @@ -0,0 +1,74 @@ +.. title:: clang-tidy - modernize-use-std-numbers + +modernize-use-std-numbers +========================= + +Finds constants and function calls to math functions that can be replaced +with C++20's mathematical constants from the ``numbers`` header and offers +fix-it hints. +Does not match the use of variables with that value, and instead, +offers a replacement for the definition of those variables. +Function calls that match the pattern of how the constant is calculated are +matched and replaced with the ``std::numbers`` constant. +The use of macros gets replaced with the corresponding ``std::numbers`` +constant, instead of changing the macro definition. + +The following list of constants from the ``numbers`` header are supported: + +* ``e`` +* ``log2e`` +* ``log10e`` +* ``pi`` +* ``inv_pi`` +* ``inv_sqrtpi`` +* ``ln2`` +* ``ln10`` +* ``sqrt2`` +* ``sqrt3`` +* ``inv_sqrt3`` +* ``egamma`` +* ``phi`` + +The list currently includes all constants as of C++20. + +The replacements use the type of the matched constant and can remove explicit +casts, i.e., switching between ``std::numbers::e``, +``std::numbers::e_v`` and ``std::numbers::e_v`` where +appropriate. + +.. code-block:: c++ + + double sqrt(double); + double log2(double); + void sink(auto&&) {} + void floatSink(float); + + #define MY_PI 3.1415926 + + void foo() { + const double Pi = 3.141592653589; // const double Pi = std::numbers::pi + const auto Use = Pi / 2; // no match for Pi + static constexpr double Euler = 2.7182818; // static constexpr double Euler = std::numbers::e; + + log2(exp(1)); // std::numbers::log2e; + log2(Euler); // std::numbers::log2e; + 1 / sqrt(MY_PI); // std::numbers::inv_sqrtpi; + sink(MY_PI); // sink(std::numbers::pi); + floatSink(MY_PI); // floatSink(std::numbers::pi); + floatSink(static_cast(MY_PI)); // floatSink(std::numbers::pi_v); + } + +Options +------- + +.. option:: DiffThreshold + + A floating point value that sets the detection threshold for when literals + match a constant. A literal matches a constant if + ``abs(literal - constant) < DiffThreshold`` evaluates to ``true``. Default + is `0.001`. + +.. option:: IncludeStyle + + A string specifying which include-style is used, `llvm` or `google`. Default + is `llvm`. diff --git a/clang-tools-extra/include-cleaner/lib/Analysis.cpp b/clang-tools-extra/include-cleaner/lib/Analysis.cpp index 09365c36f9f2c5577eff28385b9fee6f636157ab..450c4c796c141567f8620fe03b631e7d0160b91d 100644 --- a/clang-tools-extra/include-cleaner/lib/Analysis.cpp +++ b/clang-tools-extra/include-cleaner/lib/Analysis.cpp @@ -87,7 +87,7 @@ analyze(llvm::ArrayRef ASTRoots, llvm::StringSet<> Missing; if (!HeaderFilter) HeaderFilter = [](llvm::StringRef) { return false; }; - const DirectoryEntry *ResourceDir = + OptionalDirectoryEntryRef ResourceDir = PP.getHeaderSearchInfo().getModuleMap().getBuiltinDir(); walkUsed(ASTRoots, MacroRefs, PI, PP, [&](const SymbolReference &Ref, llvm::ArrayRef
Providers) { @@ -95,7 +95,7 @@ analyze(llvm::ArrayRef ASTRoots, for (const Header &H : Providers) { if (H.kind() == Header::Physical && (H.physical() == MainFile || - H.physical().getDir() == ResourceDir)) { + (ResourceDir && H.physical().getDir() == *ResourceDir))) { Satisfied = true; } for (const Include *I : Inc.match(H)) { @@ -114,7 +114,7 @@ analyze(llvm::ArrayRef ASTRoots, for (const Include &I : Inc.all()) { if (Used.contains(&I) || !I.Resolved || HeaderFilter(I.Resolved->getFileEntry().tryGetRealPathName()) || - I.Resolved->getFileEntry().getDir() == ResourceDir) + (ResourceDir && I.Resolved->getFileEntry().getDir() == *ResourceDir)) continue; if (PI) { if (PI->shouldKeep(*I.Resolved)) diff --git a/clang-tools-extra/modularize/ModuleAssistant.cpp b/clang-tools-extra/modularize/ModuleAssistant.cpp index 0d4c09987eb1cf1c87f54f57ee955c5cfc6f9b01..5c11ffdb8589d55e224680835d1b887e09b53f55 100644 --- a/clang-tools-extra/modularize/ModuleAssistant.cpp +++ b/clang-tools-extra/modularize/ModuleAssistant.cpp @@ -175,7 +175,7 @@ static bool addModuleDescription(Module *RootModule, llvm::SmallString<256> NativePath, NativePrefix; llvm::sys::path::native(HeaderFilePath, NativePath); llvm::sys::path::native(HeaderPrefix, NativePrefix); - if (NativePath.startswith(NativePrefix)) + if (NativePath.starts_with(NativePrefix)) FilePath = std::string(NativePath.substr(NativePrefix.size() + 1)); else FilePath = std::string(HeaderFilePath); diff --git a/clang-tools-extra/pseudo/include/clang-pseudo/Token.h b/clang-tools-extra/pseudo/include/clang-pseudo/Token.h index 22b72c71cbbabc86ec26031bf3b8048f5c6ee896..859fd7d2b3dfe289e391c1b515ac18554274ac3e 100644 --- a/clang-tools-extra/pseudo/include/clang-pseudo/Token.h +++ b/clang-tools-extra/pseudo/include/clang-pseudo/Token.h @@ -32,6 +32,7 @@ #include "clang/Basic/LangStandard.h" #include "clang/Basic/TokenKinds.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/STLForwardCompat.h" #include "llvm/Support/raw_ostream.h" #include #include @@ -71,10 +72,10 @@ struct Token { Index OriginalIndex = Invalid; // Helpers to get/set Flags based on `enum class`. template bool flag(T Mask) const { - return Flags & uint8_t{static_cast>(Mask)}; + return Flags & uint8_t{llvm::to_underlying(Mask)}; } template void setFlag(T Mask) { - Flags |= uint8_t{static_cast>(Mask)}; + Flags |= uint8_t{llvm::to_underlying(Mask)}; } /// Returns the next token in the stream. this may not be a sentinel. diff --git a/clang-tools-extra/test/clang-tidy/checkers/hicpp/ignored-remove-result.cpp b/clang-tools-extra/test/clang-tidy/checkers/hicpp/ignored-remove-result.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b068f08590989394dc5702f310515d9c4b7f8793 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/hicpp/ignored-remove-result.cpp @@ -0,0 +1,66 @@ +// RUN: %check_clang_tidy %s hicpp-ignored-remove-result %t +// RUN: %check_clang_tidy -check-suffixes=NOCAST %s hicpp-ignored-remove-result %t -- -config='{CheckOptions: {hicpp-ignored-remove-result.AllowCastToVoid: false}}' + +namespace std { + +template +ForwardIt remove(ForwardIt, ForwardIt, const T &); + +template +ForwardIt remove_if(ForwardIt, ForwardIt, UnaryPredicate); + +template +ForwardIt unique(ForwardIt, ForwardIt); + +template +InputIt find(InputIt, InputIt, const T&); + +class error_code { +}; + +} // namespace std + +std::error_code errorFunc() { + return std::error_code(); +} + +void warning() { + std::remove(nullptr, nullptr, 1); + // CHECK-MESSAGES: [[@LINE-1]]:3: warning: the value returned by this function should not be disregarded; neglecting it may lead to errors + // CHECK-MESSAGES: [[@LINE-2]]:3: note: cast the expression to void to silence this warning + // CHECK-MESSAGES-NOCAST: [[@LINE-3]]:3: warning: the value returned by this function should not be disregarded; neglecting it may lead to errors + + std::remove_if(nullptr, nullptr, nullptr); + // CHECK-MESSAGES: [[@LINE-1]]:3: warning: the value returned by this function should not be disregarded; neglecting it may lead to errors + // CHECK-MESSAGES: [[@LINE-2]]:3: note: cast the expression to void to silence this warning + // CHECK-MESSAGES-NOCAST: [[@LINE-3]]:3: warning: the value returned by this function should not be disregarded; neglecting it may lead to errors + + std::unique(nullptr, nullptr); + // CHECK-MESSAGES: [[@LINE-1]]:3: warning: the value returned by this function should not be disregarded; neglecting it may lead to errors + // CHECK-MESSAGES: [[@LINE-2]]:3: note: cast the expression to void to silence this warning + // CHECK-MESSAGES-NOCAST: [[@LINE-3]]:3: warning: the value returned by this function should not be disregarded; neglecting it may lead to errors +} + +void optionalWarning() { + // No warning unless AllowCastToVoid=false + (void)std::remove(nullptr, nullptr, 1); + // CHECK-MESSAGES-NOCAST: [[@LINE-1]]:9: warning: the value returned by this function should not be disregarded; neglecting it may lead to errors +} + +void noWarning() { + + auto RemoveRetval = std::remove(nullptr, nullptr, 1); + + auto RemoveIfRetval = std::remove_if(nullptr, nullptr, nullptr); + + auto UniqueRetval = std::unique(nullptr, nullptr); + + // Verify that other checks in the baseclass are not used. + // - no warning on std::find since the checker overrides + // bugprone-unused-return-value's checked functions. + std::find(nullptr, nullptr, 1); + // - no warning on return types since the checker disable + // bugprone-unused-return-value's checked return types. + errorFunc(); + (void) errorFunc(); +} diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-numbers.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-numbers.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6c5762da5e2e841f81a95f71b62bed98ed25a9cd --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-numbers.cpp @@ -0,0 +1,493 @@ +// RUN: %check_clang_tidy -check-suffix=ALL -std=c++20 %s modernize-use-std-numbers %t +// RUN: %check_clang_tidy -check-suffix=ALL,IMPRECISE -std=c++20 %s modernize-use-std-numbers %t -- -config="{CheckOptions: { modernize-use-std-numbers.DiffThreshold: 0.01 }}" + +// CHECK-FIXES-ALL: #include + +namespace bar { + double sqrt(double Arg); + float sqrt(float Arg); + template + auto sqrt(T val) { return sqrt(static_cast(val)); } + + static constexpr double e = 2.718281828459045235360287471352662497757247093; + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:33: warning: prefer 'std::numbers::e' to this literal, differs by '0.00e+00' [modernize-use-std-numbers] + // CHECK-FIXES-ALL: static constexpr double e = std::numbers::e; +} + +double exp(double Arg); +double log(double Arg); + +double log2(double Arg); +float log2(float Arg); +template +auto log2(T val) { return log2(static_cast(val)); } + +double log10(double Arg); + +template +void sink(T&&) { } + +void floatSink(float) {} + +#define MY_PI 3.1415926 + +#define INV_SQRT3 1 / bar::sqrt(3) +#define NOT_INV_SQRT3 1 / bar::sqrt(3) + 1 + +using my_double = double; +using my_float = float; + +void foo(){ + static constexpr double Pi = 3.1415926; + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:34: warning: prefer 'std::numbers::pi' to this literal, differs by '5.36e-08' [modernize-use-std-numbers] + // CHECK-FIXES-ALL: static constexpr double Pi = std::numbers::pi; + + static constexpr double Euler = 2.7182818; + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:37: warning: prefer 'std::numbers::e' to this literal, differs by '2.85e-08' [modernize-use-std-numbers] + // CHECK-FIXES-ALL: static constexpr double Euler = std::numbers::e; + + static constexpr double Phi = 1.6180339; + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:35: warning: prefer 'std::numbers::phi' to this literal, differs by '8.87e-08' [modernize-use-std-numbers] + // CHECK-FIXES-ALL: static constexpr double Phi = std::numbers::phi; + + static constexpr double PiCopy = Pi; + static constexpr double PiDefineFromMacro = MY_PI; + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:49: warning: prefer 'std::numbers::pi' to this macro, differs by '5.36e-08' [modernize-use-std-numbers] + // CHECK-FIXES-ALL: static constexpr double PiDefineFromMacro = std::numbers::pi; + + static constexpr double Pi2 = 3.14; + // CHECK-MESSAGES-IMPRECISE: :[[@LINE-1]]:35: warning: prefer 'std::numbers::pi' to this literal, differs by '1.59e-03' [modernize-use-std-numbers] + // CHECK-FIXES-IMPRECISE: static constexpr double Pi2 = std::numbers::pi; + static constexpr double Euler2 = 2.71; + // CHECK-MESSAGES-IMPRECISE: :[[@LINE-1]]:38: warning: prefer 'std::numbers::e' to this literal, differs by '8.28e-03' [modernize-use-std-numbers] + // CHECK-FIXES-IMPRECISE: static constexpr double Euler2 = std::numbers::e; + static constexpr double Phi2 = 1.61; + // CHECK-MESSAGES-IMPRECISE: :[[@LINE-1]]:36: warning: prefer 'std::numbers::phi' to this literal, differs by '8.03e-03' [modernize-use-std-numbers] + // CHECK-FIXES-IMPRECISE: static constexpr double Phi2 = std::numbers::phi; + + static constexpr double Pi3 = 3.1415926L; + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:35: warning: prefer 'std::numbers::pi_v' to this literal, differs by '5.36e-08' [modernize-use-std-numbers] + // CHECK-FIXES-ALL: static constexpr double Pi3 = std::numbers::pi_v; + + static constexpr double Euler3 = 2.7182818L; + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:38: warning: prefer 'std::numbers::e_v' to this literal, differs by '2.85e-08' [modernize-use-std-numbers] + // CHECK-FIXES-ALL: static constexpr double Euler3 = std::numbers::e_v; + + static constexpr double Phi3 = 1.6180339L; + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:36: warning: prefer 'std::numbers::phi_v' to this literal, differs by '8.87e-08' [modernize-use-std-numbers] + // CHECK-FIXES-ALL: static constexpr double Phi3 = std::numbers::phi_v; + + static constexpr long double Pi4 = 3.1415926L; + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:40: warning: prefer 'std::numbers::pi_v' to this literal, differs by '5.36e-08' [modernize-use-std-numbers] + // CHECK-FIXES-ALL: static constexpr long double Pi4 = std::numbers::pi_v; + + static constexpr long double Euler4 = 2.7182818L; + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:43: warning: prefer 'std::numbers::e_v' to this literal, differs by '2.85e-08' [modernize-use-std-numbers] + // CHECK-FIXES-ALL: static constexpr long double Euler4 = std::numbers::e_v; + + static constexpr long double Phi4 = 1.6180339L; + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:41: warning: prefer 'std::numbers::phi_v' to this literal, differs by '8.87e-08' [modernize-use-std-numbers] + // CHECK-FIXES-ALL: static constexpr long double Phi4 = std::numbers::phi_v; + + static constexpr my_double Euler5 = 2.7182818; + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:41: warning: prefer 'std::numbers::e' to this literal, differs by '2.85e-08' [modernize-use-std-numbers] + // CHECK-FIXES-ALL: static constexpr my_double Euler5 = std::numbers::e; + + static constexpr my_float Euler6 = 2.7182818; + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:40: warning: prefer 'std::numbers::e' to this literal, differs by '2.85e-08' [modernize-use-std-numbers] + // CHECK-FIXES-ALL: static constexpr my_float Euler6 = std::numbers::e; + + static constexpr int NotEuler7 = 2.7182818; + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:38: warning: prefer 'std::numbers::e' to this literal, differs by '2.85e-08' [modernize-use-std-numbers] + // CHECK-FIXES-ALL: static constexpr int NotEuler7 = std::numbers::e; + + static constexpr double InvPi = 1.0 / Pi; + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:37: warning: prefer 'std::numbers::inv_pi' to this formula [modernize-use-std-numbers] + // CHECK-FIXES-ALL: static constexpr double InvPi = std::numbers::inv_pi; + + static constexpr my_float Actually2MyFloat = 2; + bar::sqrt(Actually2MyFloat); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:5: warning: prefer 'std::numbers::sqrt2_v' to this formula [modernize-use-std-numbers] + // CHECK-FIXES-ALL: std::numbers::sqrt2_v; + + sink(MY_PI); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:10: warning: prefer 'std::numbers::pi' to this macro, differs by '5.36e-08' [modernize-use-std-numbers] + // CHECK-FIXES-ALL: sink(std::numbers::pi); + + auto X = 42.0; + auto Y = X * 3.14; + // CHECK-MESSAGES-IMPRECISE: :[[@LINE-1]]:18: warning: prefer 'std::numbers::pi' to this literal, differs by '1.59e-03' [modernize-use-std-numbers] + // CHECK-FIXES-IMPRECISE: auto Y = X * std::numbers::pi; + + constexpr static auto One = 1; + constexpr static auto Two = 2; + + bar::sqrt(2); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:5: warning: prefer 'std::numbers::sqrt2' to this formula [modernize-use-std-numbers] + // CHECK-FIXES-ALL: std::numbers::sqrt2; + + bar::sqrt(Two); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:5: warning: prefer 'std::numbers::sqrt2' to this formula [modernize-use-std-numbers] + // CHECK-FIXES-ALL: std::numbers::sqrt2; + + bar::sqrt(2.0); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:5: warning: prefer 'std::numbers::sqrt2' to this formula [modernize-use-std-numbers] + // CHECK-FIXES-ALL: std::numbers::sqrt2; + + auto Not2 = 2; + Not2 = 42; + bar::sqrt(Not2); + + const auto Actually2 = 2; + bar::sqrt(Actually2); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:5: warning: prefer 'std::numbers::sqrt2' to this formula [modernize-use-std-numbers] + // CHECK-FIXES-ALL: std::numbers::sqrt2; + + exp(1); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:5: warning: prefer 'std::numbers::e' to this formula [modernize-use-std-numbers] + // CHECK-FIXES-ALL: std::numbers::e; + + exp(One); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:5: warning: prefer 'std::numbers::e' to this formula [modernize-use-std-numbers] + // CHECK-FIXES-ALL: std::numbers::e; + + exp(1.00000000000001); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:5: warning: prefer 'std::numbers::e' to this formula [modernize-use-std-numbers] + // CHECK-FIXES-ALL: std::numbers::e; + + log2(exp(1)); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:5: warning: prefer 'std::numbers::log2e' to this formula [modernize-use-std-numbers] + // CHECK-MESSAGES-ALL: :[[@LINE-2]]:10: warning: prefer 'std::numbers::e' to this formula [modernize-use-std-numbers] + // CHECK-FIXES-ALL: std::numbers::log2e; + + log2(Euler); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:5: warning: prefer 'std::numbers::log2e' to this formula [modernize-use-std-numbers] + // CHECK-FIXES-ALL: std::numbers::log2e; + + log2(bar::e); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:5: warning: prefer 'std::numbers::log2e' to this formula [modernize-use-std-numbers] + // CHECK-FIXES-ALL: std::numbers::log2e; + + log2(Euler5); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:5: warning: prefer 'std::numbers::log2e' to this formula [modernize-use-std-numbers] + // CHECK-FIXES-ALL: std::numbers::log2e; + + log2(Euler6); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:5: warning: prefer 'std::numbers::log2e_v' to this formula [modernize-use-std-numbers] + // CHECK-FIXES-ALL: std::numbers::log2e_v; + + log2(NotEuler7); + + auto log2e = 1.4426950; + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:18: warning: prefer 'std::numbers::log2e' to this literal, differs by '4.09e-08' [modernize-use-std-numbers] + // CHECK-FIXES-ALL: auto log2e = std::numbers::log2e; + + floatSink(log2(Euler)); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:15: warning: prefer 'std::numbers::log2e' to this formula [modernize-use-std-numbers] + // CHECK-FIXES-ALL: floatSink(std::numbers::log2e); + + floatSink(static_cast(log2(Euler))); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:15: warning: prefer 'std::numbers::log2e_v' to this formula [modernize-use-std-numbers] + // CHECK-FIXES-ALL: floatSink(std::numbers::log2e_v); + + floatSink(1.4426950); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:15: warning: prefer 'std::numbers::log2e' to this literal, differs by '4.09e-08' [modernize-use-std-numbers] + // CHECK-FIXES-ALL: floatSink(std::numbers::log2e); + + floatSink(static_cast(1.4426950)); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:15: warning: prefer 'std::numbers::log2e_v' to this literal, differs by '4.09e-08' [modernize-use-std-numbers] + // CHECK-FIXES-ALL: floatSink(std::numbers::log2e_v); + + floatSink(log2(static_cast(Euler))); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:15: warning: prefer 'std::numbers::log2e_v' to this formula [modernize-use-std-numbers] + // CHECK-FIXES-ALL: floatSink(std::numbers::log2e_v); + + floatSink(static_cast(log2(static_cast(Euler)))); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:15: warning: prefer 'std::numbers::log2e_v' to this formula [modernize-use-std-numbers] + // CHECK-FIXES-ALL: floatSink(std::numbers::log2e_v); + + floatSink(static_cast(log2(static_cast(Euler)))); + + floatSink(static_cast(log2(static_cast(Euler)))); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:32: warning: prefer 'std::numbers::log2e_v' to this formula [modernize-use-std-numbers] + // CHECK-FIXES-ALL: floatSink(static_cast(std::numbers::log2e_v)); + + floatSink(1.4426950F); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:15: warning: prefer 'std::numbers::log2e_v' to this literal, differs by '1.93e-08' [modernize-use-std-numbers] + // CHECK-FIXES-ALL: floatSink(std::numbers::log2e_v); + + floatSink(static_cast(1.4426950F)); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:15: warning: prefer 'std::numbers::log2e' to this literal, differs by '1.93e-08' [modernize-use-std-numbers] + // CHECK-FIXES-ALL: floatSink(std::numbers::log2e); + + floatSink(static_cast(1.4426950F)); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:32: warning: prefer 'std::numbers::log2e_v' to this literal, differs by '1.93e-08' [modernize-use-std-numbers] + // CHECK-FIXES-ALL: floatSink(static_cast(std::numbers::log2e_v)); + + log10(exp(1)); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:5: warning: prefer 'std::numbers::log10e' to this formula [modernize-use-std-numbers] + // CHECK-MESSAGES-ALL: :[[@LINE-2]]:11: warning: prefer 'std::numbers::e' to this formula [modernize-use-std-numbers] + // CHECK-FIXES-ALL: std::numbers::log10e; + + log10(Euler); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:5: warning: prefer 'std::numbers::log10e' to this formula [modernize-use-std-numbers] + // CHECK-FIXES-ALL: std::numbers::log10e; + + log10(bar::e); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:5: warning: prefer 'std::numbers::log10e' to this formula [modernize-use-std-numbers] + // CHECK-FIXES-ALL: std::numbers::log10e; + + auto log10e = .434294; + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:19: warning: prefer 'std::numbers::log10e' to this literal, differs by '4.82e-07' [modernize-use-std-numbers] + // CHECK-FIXES-ALL: auto log10e = std::numbers::log10e; + + auto egamma = 0.5772156 * 42; + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:19: warning: prefer 'std::numbers::egamma' to this literal, differs by '6.49e-08' [modernize-use-std-numbers] + // CHECK-FIXES-ALL: auto egamma = std::numbers::egamma * 42; + + sink(InvPi); + + sink(1 / Pi); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:10: warning: prefer 'std::numbers::inv_pi' to this formula [modernize-use-std-numbers] + // CHECK-FIXES-ALL: sink(std::numbers::inv_pi); + + sink(1 / bar::sqrt(Pi)); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:10: warning: prefer 'std::numbers::inv_sqrtpi' to this formula [modernize-use-std-numbers] + // CHECK-FIXES-ALL: sink(std::numbers::inv_sqrtpi); + + sink(1 / bar::sqrt(MY_PI)); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:10: warning: prefer 'std::numbers::inv_sqrtpi' to this formula [modernize-use-std-numbers] + // CHECK-MESSAGES-ALL: :[[@LINE-2]]:24: warning: prefer 'std::numbers::pi' to this macro, differs by '5.36e-08' [modernize-use-std-numbers] + // CHECK-FIXES-ALL: sink(std::numbers::inv_sqrtpi); + + log(2); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:5: warning: prefer 'std::numbers::ln2' to this formula [modernize-use-std-numbers] + // CHECK-FIXES-ALL: std::numbers::ln2; + + log(10); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:5: warning: prefer 'std::numbers::ln10' to this formula [modernize-use-std-numbers] + // CHECK-FIXES-ALL: std::numbers::ln10; + + bar::sqrt(2); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:5: warning: prefer 'std::numbers::sqrt2' to this formula [modernize-use-std-numbers] + // CHECK-FIXES-ALL: std::numbers::sqrt2; + + sink(1 / bar::sqrt(3)); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:10: warning: prefer 'std::numbers::inv_sqrt3' to this formula [modernize-use-std-numbers] + // CHECK-MESSAGES-ALL: :[[@LINE-2]]:14: warning: prefer 'std::numbers::sqrt3' to this formula [modernize-use-std-numbers] + // CHECK-FIXES-ALL: sink(std::numbers::inv_sqrt3); + + sink(INV_SQRT3); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:10: warning: prefer 'std::numbers::inv_sqrt3' to this macro [modernize-use-std-numbers] + // CHECK-FIXES-ALL: sink(std::numbers::inv_sqrt3); + + sink(NOT_INV_SQRT3); + + const auto inv_sqrt3f = .577350269F; + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:29: warning: prefer 'std::numbers::inv_sqrt3_v' to this literal, differs by '1.04e-08' [modernize-use-std-numbers] + // CHECK-FIXES-ALL: const auto inv_sqrt3f = std::numbers::inv_sqrt3_v; + + bar::sqrt(3); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:5: warning: prefer 'std::numbers::sqrt3' to this formula [modernize-use-std-numbers] + // CHECK-FIXES-ALL: std::numbers::sqrt3; + + auto somePhi = 1.6180339; + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:20: warning: prefer 'std::numbers::phi' to this literal, differs by '8.87e-08' [modernize-use-std-numbers] + // CHECK-FIXES-ALL: auto somePhi = std::numbers::phi; + + sink(Phi); + + sink((42 + bar::sqrt(5)) / 2); + + sink((1 + bar::sqrt(5)) / 2); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:10: warning: prefer 'std::numbers::phi' to this formula [modernize-use-std-numbers] + // CHECK-FIXES-ALL: sink(std::numbers::phi); + + sink((bar::sqrt(5.0F) + 1) / 2); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:10: warning: prefer 'std::numbers::phi_v' to this formula [modernize-use-std-numbers] + // CHECK-FIXES-ALL: sink(std::numbers::phi_v); +} + + + +template +void baz(){ + static constexpr T Pi = 3.1415926; + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:29: warning: prefer 'std::numbers::pi' to this literal, differs by '5.36e-08' [modernize-use-std-numbers] + // CHECK-FIXES-ALL: static constexpr T Pi = std::numbers::pi; + + static constexpr T Euler = 2.7182818; + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:32: warning: prefer 'std::numbers::e' to this literal, differs by '2.85e-08' [modernize-use-std-numbers] + // CHECK-FIXES-ALL: static constexpr T Euler = std::numbers::e; + + static constexpr T Phi = 1.6180339; + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:30: warning: prefer 'std::numbers::phi' to this literal, differs by '8.87e-08' [modernize-use-std-numbers] + // CHECK-FIXES-ALL: static constexpr T Phi = std::numbers::phi; + + static constexpr T PiCopy = Pi; + static constexpr T PiDefineFromMacro = MY_PI; + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:44: warning: prefer 'std::numbers::pi' to this macro, differs by '5.36e-08' [modernize-use-std-numbers] + // CHECK-FIXES-ALL: static constexpr T PiDefineFromMacro = std::numbers::pi; + + static constexpr T Pi2 = 3.14; + // CHECK-MESSAGES-IMPRECISE: :[[@LINE-1]]:30: warning: prefer 'std::numbers::pi' to this literal, differs by '1.59e-03' [modernize-use-std-numbers] + // CHECK-FIXES-IMPRECISE: static constexpr T Pi2 = std::numbers::pi; + static constexpr T Euler2 = 2.71; + // CHECK-MESSAGES-IMPRECISE: :[[@LINE-1]]:33: warning: prefer 'std::numbers::e' to this literal, differs by '8.28e-03' [modernize-use-std-numbers] + // CHECK-FIXES-IMPRECISE: static constexpr T Euler2 = std::numbers::e; + static constexpr T Phi2 = 1.61; + // CHECK-MESSAGES-IMPRECISE: :[[@LINE-1]]:31: warning: prefer 'std::numbers::phi' to this literal, differs by '8.03e-03' [modernize-use-std-numbers] + // CHECK-FIXES-IMPRECISE: static constexpr T Phi2 = std::numbers::phi; + + static constexpr T Pi3 = 3.1415926L; + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:30: warning: prefer 'std::numbers::pi_v' to this literal, differs by '5.36e-08' [modernize-use-std-numbers] + // CHECK-FIXES-ALL: static constexpr T Pi3 = std::numbers::pi_v; + + static constexpr T Euler3 = 2.7182818L; + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:33: warning: prefer 'std::numbers::e_v' to this literal, differs by '2.85e-08' [modernize-use-std-numbers] + // CHECK-FIXES-ALL: static constexpr T Euler3 = std::numbers::e_v; + + static constexpr T Phi3 = 1.6180339L; + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:31: warning: prefer 'std::numbers::phi_v' to this literal, differs by '8.87e-08' [modernize-use-std-numbers] + // CHECK-FIXES-ALL: static constexpr T Phi3 = std::numbers::phi_v; + + static constexpr my_float Actually2MyFloat = 2; + bar::sqrt(Actually2MyFloat); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:5: warning: prefer 'std::numbers::sqrt2_v' to this formula [modernize-use-std-numbers] + // CHECK-FIXES-ALL: std::numbers::sqrt2_v; + + constexpr static T One = 1; + constexpr static T Two = 2; + + bar::sqrt(2); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:5: warning: prefer 'std::numbers::sqrt2' to this formula [modernize-use-std-numbers] + // CHECK-FIXES-ALL: std::numbers::sqrt2; + + bar::sqrt(Two); + + bar::sqrt(2.0); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:5: warning: prefer 'std::numbers::sqrt2' to this formula [modernize-use-std-numbers] + // CHECK-FIXES-ALL: std::numbers::sqrt2; + + T Not2 = 2; + Not2 = 42; + bar::sqrt(Not2); + + const T Actually2 = 2; + bar::sqrt(Actually2); + + exp(1); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:5: warning: prefer 'std::numbers::e' to this formula [modernize-use-std-numbers] + // CHECK-FIXES-ALL: std::numbers::e; + + exp(One); + + exp(1.00000000000001); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:5: warning: prefer 'std::numbers::e' to this formula [modernize-use-std-numbers] + // CHECK-FIXES-ALL: std::numbers::e; + + log2(exp(1)); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:5: warning: prefer 'std::numbers::log2e' to this formula [modernize-use-std-numbers] + // CHECK-MESSAGES-ALL: :[[@LINE-2]]:10: warning: prefer 'std::numbers::e' to this formula [modernize-use-std-numbers] + // CHECK-FIXES-ALL: std::numbers::log2e; + + log2(Euler); + + log2(bar::e); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:5: warning: prefer 'std::numbers::log2e' to this formula [modernize-use-std-numbers] + // CHECK-FIXES-ALL: std::numbers::log2e; + + T log2e = 1.4426950; + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:15: warning: prefer 'std::numbers::log2e' to this literal, differs by '4.09e-08' [modernize-use-std-numbers] + // CHECK-FIXES-ALL: T log2e = std::numbers::log2e; + + log10(exp(1)); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:5: warning: prefer 'std::numbers::log10e' to this formula [modernize-use-std-numbers] + // CHECK-MESSAGES-ALL: :[[@LINE-2]]:11: warning: prefer 'std::numbers::e' to this formula [modernize-use-std-numbers] + // CHECK-FIXES-ALL: std::numbers::log10e; + + log10(Euler); + + log10(bar::e); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:5: warning: prefer 'std::numbers::log10e' to this formula [modernize-use-std-numbers] + // CHECK-FIXES-ALL: std::numbers::log10e; + + T log10e = .434294; + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:16: warning: prefer 'std::numbers::log10e' to this literal, differs by '4.82e-07' [modernize-use-std-numbers] + // CHECK-FIXES-ALL: T log10e = std::numbers::log10e; + + T egamma = 0.5772156 * 42; + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:16: warning: prefer 'std::numbers::egamma' to this literal, differs by '6.49e-08' [modernize-use-std-numbers] + // CHECK-FIXES-ALL: T egamma = std::numbers::egamma * 42; + + sink(1 / Pi); + + sink(1 / bar::sqrt(Pi)); + + sink(1 / bar::sqrt(MY_PI)); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:10: warning: prefer 'std::numbers::inv_sqrtpi' to this formula [modernize-use-std-numbers] + // CHECK-MESSAGES-ALL: :[[@LINE-2]]:24: warning: prefer 'std::numbers::pi' to this macro, differs by '5.36e-08' [modernize-use-std-numbers] + // CHECK-FIXES-ALL: sink(std::numbers::inv_sqrtpi); + + + log(2); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:5: warning: prefer 'std::numbers::ln2' to this formula [modernize-use-std-numbers] + // CHECK-FIXES-ALL: std::numbers::ln2; + + log(10); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:5: warning: prefer 'std::numbers::ln10' to this formula [modernize-use-std-numbers] + // CHECK-FIXES-ALL: std::numbers::ln10; + + bar::sqrt(2); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:5: warning: prefer 'std::numbers::sqrt2' to this formula [modernize-use-std-numbers] + // CHECK-FIXES-ALL: std::numbers::sqrt2; + + sink(1 / bar::sqrt(3)); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:10: warning: prefer 'std::numbers::inv_sqrt3' to this formula [modernize-use-std-numbers] + // CHECK-MESSAGES-ALL: :[[@LINE-2]]:14: warning: prefer 'std::numbers::sqrt3' to this formula [modernize-use-std-numbers] + // CHECK-FIXES-ALL: sink(std::numbers::inv_sqrt3); + + bar::sqrt(3); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:5: warning: prefer 'std::numbers::sqrt3' to this formula [modernize-use-std-numbers] + // CHECK-FIXES-ALL: std::numbers::sqrt3; + + T phi = 1.6180339; + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:13: warning: prefer 'std::numbers::phi' to this literal, differs by '8.87e-08' [modernize-use-std-numbers] + // CHECK-FIXES-ALL: T phi = std::numbers::phi; + + sink((42 + bar::sqrt(5)) / 2); + + sink((1 + bar::sqrt(5)) / 2); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:10: warning: prefer 'std::numbers::phi' to this formula [modernize-use-std-numbers] + // CHECK-FIXES-ALL: sink(std::numbers::phi); + + sink((bar::sqrt(5.0F) + 1) / 2); + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:10: warning: prefer 'std::numbers::phi_v' to this formula [modernize-use-std-numbers] + // CHECK-FIXES-ALL: sink(std::numbers::phi_v); +} + +template +void foobar(){ + const T Two = 2; + bar::sqrt(Two); +} +void use_templates() { + foobar(); + foobar(); + + baz(); + baz(); +} + +#define BIG_MARCO \ + struct InvSqrt3 { \ + template static T get() { return 1 / bar::sqrt(3); } \ + } + +BIG_MARCO; + +void use_BIG_MACRO() { +InvSqrt3 f{}; +f.get(); +f.get(); +} diff --git a/clang-tools-extra/test/clang-tidy/infrastructure/Inputs/compilation-database/template.json b/clang-tools-extra/test/clang-tidy/infrastructure/Inputs/compilation-database/template.json index 74275d953727cc53de44e03a216805c408209336..53ee3fa7a98da34cf8d77a358b8c0c8db56216ff 100644 --- a/clang-tools-extra/test/clang-tidy/infrastructure/Inputs/compilation-database/template.json +++ b/clang-tools-extra/test/clang-tidy/infrastructure/Inputs/compilation-database/template.json @@ -20,10 +20,15 @@ "file": "test_dir/b/c.cpp" }, { - "directory": "test_dir/b", - "command": "clang++ -I../include -o test.o ../b/d.cpp", + "directory": "test_dir/", + "command": "clang++ -o test.o ./b/d.cpp", "file": "test_dir/b/d.cpp" }, +{ + "directory": "test_dir/b", + "command": "clang++ -I../include -o test.o ../include.cpp", + "file": "test_dir/include.cpp" +}, { "directory": "test_dir/", "command": "clang++ -o test.o test_dir/b/not-exist.cpp", diff --git a/clang-tools-extra/test/clang-tidy/infrastructure/clang-tidy-run-with-database.cpp b/clang-tools-extra/test/clang-tidy/infrastructure/clang-tidy-run-with-database.cpp index f8c05a3f69e956ec5d71bac89b0f8d0222b68926..3c4e8494a4ae3b8e6ffa11297b37c7a553d12cb6 100644 --- a/clang-tools-extra/test/clang-tidy/infrastructure/clang-tidy-run-with-database.cpp +++ b/clang-tools-extra/test/clang-tidy/infrastructure/clang-tidy-run-with-database.cpp @@ -5,8 +5,9 @@ // RUN: echo 'int *AB = 0;' > %T/compilation-database-test/a/b.cpp // RUN: echo 'int *BB = 0;' > %T/compilation-database-test/b/b.cpp // RUN: echo 'int *BC = 0;' > %T/compilation-database-test/b/c.cpp +// RUN: echo 'int *BD = 0;' > %T/compilation-database-test/b/d.cpp // RUN: echo 'int *HP = 0;' > %T/compilation-database-test/include/header.h -// RUN: echo '#include "header.h"' > %T/compilation-database-test/b/d.cpp +// RUN: echo '#include "header.h"' > %T/compilation-database-test/include.cpp // RUN: sed 's|test_dir|%/T/compilation-database-test|g' %S/Inputs/compilation-database/template.json > %T/compile_commands.json // Regression test: shouldn't crash. @@ -15,15 +16,17 @@ // CHECK-NOT-EXIST: unable to handle compilation // CHECK-NOT-EXIST: Found compiler error -// RUN: clang-tidy --checks=-*,modernize-use-nullptr -p %T %T/compilation-database-test/a/a.cpp %T/compilation-database-test/a/b.cpp %T/compilation-database-test/b/b.cpp %T/compilation-database-test/b/c.cpp %T/compilation-database-test/b/d.cpp -header-filter=.* -fix +// RUN: clang-tidy --checks=-*,modernize-use-nullptr -p %T %T/compilation-database-test/a/a.cpp %T/compilation-database-test/a/b.cpp %T/compilation-database-test/b/b.cpp %T/compilation-database-test/b/c.cpp %T/compilation-database-test/b/d.cpp %T/compilation-database-test/include.cpp -header-filter=.* -fix // RUN: FileCheck -input-file=%T/compilation-database-test/a/a.cpp %s -check-prefix=CHECK-FIX1 // RUN: FileCheck -input-file=%T/compilation-database-test/a/b.cpp %s -check-prefix=CHECK-FIX2 // RUN: FileCheck -input-file=%T/compilation-database-test/b/b.cpp %s -check-prefix=CHECK-FIX3 // RUN: FileCheck -input-file=%T/compilation-database-test/b/c.cpp %s -check-prefix=CHECK-FIX4 -// RUN: FileCheck -input-file=%T/compilation-database-test/include/header.h %s -check-prefix=CHECK-FIX5 +// RUN: FileCheck -input-file=%T/compilation-database-test/b/d.cpp %s -check-prefix=CHECK-FIX5 +// RUN: FileCheck -input-file=%T/compilation-database-test/include/header.h %s -check-prefix=CHECK-FIX6 // CHECK-FIX1: int *AA = nullptr; // CHECK-FIX2: int *AB = nullptr; // CHECK-FIX3: int *BB = nullptr; // CHECK-FIX4: int *BC = nullptr; -// CHECK-FIX5: int *HP = nullptr; +// CHECK-FIX5: int *BD = nullptr; +// CHECK-FIX6: int *HP = nullptr; diff --git a/clang/CMakeLists.txt b/clang/CMakeLists.txt index 9b52c58be41e7f7489b66754a18a2e26e8316967..2ca6db02e58791d5f4ea9f6b8e57dccbb425da89 100644 --- a/clang/CMakeLists.txt +++ b/clang/CMakeLists.txt @@ -290,8 +290,10 @@ endif() if(NOT DEFINED CLANG_VERSION_PATCHLEVEL) set(CLANG_VERSION_PATCHLEVEL ${LLVM_VERSION_PATCH}) endif() -# Unlike PACKAGE_VERSION, CLANG_VERSION does not include LLVM_VERSION_SUFFIX. -set(CLANG_VERSION "${CLANG_VERSION_MAJOR}.${CLANG_VERSION_MINOR}.${CLANG_VERSION_PATCHLEVEL}") +if(NOT DEFINED CLANG_VERSION_SUFFIX) + set(CLANG_VERSION_SUFFIX ${LLVM_VERSION_SUFFIX}) +endif() +set(CLANG_VERSION "${CLANG_VERSION_MAJOR}.${CLANG_VERSION_MINOR}.${CLANG_VERSION_PATCHLEVEL}${CLANG_VERSION_SUFFIX}") message(STATUS "Clang version: ${CLANG_VERSION}") # Configure the Version.inc file. @@ -650,6 +652,7 @@ if (CLANG_ENABLE_BOOTSTRAP) CLANG_VERSION_MAJOR CLANG_VERSION_MINOR CLANG_VERSION_PATCHLEVEL + CLANG_VERSION_SUFFIX CLANG_VENDOR LLVM_VERSION_SUFFIX LLVM_BINUTILS_INCDIR diff --git a/clang/docs/InternalsManual.rst b/clang/docs/InternalsManual.rst index f8e3da5f9736829ab7f409a2f1372ba8222afd64..05fadf5a034464364191bcd09f8f82021ae71287 100644 --- a/clang/docs/InternalsManual.rst +++ b/clang/docs/InternalsManual.rst @@ -477,9 +477,8 @@ mode. Instead of formatting and printing out the diagnostics, this implementation just captures and remembers the diagnostics as they fly by. Then ``-verify`` compares the list of produced diagnostics to the list of expected ones. If they disagree, it prints out its own output. Full -documentation for the ``-verify`` mode can be found in the Clang API -documentation for `VerifyDiagnosticConsumer -`_. +documentation for the ``-verify`` mode can be found at +:ref:`verifying-diagnostics`. There are many other possible implementations of this interface, and this is why we prefer diagnostics to pass down rich structured information in @@ -3314,6 +3313,8 @@ Testing All functional changes to Clang should come with test coverage demonstrating the change in behavior. +.. _verifying-diagnostics: + Verifying Diagnostics ^^^^^^^^^^^^^^^^^^^^^ Clang ``-cc1`` supports the ``-verify`` command line option as a way to @@ -3375,7 +3376,7 @@ truncated text instead.) Here's an example of the most commonly used way to specify expected diagnostics: -.. code-block: c++ +.. code-block:: c++ int A = B; // expected-error {{use of undeclared identifier 'B'}} @@ -3385,7 +3386,7 @@ more readable, you can use slash-newline to separate out the diagnostics. Alternatively, it is possible to specify the line on which the diagnostic should appear by appending ``@`` to ``expected-``, for example: -.. code-block: c++ +.. code-block:: c++ #warning some text // expected-warning@10 {{some text}} @@ -3398,7 +3399,7 @@ header file, it may be beneficial to be able to declare the file in which the diagnostic will appear, rather than placing the ``expected-*`` directive in the actual file itself. This can be done using the following syntax: -.. code-block: c++ +.. code-block:: c++ // expected-error@path/include.h:15 {{error message}} @@ -3413,7 +3414,7 @@ diagnostic can instead be indicated by a marker of the form ``#``. Markers are specified by including them in a comment, and then referenced by appending the marker to the diagnostic with ``@#``, as with: -.. code-block: c++ +.. code-block:: c++ #warning some text // #1 // ... other code ... @@ -3428,14 +3429,14 @@ syntax is ``expected- {{diag text}}``, where ```` is one of integer. This allows the diagnostic to appear as many times as specified. For example: -.. code-block: c++ +.. code-block:: c++ void f(); // expected-note 2 {{previous declaration is here}} Where the diagnostic is expected to occur a minimum number of times, this can be specified by appending a ``+`` to the number. For example: -.. code-block: c++ +.. code-block:: c++ void f(); // expected-note 0+ {{previous declaration is here}} void g(); // expected-note 1+ {{previous declaration is here}} @@ -3445,13 +3446,13 @@ swallowed if it occurs, but will not generate an error if it does not occur. In the second example, the diagnostic must occur at least once. As a short-hand, "one or more" can be specified simply by ``+``. For example: -.. code-block: c++ +.. code-block:: c++ void g(); // expected-note + {{previous declaration is here}} A range can also be specified by ``-``. For example: -.. code-block: c++ +.. code-block:: c++ void f(); // expected-note 0-1 {{previous declaration is here}} @@ -3460,13 +3461,13 @@ In this example, the diagnostic may appear only once, if at all. Regex matching mode may be selected by appending ``-re`` to the diagnostic type and including regexes wrapped in double curly braces in the directive, such as: -.. code-block: c++ +.. code-block:: text expected-error-re {{format specifies type 'wchar_t **' (aka '{{.+}}')}} Examples matching error: "variable has incomplete type 'struct s'" -.. code-block: c++ +.. code-block:: c++ // expected-error {{variable has incomplete type 'struct s'}} // expected-error {{variable has incomplete type}} diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst index 8e01ef6cbb3997e9d24a9e89b2542bd573a1b0c1..13fb7c345aa4ebf3bd9be20ed2284bf40f9a02b6 100644 --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -1470,7 +1470,7 @@ Relaxed constexpr __cpp_constexpr C++14 ``if constexpr`` __cpp_if_constexpr C++17 C++11 fold expressions __cpp_fold_expressions C++17 C++03 Lambda capture of \*this by value __cpp_capture_star_this C++17 C++11 -Attributes on enums __cpp_enumerator_attributes C++17 C++11 +Attributes on enums __cpp_enumerator_attributes C++17 C++03 Guaranteed copy elision __cpp_guaranteed_copy_elision C++17 C++03 Hexadecimal floating literals __cpp_hex_float C++17 C++03 ``inline`` variables __cpp_inline_variables C++17 C++03 @@ -1483,6 +1483,7 @@ Conditional ``explicit`` __cpp_conditional_explicit C++20 ``using enum`` __cpp_using_enum C++20 C++03 ``if consteval`` __cpp_if_consteval C++23 C++20 ``static operator()`` __cpp_static_call_operator C++23 C++03 +Attributes on Lambda-Expressions C++23 C++11 -------------------------------------- -------------------------------- ------------- ------------- Designated initializers (N494) C99 C89 Array & element qualification (N2607) C23 C89 @@ -2821,7 +2822,7 @@ Example output: The ``__builtin_dump_struct`` function is used to print the fields of a simple structure and their values for debugging purposes. The first argument of the -builtin should be a pointer to the struct to dump. The second argument ``f`` +builtin should be a pointer to a complete record type to dump. The second argument ``f`` should be some callable expression, and can be a function object or an overload set. The builtin calls ``f``, passing any further arguments ``args...`` followed by a ``printf``-compatible format string and the corresponding @@ -3866,6 +3867,30 @@ builtin function, and are named with a ``__opencl_`` prefix. The macros and ``__OPENCL_MEMORY_SCOPE_SUB_GROUP`` are provided, with values corresponding to the enumerators of OpenCL's ``memory_scope`` enumeration.) +__scoped_atomic builtins +------------------------ + +Clang provides a set of atomics taking a memory scope argument. These atomics +are identical to the standard GNU / GCC atomic builtins but taking an extra +memory scope argument. These are designed to be a generic alternative to the +``__opencl_atomic_*`` builtin functions for targets that support atomic memory +scopes. + +Atomic memory scopes are designed to assist optimizations for systems with +several levels of memory hierarchy like GPUs. The following memory scopes are +currently supported: + +* ``__MEMORY_SCOPE_SYSTEM`` +* ``__MEMORY_SCOPE_DEVICE`` +* ``__MEMORY_SCOPE_WRKGRP`` +* ``__MEMORY_SCOPE_WVFRNT`` +* ``__MEMORY_SCOPE_SINGLE`` + +This controls whether or not the atomic operation is ordered with respect to the +whole system, the current device, an OpenCL workgroup, wavefront, or just a +single thread. If these are used on a target that does not support atomic +scopes, then they will behave exactly as the standard GNU atomic builtins. + Low-level ARM exclusive memory builtins --------------------------------------- diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 683d0026bb345bad69571744b947e628cc894824..066e4ac5b9e54b83965d0cbc64740f12a06aaa0f 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -156,6 +156,9 @@ C++23 Feature Support support for this feature is still experimental, the feature test macro ``__cpp_explicit_this_parameter`` was not set in this version. +- Added a separate warning to warn the use of attributes on lambdas as a C++23 extension + in previous language versions: ``-Wc++23-lambda-attributes``. + C++2c Feature Support ^^^^^^^^^^^^^^^^^^^^^ @@ -201,6 +204,9 @@ C Language Changes number of elements in the flexible array member. This information can improve the results of the array bound sanitizer and the ``__builtin_dynamic_object_size`` builtin. +- Enums will now be represented in TBAA metadata using their actual underlying + integer type. Previously they were treated as chars, which meant they could + alias with all other types. C23 Feature Support ^^^^^^^^^^^^^^^^^^^ @@ -232,6 +238,8 @@ Non-comprehensive list of changes in this release except that it returns the size of a type ignoring tail padding. * ``__builtin_classify_type()`` now classifies ``_BitInt`` values as the return value ``18`` and vector types as return value ``19``, to match GCC 14's behavior. +* The default value of `_MSC_VER` was raised from 1920 to 1933. +* Since MSVC 19.33 added undocumented attribute ``[[msvc::constexpr]]``, this release adds the attribute as well. * Added ``#pragma clang fp reciprocal``. @@ -256,6 +264,16 @@ New Compiler Flags * ``-fopenacc`` was added as a part of the effort to support OpenACC in clang. +* ``-fcx-limited-range`` enables the naive mathematical formulas for complex + division and multiplication with no NaN checking of results. The default is + ``-fno-cx-limited-range``, but this option is enabled by ``-ffast-math``. + +* ``-fcx-fortran-rules`` enables the naive mathematical formulas for complex + multiplication and enables application of Smith's algorithm for complex + division. See SMITH, R. L. Algorithm 116: Complex division. Commun. ACM 5, 8 + (1962). The default is ``-fno-cx-fortran-rules``. + + Deprecated Compiler Flags ------------------------- @@ -353,6 +371,8 @@ Improvements to Clang's diagnostics of a base class is not called in the constructor of its derived class. - Clang no longer emits ``-Wmissing-variable-declarations`` for variables declared with the ``register`` storage class. +- Clang's ``-Wswitch-default`` flag now diagnoses whenever a ``switch`` statement + does not have a ``default`` label. - Clang's ``-Wtautological-negation-compare`` flag now diagnoses logical tautologies like ``x && !x`` and ``!x || x`` in expressions. This also makes ``-Winfinite-recursion`` diagnose more cases. @@ -381,9 +401,6 @@ Improvements to Clang's diagnostics (`#54678: `_). - Clang now prints its 'note' diagnostic in cyan instead of black, to be more compatible with terminals with dark background colors. This is also more consistent with GCC. -- The fix-it emitted by ``-Wformat`` for scoped enumerations now take the - enumeration's underlying type into account instead of suggesting a type just - based on the format string specifier being used. - Clang now displays an improved diagnostic and a note when a defaulted special member is marked ``constexpr`` in a class with a virtual base class (`#64843: `_). @@ -503,6 +520,7 @@ Improvements to Clang's diagnostics 48 | static_assert(1 << 4 == 15); | ~~~~~~~^~~~~ +- Clang now diagnoses definitions of friend function specializations, e.g. ``friend void f<>(int) {}``. Improvements to Clang's time-trace ---------------------------------- @@ -651,8 +669,22 @@ Bug Fixes in This Version - Fixed false positive error emitted by clang when performing qualified name lookup and the current class instantiation has dependent bases. Fixes (`#13826 `_) +- Fix a ``clang-17`` regression where a templated friend with constraints is not + properly applied when its parameters reference an enclosing non-template class. + Fixes (`#71595 `_) +- Fix the name of the ifunc symbol emitted for multiversion functions declared with the + ``target_clones`` attribute. This addresses a linker error that would otherwise occur + when these functions are referenced from other TUs. +- Fixes compile error that double colon operator cannot resolve macro with parentheses. + Fixes (`#64467 `_) - Clang's ``-Wchar-subscripts`` no longer warns on chars whose values are known non-negative constants. Fixes (`#18763 `_) +- Fix crash due to incorrectly allowing conversion functions in copy elision. + Fixes (`#39319 `_) and + (`#60182 `_) and + (`#62157 `_) and + (`#64885 `_) and + (`#65568 `_) Bug Fixes to Compiler Builtins ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -794,6 +826,9 @@ Bug Fixes to C++ Support Fixes: (`#68769 `_) +- Clang now rejects incomplete types for ``__builtin_dump_struct``. Fixes: + (`#63506 `_) + - Fixed a crash for C++98/03 while checking an ill-formed ``_Static_assert`` expression. Fixes: (`#72025 `_) @@ -835,6 +870,10 @@ Miscellaneous Clang Crashes Fixed `Issue 41302 `_ - Fixed a crash when ``-ast-dump=json`` was used for code using class template deduction guides. +- Fixed a crash when a lambda marked as ``static`` referenced a captured + variable in an expression. + `Issue 74608 `_ + OpenACC Specific Changes ------------------------ @@ -878,11 +917,17 @@ Arm and AArch64 Support - New AArch64 asm constraints have been added for r8-r11(Uci) and r12-r15(Ucj). - Support has been added for the following processors (-mcpu identifiers in parenthesis): +- Support has been added for the following processors (-mcpu identifiers in parenthesis): - * Arm Cortex-A520 (cortex-a520). - * Arm Cortex-A720 (cortex-a720). - * Arm Cortex-X4 (cortex-x4). + For Arm: + + * Cortex-M52 (cortex-m52). + + For AArch64: + + * Cortex-A520 (cortex-a520). + * Cortex-A720 (cortex-a720). + * Cortex-X4 (cortex-x4). Android Support ^^^^^^^^^^^^^^^ @@ -929,6 +974,9 @@ CUDA/HIP Language Changes CUDA Support ^^^^^^^^^^^^ +- Clang now supports CUDA SDK up to 12.3 +- Added support for sm_90a + AIX Support ^^^^^^^^^^^ @@ -968,6 +1016,9 @@ Floating Point Support in Clang ``__builtin_exp10f128`` builtins. - Add ``__builtin_iszero``, ``__builtin_issignaling`` and ``__builtin_issubnormal``. +- Add support for C99's ``#pragma STDC CX_LIMITED_RANGE`` feature. This + enables the naive mathematical formulas for complex multiplication and + division, which are faster but do not correctly handle overflow and infinities. AST Matchers ------------ @@ -1022,6 +1073,9 @@ Static Analyzer `#65888 `_, and `#65887 `_ +- Move checker ``alpha.cplusplus.EnumCastOutOfRange`` out of the ``alpha`` + package to ``optin.core.EnumCastOutOfRange``. + .. _release-notes-sanitizers: Sanitizers diff --git a/clang/docs/SanitizerSpecialCaseList.rst b/clang/docs/SanitizerSpecialCaseList.rst index ab39276b0439577b0c5568a07f4190aeb5324099..c7fb0fa3f8a8286777669eee56d3155deab70e67 100644 --- a/clang/docs/SanitizerSpecialCaseList.rst +++ b/clang/docs/SanitizerSpecialCaseList.rst @@ -56,13 +56,18 @@ and lines starting with "#" are ignored. .. note:: - In `D154014 `_ we transitioned to using globs instead - of regexes to match patterns in special case lists. Since this was a - breaking change, we will temporarily support the original behavior using - regexes. If ``#!special-case-list-v2`` is the first line of the file, then - we will use the new behavior using globs. For more details, see - `this discourse post `_. + Prior to Clang 18, section names and entries described below use a variant of + regex where ``*`` is translated to ``.*``. Clang 18 (`D154014 + `) switches to glob and plans to remove + regex support in Clang 19. + For Clang 18, regex is supported if ``#!special-case-list-v1`` is the first + line of the file. + + Many special case lists use ``.`` to indicate the literal character and do + not use regex metacharacters such as ``(``, ``)``. They are unaffected by the + regex to glob transition. For more details, see `this discourse post + `_. Section names are globs written in square brackets that denote which sanitizer the following entries apply to. For example, ``[address]`` @@ -80,7 +85,6 @@ tool-specific docs. .. code-block:: bash - #!special-case-list-v2 # The line above is explained in the note above # Lines starting with # are ignored. # Turn off checks for the source file diff --git a/clang/docs/UsersManual.rst b/clang/docs/UsersManual.rst index 9d64195ee338e2c4657a2db5c43db2b6e6b2c4d2..7c30570437e8b01cd904898f5b57a582e9f4cea1 100644 --- a/clang/docs/UsersManual.rst +++ b/clang/docs/UsersManual.rst @@ -1468,6 +1468,7 @@ floating point semantic models: precise (the default), strict, and fast. With the exception of ``-ffp-contract=fast``, using any of the options below to disable any of the individual optimizations in ``-ffast-math`` will cause ``__FAST_MATH__`` to no longer be set. + ``-ffast-math`` enables ``-fcx-limited-range``. This option implies: @@ -1834,6 +1835,20 @@ floating point semantic models: precise (the default), strict, and fast. * ``16`` - Forces ``_Float16`` operations to be emitted without using excess precision arithmetic. +.. option:: -fcx-limited-range: + + This option enables the naive mathematical formulas for complex division and + multiplication with no NaN checking of results. The default is + ``-fno-cx-limited-range``, but this option is enabled by the ``-ffast-math`` + option. + +.. option:: -fcx-fortran-rules: + + This option enables the naive mathematical formulas for complex + multiplication and enables application of Smith's algorithm for complex + division. See SMITH, R. L. Algorithm 116: Complex division. Commun. + ACM 5, 8 (1962). The default is ``-fno-cx-fortran-rules``. + .. _floating-point-environment: Accessing the floating point environment @@ -3359,8 +3374,8 @@ default for Windows targets. For compatibility with existing code that compiles with MSVC, clang defines the ``_MSC_VER`` and ``_MSC_FULL_VER`` macros. When on Windows, these default to -either the same value as the currently installed version of cl.exe, or ``1920`` -and ``192000000`` (respectively). The ``-fms-compatibility-version=`` flag +either the same value as the currently installed version of cl.exe, or ``1933`` +and ``193300000`` (respectively). The ``-fms-compatibility-version=`` flag overrides these values. It accepts a dotted version tuple, such as 19.00.23506. Changing the MSVC compatibility version makes clang behave more like that version of MSVC. For example, ``-fms-compatibility-version=19`` will enable diff --git a/clang/docs/analyzer/checkers.rst b/clang/docs/analyzer/checkers.rst index f7b48e64e324f002891e5ab920d0549411f40abe..81d40395067c9aeeac28b382b79042820aaa9a0b 100644 --- a/clang/docs/analyzer/checkers.rst +++ b/clang/docs/analyzer/checkers.rst @@ -535,6 +535,52 @@ optin Checkers for portability, performance or coding style specific rules. +.. _optin-core-EnumCastOutOfRange: + +optin.core.EnumCastOutOfRange (C, C++) +"""""""""""""""""""""""""""""""""""""" +Check for integer to enumeration casts that would produce a value with no +corresponding enumerator. This is not necessarily undefined behavior, but can +lead to nasty surprises, so projects may decide to use a coding standard that +disallows these "unusual" conversions. + +Note that no warnings are produced when the enum type (e.g. `std::byte`) has no +enumerators at all. + +.. code-block:: cpp + + enum WidgetKind { A=1, B, C, X=99 }; + + void foo() { + WidgetKind c = static_cast(3); // OK + WidgetKind x = static_cast(99); // OK + WidgetKind d = static_cast(4); // warn + } + +**Limitations** + +This checker does not accept the coding pattern where an enum type is used to +store combinations of flag values: + +.. code-block:: cpp + + enum AnimalFlags + { + HasClaws = 1, + CanFly = 2, + EatsFish = 4, + Endangered = 8 + }; + + AnimalFlags operator|(AnimalFlags a, AnimalFlags b) + { + return static_cast(static_cast(a) | static_cast(b)); + } + + auto flags = HasClaws | CanFly; + +Projects that use this pattern should not enable this optin checker. + .. _optin-cplusplus-UninitializedObject: optin.cplusplus.UninitializedObject (C++) @@ -2113,23 +2159,6 @@ Reports destructions of polymorphic objects with a non-virtual destructor in the // destructor } -.. _alpha-cplusplus-EnumCastOutOfRange: - -alpha.cplusplus.EnumCastOutOfRange (C++) -"""""""""""""""""""""""""""""""""""""""" -Check for integer to enumeration casts that could result in undefined values. - -.. code-block:: cpp - - enum TestEnum { - A = 0 - }; - - void foo() { - TestEnum t = static_cast(-1); - // warn: the value provided to the cast expression is not in - // the valid range of values for the enum - .. _alpha-cplusplus-InvalidatedIterator: alpha.cplusplus.InvalidatedIterator (C++) diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index a9c4c67a60e8e8e607eb9308075cf298c47afd34..a41f2d66b37b69dcdfdf8206ba34ee4ff5528379 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -6498,7 +6498,7 @@ public: return cast(SubExprs[ORDER_FAIL]); } Expr *getVal2() const { - if (Op == AO__atomic_exchange) + if (Op == AO__atomic_exchange || Op == AO__scoped_atomic_exchange) return cast(SubExprs[ORDER_FAIL]); assert(NumSubExprs > VAL2); return cast(SubExprs[VAL2]); @@ -6539,7 +6539,9 @@ public: getOp() == AO__opencl_atomic_compare_exchange_weak || getOp() == AO__hip_atomic_compare_exchange_weak || getOp() == AO__atomic_compare_exchange || - getOp() == AO__atomic_compare_exchange_n; + getOp() == AO__atomic_compare_exchange_n || + getOp() == AO__scoped_atomic_compare_exchange || + getOp() == AO__scoped_atomic_compare_exchange_n; } bool isOpenCL() const { @@ -6569,13 +6571,13 @@ public: /// \return empty atomic scope model if the atomic op code does not have /// scope operand. static std::unique_ptr getScopeModel(AtomicOp Op) { - auto Kind = - (Op >= AO__opencl_atomic_load && Op <= AO__opencl_atomic_fetch_max) - ? AtomicScopeModelKind::OpenCL - : (Op >= AO__hip_atomic_load && Op <= AO__hip_atomic_fetch_max) - ? AtomicScopeModelKind::HIP - : AtomicScopeModelKind::None; - return AtomicScopeModel::create(Kind); + if (Op >= AO__opencl_atomic_load && Op <= AO__opencl_atomic_fetch_max) + return AtomicScopeModel::create(AtomicScopeModelKind::OpenCL); + else if (Op >= AO__hip_atomic_load && Op <= AO__hip_atomic_fetch_max) + return AtomicScopeModel::create(AtomicScopeModelKind::HIP); + else if (Op >= AO__scoped_atomic_load && Op <= AO__scoped_atomic_fetch_max) + return AtomicScopeModel::create(AtomicScopeModelKind::Generic); + return AtomicScopeModel::create(AtomicScopeModelKind::None); } /// Get atomic scope model. diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index 6c147eb8f64062334c969b7c0006a058676184fd..b3ae66e6e769d08cad0f7e8ada1384921132b00d 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -36,6 +36,7 @@ #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/PointerUnion.h" +#include "llvm/ADT/STLForwardCompat.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" #include "llvm/ADT/iterator_range.h" @@ -2384,8 +2385,6 @@ public: bool isRVVType(unsigned ElementCount) const; - bool isRVVType() const; - bool isRVVType(unsigned Bitwidth, bool IsFloat, bool IsBFloat = false) const; /// Return the implicit lifetime for this type, which must not be dependent. @@ -7284,14 +7283,6 @@ inline bool Type::isOpenCLSpecificType() const { isQueueT() || isReserveIDT() || isPipeType() || isOCLExtOpaqueType(); } -inline bool Type::isRVVType() const { -#define RVV_TYPE(Name, Id, SingletonId) \ - isSpecificBuiltinType(BuiltinType::Id) || - return -#include "clang/Basic/RISCVVTypes.def" - false; // end of boolean or operation. -} - inline bool Type::isRVVType(unsigned ElementCount) const { bool Ret = false; #define RVV_VECTOR_TYPE(Name, Id, SingletonId, NumEls, ElBits, NF, IsSigned, \ @@ -7524,7 +7515,7 @@ inline const Type *Type::getPointeeOrArrayElementType() const { /// spaces into a diagnostic with <<. inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &PD, LangAS AS) { - PD.AddTaggedVal(static_cast>(AS), + PD.AddTaggedVal(llvm::to_underlying(AS), DiagnosticsEngine::ArgumentKind::ak_addrspace); return PD; } diff --git a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def index ff687a0d178bdea28726a7b0113de267d1cfd9ec..757ee452ced74880adc332e4bfbfdb3e49a3b84e 100644 --- a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def +++ b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def @@ -36,6 +36,7 @@ FIXABLE_GADGET(PointerDereference) FIXABLE_GADGET(UPCAddressofArraySubscript) // '&DRE[any]' in an Unspecified Pointer Context FIXABLE_GADGET(UPCStandalonePointer) FIXABLE_GADGET(UPCPreIncrement) // '++Ptr' in an Unspecified Pointer Context +FIXABLE_GADGET(UUCAddAssign) // 'Ptr += n' in an Unspecified Untyped Context FIXABLE_GADGET(PointerAssignment) FIXABLE_GADGET(PointerInit) diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 1800f584c7e1088ac1b0f354f587ad2338dd6042..0d94ea2851c9ab6bc8e2a8057b517ebc7f9e7af8 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -2024,6 +2024,14 @@ def BPFPreserveAccessIndex : InheritableAttr, let LangOpts = [COnly]; } +def BPFPreserveStaticOffset : InheritableAttr, + TargetSpecificAttr { + let Spellings = [Clang<"preserve_static_offset">]; + let Subjects = SubjectList<[Record], ErrorDiag>; + let Documentation = [BPFPreserveStaticOffsetDocs]; + let LangOpts = [COnly]; +} + def BTFDeclTag : InheritableAttr { let Spellings = [Clang<"btf_decl_tag">]; let Args = [StringArgument<"BTFDeclTag">]; @@ -3638,6 +3646,14 @@ def : MutualExclusions<[Owner, Pointer]>; // Microsoft-related attributes +def MSConstexpr : InheritableAttr { + let LangOpts = [MicrosoftExt]; + let Spellings = [CXX11<"msvc", "constexpr">]; + let Subjects = SubjectList<[Function, ReturnStmt], ErrorDiag, + "functions and return statements">; + let Documentation = [MSConstexprDocs]; +} + def MSNoVTable : InheritableAttr, TargetSpecificAttr { let Spellings = [Declspec<"novtable">]; let Subjects = SubjectList<[CXXRecord]>; @@ -4242,7 +4258,8 @@ def HLSLResource : InheritableAttr { "StructuredBuffer", "CBuffer", "Sampler", "TBuffer", "RTAccelerationStructure", "FeedbackTexture2D", "FeedbackTexture2DArray"], - /*opt=*/0, /*fake=*/0, /*isExternalType=*/1> + /*opt=*/0, /*fake=*/0, /*isExternalType=*/1>, + DefaultBoolArgument<"isROV", /*default=*/0> ]; let Documentation = [InternalOnly]; } diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index b45ec6bbb8d37ef1285ed8d86b4d4143a33cc7dd..1a98196834cefc31a73523b79a82035c408db535 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -2199,6 +2199,43 @@ preserving struct or union member access debuginfo indices of this struct or union, similar to clang ``__builtin_preserve_access_index()``. }]; } + +def BPFPreserveStaticOffsetDocs : Documentation { + let Category = DocCatFunction; + let Content = [{ +Clang supports the ``__attribute__((preserve_static_offset))`` +attribute for the BPF target. This attribute may be attached to a +struct or union declaration. Reading or writing fields of types having +such annotation is guaranteed to generate LDX/ST/STX instruction with +offset corresponding to the field. + +For example: + +.. code-block:: c + + struct foo { + int a; + int b; + }; + + struct bar { + int a; + struct foo b; + } __attribute__((preserve_static_offset)); + + void buz(struct bar *g) { + g->b.a = 42; + } + +The assignment to ``g``'s field would produce an ST instruction with +offset 8: ``*(u32)(r1 + 8) = 42;``. + +Without this attribute generated instructions might be different, +depending on optimizations behavior. E.g. the example above could be +rewritten as ``r1 += 8; *(u32)(r1 + 0) = 42;``. + }]; +} + def BTFDeclTagDocs : Documentation { let Category = DocCatFunction; let Content = [{ @@ -2515,6 +2552,13 @@ example, the following will emit 4 versions of the function: __attribute__((target_clones("arch=atom,avx2","arch=ivybridge","default"))) void foo() {} +For targets that support the GNU indirect function (IFUNC) feature, dispatch +is performed by emitting an indirect function that is resolved to the appropriate +target clone at load time. The indirect function is given the name the +multiversioned function would have if it had been declared without the attribute. +For backward compatibility with earlier Clang releases, a function alias with an +``.ifunc`` suffix is also emitted. The ``.ifunc`` suffixed symbol is a deprecated +feature and support for it may be removed in the future. }]; } @@ -2615,8 +2659,9 @@ An error will be given if: - Specified values violate subtarget specifications; - Specified values are not compatible with values provided through other attributes; - - The AMDGPU target backend is unable to create machine code that can meet the - request. + +The AMDGPU target backend will emit a warning whenever it is unable to +create machine code that meets the request. }]; } @@ -3612,6 +3657,21 @@ an error: }]; } +def MSConstexprDocs : Documentation { + let Category = DocCatStmt; + let Content = [{ +The ``[[msvc::constexpr]]`` attribute can be applied only to a function +definition or a ``return`` statement. It does not impact function declarations. +A ``[[msvc::constexpr]]`` function cannot be ``constexpr`` or ``consteval``. +A ``[[msvc::constexpr]]`` function is treated as if it were a ``constexpr`` function +when it is evaluated in a constant context of ``[[msvc::constexpr]] return`` statement. +Otherwise, it is treated as a regular function. + +Semantics of this attribute are enabled only under MSVC compatibility +(``-fms-compatibility-version``) 19.33 and later. + }]; +} + def MSNoVTableDocs : Documentation { let Category = DocCatDecl; let Content = [{ diff --git a/clang/include/clang/Basic/Builtins.def b/clang/include/clang/Basic/Builtins.def index ec39e926889b936c47c89ca21614d0a5d2cf7e99..4dcbaf8a7beaa6598f91cba2d040b36699349364 100644 --- a/clang/include/clang/Basic/Builtins.def +++ b/clang/include/clang/Basic/Builtins.def @@ -904,6 +904,32 @@ BUILTIN(__atomic_signal_fence, "vi", "n") BUILTIN(__atomic_always_lock_free, "bzvCD*", "nE") BUILTIN(__atomic_is_lock_free, "bzvCD*", "nE") +// GNU atomic builtins with atomic scopes. +ATOMIC_BUILTIN(__scoped_atomic_load, "v.", "t") +ATOMIC_BUILTIN(__scoped_atomic_load_n, "v.", "t") +ATOMIC_BUILTIN(__scoped_atomic_store, "v.", "t") +ATOMIC_BUILTIN(__scoped_atomic_store_n, "v.", "t") +ATOMIC_BUILTIN(__scoped_atomic_exchange, "v.", "t") +ATOMIC_BUILTIN(__scoped_atomic_exchange_n, "v.", "t") +ATOMIC_BUILTIN(__scoped_atomic_compare_exchange, "v.", "t") +ATOMIC_BUILTIN(__scoped_atomic_compare_exchange_n, "v.", "t") +ATOMIC_BUILTIN(__scoped_atomic_fetch_add, "v.", "t") +ATOMIC_BUILTIN(__scoped_atomic_fetch_sub, "v.", "t") +ATOMIC_BUILTIN(__scoped_atomic_fetch_and, "v.", "t") +ATOMIC_BUILTIN(__scoped_atomic_fetch_or, "v.", "t") +ATOMIC_BUILTIN(__scoped_atomic_fetch_xor, "v.", "t") +ATOMIC_BUILTIN(__scoped_atomic_fetch_nand, "v.", "t") +ATOMIC_BUILTIN(__scoped_atomic_add_fetch, "v.", "t") +ATOMIC_BUILTIN(__scoped_atomic_sub_fetch, "v.", "t") +ATOMIC_BUILTIN(__scoped_atomic_and_fetch, "v.", "t") +ATOMIC_BUILTIN(__scoped_atomic_or_fetch, "v.", "t") +ATOMIC_BUILTIN(__scoped_atomic_xor_fetch, "v.", "t") +ATOMIC_BUILTIN(__scoped_atomic_max_fetch, "v.", "t") +ATOMIC_BUILTIN(__scoped_atomic_min_fetch, "v.", "t") +ATOMIC_BUILTIN(__scoped_atomic_nand_fetch, "v.", "t") +ATOMIC_BUILTIN(__scoped_atomic_fetch_min, "v.", "t") +ATOMIC_BUILTIN(__scoped_atomic_fetch_max, "v.", "t") + // OpenCL 2.0 atomic builtins. ATOMIC_BUILTIN(__opencl_atomic_init, "v.", "t") ATOMIC_BUILTIN(__opencl_atomic_load, "v.", "t") diff --git a/clang/include/clang/Basic/BuiltinsNVPTX.def b/clang/include/clang/Basic/BuiltinsNVPTX.def index d74a7d1e55dd28176c55b83b8364bf2dd537ca87..0f2e8260143be78341acd1e3527734709b7caf1e 100644 --- a/clang/include/clang/Basic/BuiltinsNVPTX.def +++ b/clang/include/clang/Basic/BuiltinsNVPTX.def @@ -26,7 +26,9 @@ #pragma push_macro("SM_87") #pragma push_macro("SM_89") #pragma push_macro("SM_90") -#define SM_90 "sm_90" +#pragma push_macro("SM_90a") +#define SM_90a "sm_90a" +#define SM_90 "sm_90|" SM_90a #define SM_89 "sm_89|" SM_90 #define SM_87 "sm_87|" SM_89 #define SM_86 "sm_86|" SM_87 @@ -56,7 +58,11 @@ #pragma push_macro("PTX78") #pragma push_macro("PTX80") #pragma push_macro("PTX81") -#define PTX81 "ptx81" +#pragma push_macro("PTX82") +#pragma push_macro("PTX83") +#define PTX83 "ptx83" +#define PTX82 "ptx82|" PTX83 +#define PTX81 "ptx81|" PTX82 #define PTX80 "ptx80|" PTX81 #define PTX78 "ptx78|" PTX80 #define PTX77 "ptx77|" PTX78 @@ -1055,6 +1061,7 @@ TARGET_BUILTIN(__nvvm_getctarank_shared_cluster, "iv*3", "", AND(SM_90,PTX78)) #pragma pop_macro("SM_87") #pragma pop_macro("SM_89") #pragma pop_macro("SM_90") +#pragma pop_macro("SM_90a") #pragma pop_macro("PTX42") #pragma pop_macro("PTX60") #pragma pop_macro("PTX61") @@ -1072,3 +1079,5 @@ TARGET_BUILTIN(__nvvm_getctarank_shared_cluster, "iv*3", "", AND(SM_90,PTX78)) #pragma pop_macro("PTX78") #pragma pop_macro("PTX80") #pragma pop_macro("PTX81") +#pragma pop_macro("PTX82") +#pragma pop_macro("PTX83") diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def index 675645cd534ed76358500294191fe97b0e3d2fb2..0acb5ae134ea245ed60fe91dbe18ff727fc13e71 100644 --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -28,12 +28,8 @@ CODEGENOPT(Name, Bits, Default) #endif CODEGENOPT(DisableIntegratedAS, 1, 0) ///< -no-integrated-as -ENUM_CODEGENOPT(CompressDebugSections, llvm::DebugCompressionType, 2, - llvm::DebugCompressionType::None) CODEGENOPT(RelaxELFRelocations, 1, 1) ///< -Wa,-mrelax-relocations={yes,no} CODEGENOPT(AsmVerbose , 1, 0) ///< -dA, -fverbose-asm. -CODEGENOPT(Dwarf64 , 1, 0) ///< -gdwarf64. -CODEGENOPT(Dwarf32 , 1, 1) ///< -gdwarf32. CODEGENOPT(PreserveAsmComments, 1, 1) ///< -dA, -fno-preserve-as-comments. CODEGENOPT(AssumeSaneOperatorNew , 1, 1) ///< implicit __attribute__((malloc)) operator new CODEGENOPT(AssumeUniqueVTables , 1, 1) ///< Assume a class has only one vtable. @@ -73,10 +69,6 @@ CODEGENOPT(DebugPassManager, 1, 0) ///< Prints debug information for the new CODEGENOPT(DisableRedZone , 1, 0) ///< Set when -mno-red-zone is enabled. CODEGENOPT(EmitCallSiteInfo, 1, 0) ///< Emit call site info only in the case of ///< '-g' + 'O>0' level. -CODEGENOPT(EnableDIPreservationVerify, 1, 0) ///< Enable di preservation verify - ///< each (it means check - ///< the original debug info - ///< metadata preservation). CODEGENOPT(IndirectTlsSegRefs, 1, 0) ///< Set when -mno-tls-direct-seg-refs ///< is specified. CODEGENOPT(DisableTailCalls , 1, 0) ///< Do not emit tail calls. @@ -113,16 +105,10 @@ CODEGENOPT(IndirectBranchCSPrefix, 1, 0) ///< if -mindirect-branch-cs-prefix CODEGENOPT(XRayInstrumentFunctions , 1, 0) ///< Set when -fxray-instrument is ///< enabled. CODEGENOPT(StackSizeSection , 1, 0) ///< Set when -fstack-size-section is enabled. -CODEGENOPT(ForceDwarfFrameSection , 1, 0) ///< Set when -fforce-dwarf-frame is - ///< enabled. ///< Set when -femit-compact-unwind-non-canonical is enabled. CODEGENOPT(EmitCompactUnwindNonCanonical, 1, 0) -///< Set when -femit-dwarf-unwind is passed. -ENUM_CODEGENOPT(EmitDwarfUnwind, llvm::EmitDwarfUnwindType, 2, - llvm::EmitDwarfUnwindType::Default) - ///< Set when -fxray-always-emit-customevents is enabled. CODEGENOPT(XRayAlwaysEmitCustomEvents , 1, 0) @@ -178,8 +164,6 @@ CODEGENOPT(IncrementalLinkerCompatible, 1, 0) ///< Emit an object file which can CODEGENOPT(MergeAllConstants , 1, 1) ///< Merge identical constants. CODEGENOPT(MergeFunctions , 1, 0) ///< Set when -fmerge-functions is enabled. CODEGENOPT(NoCommon , 1, 0) ///< Set when -fno-common or C++ is enabled. -CODEGENOPT(NoDwarfDirectoryAsm , 1, 0) ///< Set when -fno-dwarf-directory-asm is - ///< enabled. CODEGENOPT(NoExecStack , 1, 0) ///< Set when -Wa,--noexecstack is enabled. CODEGENOPT(FatalWarnings , 1, 0) ///< Set when -Wa,--fatal-warnings is ///< enabled. @@ -187,8 +171,6 @@ CODEGENOPT(NoWarn , 1, 0) ///< Set when -Wa,--no-warn is enabled. CODEGENOPT(NoTypeCheck , 1, 0) ///< Set when -Wa,--no-type-check is enabled. CODEGENOPT(MisExpect , 1, 0) ///< Set when -Wmisexpect is enabled CODEGENOPT(EnableSegmentedStacks , 1, 0) ///< Set when -fsplit-stack is enabled. -CODEGENOPT(NoInlineLineTables, 1, 0) ///< Whether debug info should contain - ///< inline line tables. CODEGENOPT(StackClashProtector, 1, 0) ///< Set when -fstack-clash-protection is enabled. CODEGENOPT(NoImplicitFloat , 1, 0) ///< Set when -mno-implicit-float is enabled. CODEGENOPT(NullPointerIsValid , 1, 0) ///< Assume Null pointer deference is defined. @@ -341,37 +323,6 @@ VALUE_CODEGENOPT(StackProbeSize , 32, 4096) ///< Overrides default stack ///< probe size, even if 0. VALUE_CODEGENOPT(WarnStackSize , 32, UINT_MAX) ///< Set via -fwarn-stack-size. CODEGENOPT(NoStackArgProbe, 1, 0) ///< Set when -mno-stack-arg-probe is used -CODEGENOPT(DebugStrictDwarf, 1, 1) ///< Whether or not to use strict DWARF info. - -/// Control the Assignment Tracking debug info feature. -ENUM_CODEGENOPT(AssignmentTrackingMode, AssignmentTrackingOpts, 2, AssignmentTrackingOpts::Disabled) - -CODEGENOPT(DebugColumnInfo, 1, 0) ///< Whether or not to use column information - ///< in debug info. - -CODEGENOPT(DebugTypeExtRefs, 1, 0) ///< Whether or not debug info should contain - ///< external references to a PCH or module. - -CODEGENOPT(DebugExplicitImport, 1, 0) ///< Whether or not debug info should - ///< contain explicit imports for - ///< anonymous namespaces - -/// Set debug info source file hashing algorithm. -ENUM_CODEGENOPT(DebugSrcHash, DebugSrcHashKind, 2, DSH_MD5) - -CODEGENOPT(SplitDwarfInlining, 1, 1) ///< Whether to include inlining info in the - ///< skeleton CU to allow for symbolication - ///< of inline stack frames without .dwo files. -CODEGENOPT(DebugFwdTemplateParams, 1, 0) ///< Whether to emit complete - ///< template parameter descriptions in - ///< forward declarations (versus just - ///< including them in the name). -ENUM_CODEGENOPT(DebugSimpleTemplateNames, llvm::codegenoptions::DebugTemplateNamesKind, 2, llvm::codegenoptions::DebugTemplateNamesKind::Full) ///< Whether to emit template parameters - ///< in the textual names of template - ///< specializations. - ///< Implies DebugFwdTemplateNames to - ///< allow decorated names to be - ///< reconstructed when needed. CODEGENOPT(EmitLLVMUseLists, 1, 0) ///< Control whether to serialize use-lists. CODEGENOPT(WholeProgramVTables, 1, 0) ///< Whether to apply whole-program @@ -395,30 +346,6 @@ VALUE_CODEGENOPT(SmallDataLimit, 32, 0) /// The lower bound for a buffer to be considered for stack protection. VALUE_CODEGENOPT(SSPBufferSize, 32, 0) -/// The kind of generated debug info. -ENUM_CODEGENOPT(DebugInfo, llvm::codegenoptions::DebugInfoKind, 4, llvm::codegenoptions::NoDebugInfo) - -/// Whether to generate macro debug info. -CODEGENOPT(MacroDebugInfo, 1, 0) - -/// Tune the debug info for this debugger. -ENUM_CODEGENOPT(DebuggerTuning, llvm::DebuggerKind, 3, - llvm::DebuggerKind::Default) - -/// Dwarf version. Version zero indicates to LLVM that no DWARF should be -/// emitted. -VALUE_CODEGENOPT(DwarfVersion, 3, 0) - -/// Whether we should emit CodeView debug information. It's possible to emit -/// CodeView and DWARF into the same object. -CODEGENOPT(EmitCodeView, 1, 0) - -/// Whether to emit the .debug$H section containing hashes of CodeView types. -CODEGENOPT(CodeViewGHash, 1, 0) - -/// Whether to emit the compiler path and command line into the CodeView debug information. -CODEGENOPT(CodeViewCommandLine, 1, 0) - /// The kind of inlining to perform. ENUM_CODEGENOPT(Inlining, InliningMethod, 2, NormalInlining) @@ -451,26 +378,14 @@ CODEGENOPT(DirectAccessExternalData, 1, 0) /// paths that reach the end of a function without executing a required return. CODEGENOPT(StrictReturn, 1, 1) -/// Whether emit extra debug info for sample pgo profile collection. -CODEGENOPT(DebugInfoForProfiling, 1, 0) - /// Whether emit pseudo probes for sample pgo profile collection. CODEGENOPT(PseudoProbeForProfiling, 1, 0) /// Whether 3-component vector type is preserved. CODEGENOPT(PreserveVec3Type, 1, 0) -/// Whether to emit .debug_gnu_pubnames section instead of .debug_pubnames. -CODEGENOPT(DebugNameTable, 2, 0) - -/// Whether to use DWARF base address specifiers in .debug_ranges. -CODEGENOPT(DebugRangesBaseAddress, 1, 0) - CODEGENOPT(NoPLT, 1, 0) -/// Whether to embed source in DWARF debug line section. -CODEGENOPT(EmbedSource, 1, 0) - /// Whether to emit all vtables CODEGENOPT(ForceEmitVTables, 1, 0) @@ -515,6 +430,9 @@ ENUM_CODEGENOPT(ZeroCallUsedRegs, llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind, /// non-deleting destructors. (No effect on Microsoft ABI.) CODEGENOPT(CtorDtorReturnThis, 1, 0) +/// FIXME: Make DebugOptions its own top-level .def file. +#include "DebugOptions.def" + #undef CODEGENOPT #undef ENUM_CODEGENOPT #undef VALUE_CODEGENOPT diff --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h index b202d01af0ed6ce13dbaa09b245456b255fdee05..6952b48e898a819bef0f3b38d7d1cca65549c158 100644 --- a/clang/include/clang/Basic/CodeGenOptions.h +++ b/clang/include/clang/Basic/CodeGenOptions.h @@ -530,6 +530,10 @@ public: return SanitizeBinaryMetadataCovered || SanitizeBinaryMetadataAtomics || SanitizeBinaryMetadataUAR; } + + /// Reset all of the options that are not considered when building a + /// module. + void resetNonModularOptions(StringRef ModuleFormat); }; } // end namespace clang diff --git a/clang/include/clang/Basic/Cuda.h b/clang/include/clang/Basic/Cuda.h index 2d912bdbbd1bc59eda37053faa87be5304803b1f..916cb4b7ef34a7eeb65286c35c5c0f34d51f2091 100644 --- a/clang/include/clang/Basic/Cuda.h +++ b/clang/include/clang/Basic/Cuda.h @@ -39,9 +39,11 @@ enum class CudaVersion { CUDA_118, CUDA_120, CUDA_121, - FULLY_SUPPORTED = CUDA_118, + CUDA_122, + CUDA_123, + FULLY_SUPPORTED = CUDA_123, PARTIALLY_SUPPORTED = - CUDA_121, // Partially supported. Proceed with a warning. + CUDA_123, // Partially supported. Proceed with a warning. NEW = 10000, // Too new. Issue a warning, but allow using it. }; const char *CudaVersionToString(CudaVersion V); @@ -71,6 +73,7 @@ enum class CudaArch { SM_87, SM_89, SM_90, + SM_90a, GFX600, GFX601, GFX602, diff --git a/clang/include/clang/Basic/DebugOptions.def b/clang/include/clang/Basic/DebugOptions.def new file mode 100644 index 0000000000000000000000000000000000000000..7cd3edf08a17eadb3ae0965e8747654f4e66a593 --- /dev/null +++ b/clang/include/clang/Basic/DebugOptions.def @@ -0,0 +1,146 @@ +//===--- DebugOptions.def - Debug option database ----------------- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines debug-specific codegen options. Users of this file +// must define the CODEGENOPT macro to make use of this information. +// Optionally, the user may also define DEBUGOPT (for flags), ENUM_DEBUGOPT (for +// options that have enumeration type), and VALUE_DEBUGOPT (is a debug option +// that describes a value rather than a flag). +// +// BENIGN_ variants of the macros are used to describe options that do not +// affect the generated PCM. +// +//===----------------------------------------------------------------------===// +#ifndef DEBUGOPT +#define DEBUGOPT(Name, Bits, Default) \ +CODEGENOPT(Name, Bits, Default) +#endif + +#ifndef VALUE_DEBUGOPT +# define VALUE_DEBUGOPT(Name, Bits, Default) \ +VALUE_CODEGENOPT(Name, Bits, Default) +#endif + +#ifndef ENUM_DEBUGOPT +# define ENUM_DEBUGOPT(Name, Type, Bits, Default) \ +ENUM_CODEGENOPT(Name, Type, Bits, Default) +#endif + +#ifndef BENIGN_DEBUGOPT +#define BENIGN_DEBUGOPT(Name, Bits, Default) \ +DEBUGOPT(Name, Bits, Default) +#endif + +#ifndef BENIGN_VALUE_DEBUGOPT +# define BENIGN_VALUE_DEBUGOPT(Name, Bits, Default) \ +VALUE_DEBUGOPT(Name, Bits, Default) +#endif + +#ifndef BENIGN_ENUM_DEBUGOPT +# define BENIGN_ENUM_DEBUGOPT(Name, Type, Bits, Default) \ +ENUM_DEBUGOPT(Name, Type, Bits, Default) +#endif + +BENIGN_ENUM_DEBUGOPT(CompressDebugSections, llvm::DebugCompressionType, 2, + llvm::DebugCompressionType::None) +DEBUGOPT(Dwarf64, 1, 0) ///< -gdwarf64. +BENIGN_DEBUGOPT(EnableDIPreservationVerify, 1, 0) ///< Enable di preservation + ///< verify each (it means + ///< check the original debug + ///< info metadata + ///< preservation). +BENIGN_DEBUGOPT(ForceDwarfFrameSection , 1, 0) ///< Set when -fforce-dwarf-frame + ///< is enabled. + +///< Set when -femit-dwarf-unwind is passed. +BENIGN_ENUM_DEBUGOPT(EmitDwarfUnwind, llvm::EmitDwarfUnwindType, 2, + llvm::EmitDwarfUnwindType::Default) + +BENIGN_DEBUGOPT(NoDwarfDirectoryAsm , 1, 0) ///< Set when -fno-dwarf-directory-asm + ///< is enabled. + +BENIGN_DEBUGOPT(NoInlineLineTables, 1, 0) ///< Whether debug info should contain + ///< inline line tables. + +DEBUGOPT(DebugStrictDwarf, 1, 1) ///< Whether or not to use strict DWARF info. + +/// Control the Assignment Tracking debug info feature. +BENIGN_ENUM_DEBUGOPT(AssignmentTrackingMode, AssignmentTrackingOpts, 2, + AssignmentTrackingOpts::Disabled) + +DEBUGOPT(DebugColumnInfo, 1, 0) ///< Whether or not to use column information + ///< in debug info. + +DEBUGOPT(DebugTypeExtRefs, 1, 0) ///< Whether or not debug info should contain + ///< external references to a PCH or module. + +DEBUGOPT(DebugExplicitImport, 1, 0) ///< Whether or not debug info should + ///< contain explicit imports for + ///< anonymous namespaces + +/// Set debug info source file hashing algorithm. +ENUM_DEBUGOPT(DebugSrcHash, DebugSrcHashKind, 2, DSH_MD5) + +DEBUGOPT(SplitDwarfInlining, 1, 1) ///< Whether to include inlining info in the + ///< skeleton CU to allow for symbolication + ///< of inline stack frames without .dwo files. +DEBUGOPT(DebugFwdTemplateParams, 1, 0) ///< Whether to emit complete + ///< template parameter descriptions in + ///< forward declarations (versus just + ///< including them in the name). +ENUM_DEBUGOPT(DebugSimpleTemplateNames, + llvm::codegenoptions::DebugTemplateNamesKind, 2, + llvm::codegenoptions::DebugTemplateNamesKind::Full) + ///< Whether to emit template parameters in the textual names of + ///< template specializations. + ///< Implies DebugFwdTemplateNames to allow decorated names to be + ///< reconstructed when needed. + +/// The kind of generated debug info. +ENUM_DEBUGOPT(DebugInfo, llvm::codegenoptions::DebugInfoKind, 4, + llvm::codegenoptions::NoDebugInfo) + +/// Whether to generate macro debug info. +DEBUGOPT(MacroDebugInfo, 1, 0) + +/// Tune the debug info for this debugger. +ENUM_DEBUGOPT(DebuggerTuning, llvm::DebuggerKind, 3, + llvm::DebuggerKind::Default) + +/// Dwarf version. Version zero indicates to LLVM that no DWARF should be +/// emitted. +VALUE_DEBUGOPT(DwarfVersion, 3, 0) + +/// Whether we should emit CodeView debug information. It's possible to emit +/// CodeView and DWARF into the same object. +DEBUGOPT(EmitCodeView, 1, 0) + +/// Whether to emit the .debug$H section containing hashes of CodeView types. +DEBUGOPT(CodeViewGHash, 1, 0) + +/// Whether to emit the compiler path and command line into the CodeView debug information. +DEBUGOPT(CodeViewCommandLine, 1, 0) + +/// Whether emit extra debug info for sample pgo profile collection. +DEBUGOPT(DebugInfoForProfiling, 1, 0) + +/// Whether to emit .debug_gnu_pubnames section instead of .debug_pubnames. +DEBUGOPT(DebugNameTable, 2, 0) + +/// Whether to use DWARF base address specifiers in .debug_ranges. +DEBUGOPT(DebugRangesBaseAddress, 1, 0) + +/// Whether to embed source in DWARF debug line section. +DEBUGOPT(EmbedSource, 1, 0) + +#undef DEBUGOPT +#undef ENUM_DEBUGOPT +#undef VALUE_DEBUGOPT +#undef BENIGN_DEBUGOPT +#undef BENIGN_ENUM_DEBUGOPT +#undef BENIGN_VALUE_DEBUGOPT diff --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/clang/include/clang/Basic/DiagnosticFrontendKinds.td index 715e0c0dc8fa84e5fa851e11dc1bd4661344d1c6..568000106a84dc75d003089b54383485f9163222 100644 --- a/clang/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/clang/include/clang/Basic/DiagnosticFrontendKinds.td @@ -80,6 +80,7 @@ def remark_fe_backend_optimization_remark_analysis_aliasing : Remark<"%0; " "the '__restrict__' qualifier with the independent array arguments. " "Erroneous results will occur if these options are incorrectly applied!">, BackendInfo, InGroup; + def warn_fe_backend_optimization_failure : Warning<"%0">, BackendInfo, InGroup, DefaultWarn; def note_fe_backend_invalid_loc : Note<"could " diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td index ff028bbbf74261e0829ca0294e27acaaf2ac9e80..caee2dc6daadb606dde10e47d2d5404081526d80 100644 --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/clang/include/clang/Basic/DiagnosticGroups.td @@ -632,7 +632,7 @@ def ShadowAll : DiagGroup<"shadow-all", [Shadow, ShadowFieldInConstructor, def Shorten64To32 : DiagGroup<"shorten-64-to-32">; def : DiagGroup<"sign-promo">; def SignCompare : DiagGroup<"sign-compare">; -def : DiagGroup<"switch-default">; +def SwitchDefault : DiagGroup<"switch-default">; def : DiagGroup<"synth">; def SizeofArrayArgument : DiagGroup<"sizeof-array-argument">; def SizeofArrayDecay : DiagGroup<"sizeof-array-decay">; @@ -1126,6 +1126,8 @@ def FutureAttrs : DiagGroup<"future-attribute-extensions", [CXX14Attrs, CXX17Attrs, CXX20Attrs]>; +def CXX23AttrsOnLambda : DiagGroup<"c++23-lambda-attributes">; + // A warning group for warnings about using C++11 features as extensions in // earlier C++ versions. def CXX11 : DiagGroup<"c++11-extensions", [CXX11ExtraSemi, CXX11InlineNamespace, @@ -1145,7 +1147,7 @@ def CXX20 : DiagGroup<"c++20-extensions", [CXX20Designator, CXX20Attrs]>; // A warning group for warnings about using C++23 features as extensions in // earlier C++ versions. -def CXX23 : DiagGroup<"c++23-extensions">; +def CXX23 : DiagGroup<"c++23-extensions", [CXX23AttrsOnLambda]>; // A warning group for warnings about using C++26 features as extensions in // earlier C++ versions. diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index 21fe6066d5876105928a8560508ccf216331002f..6150fc36430ab16111148b25d725d69955e21842 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -1035,7 +1035,7 @@ def err_capture_default_first : Error< "capture default must be first">; def ext_decl_attrs_on_lambda : ExtWarn< "%select{an attribute specifier sequence|%0}1 in this position " - "is a C++23 extension">, InGroup; + "is a C++23 extension">, InGroup; def ext_lambda_missing_parens : ExtWarn< "lambda without a parameter clause is a C++23 extension">, InGroup; @@ -1362,7 +1362,7 @@ def warn_pragma_acc_unimplemented_clause_parsing : Warning<"OpenACC clause parsing not yet implemented">, InGroup; def err_acc_invalid_directive - : Error<"invalid OpenACC directive '%select{%1|%1 %2}0'">; + : Error<"invalid OpenACC directive %select{%1|'%1 %2'}0">; def err_acc_missing_directive : Error<"expected OpenACC directive">; def err_acc_invalid_open_paren : Error<"expected clause-list or newline in OpenACC directive">; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 6dfb2d7195203a3d900674331f036dd8306ab224..94e97a891baedcdcbbfb02805d771201d82d8db4 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -1669,6 +1669,8 @@ def err_qualified_friend_def : Error< "friend function definition cannot be qualified with '%0'">; def err_friend_def_in_local_class : Error< "friend function cannot be defined in a local class">; +def err_friend_specialization_def : Error< + "friend function specialization cannot be defined">; def err_friend_not_first_in_declaration : Error< "'friend' must appear first in a non-function declaration">; def err_using_decl_friend : Error< @@ -2884,6 +2886,8 @@ def warn_cxx11_compat_constexpr_body_multiple_return : Warning< InGroup, DefaultIgnore; def note_constexpr_body_previous_return : Note< "previous return statement is here">; +def err_ms_constexpr_cannot_be_applied : Error< + "attribute 'msvc::constexpr' cannot be applied to the %select{constexpr|consteval|virtual}0 function %1">; // C++20 function try blocks in constexpr def ext_constexpr_function_try_block_cxx20 : ExtWarn< @@ -4933,6 +4937,8 @@ def err_template_param_shadow : Error< def ext_template_param_shadow : ExtWarn< err_template_param_shadow.Summary>, InGroup; def note_template_param_here : Note<"template parameter is declared here">; +def note_template_param_external : Note< + "template parameter from hidden source: %0">; def warn_template_export_unsupported : Warning< "exported templates are unsupported">; def err_template_outside_namespace_or_class_scope : Error< @@ -5061,6 +5067,8 @@ def err_template_arg_list_different_arity : Error< "%select{class template|function template|variable template|alias template|" "template template parameter|concept|template}1 %2">; def note_template_decl_here : Note<"template is declared here">; +def note_template_decl_external : Note< + "template declaration from hidden source: %0">; def err_template_arg_must_be_type : Error< "template argument for template type parameter must be a type">; def err_template_arg_must_be_type_suggest : Error< @@ -10060,6 +10068,8 @@ def warn_missing_case : Warning<"%plural{" "3:enumeration values %1, %2, and %3 not handled in switch|" ":%0 enumeration values not handled in switch: %1, %2, %3...}0">, InGroup; +def warn_switch_default : Warning<"'switch' missing 'default' label">, + InGroup, DefaultIgnore; def warn_unannotated_fallthrough : Warning< "unannotated fall-through between switch labels">, @@ -11992,7 +12002,7 @@ def warn_tcb_enforcement_violation : Warning< // RISC-V builtin required extension warning def err_riscv_builtin_requires_extension : Error< - "builtin requires%select{| at least one of the following extensions to be enabled}0: %1">; + "builtin requires%select{| at least one of the following extensions}0: %1">; def err_riscv_builtin_invalid_lmul : Error< "LMUL argument must be in the range [0,3] or [5,7]">; def err_riscv_type_requires_extension : Error< diff --git a/clang/include/clang/Basic/DirectoryEntry.h b/clang/include/clang/Basic/DirectoryEntry.h index 5d083e68facd7a6b73975bab00dc29e8984e8ae5..906c2e9af23b3135419ad6658a51baadf1d07763 100644 --- a/clang/include/clang/Basic/DirectoryEntry.h +++ b/clang/include/clang/Basic/DirectoryEntry.h @@ -245,78 +245,4 @@ template <> struct DenseMapInfo { } // end namespace llvm -namespace clang { - -/// Wrapper around OptionalDirectoryEntryRef that degrades to 'const -/// DirectoryEntry*', facilitating incremental patches to propagate -/// DirectoryEntryRef. -/// -/// This class can be used as return value or field where it's convenient for -/// an OptionalDirectoryEntryRef to degrade to a 'const DirectoryEntry*'. The -/// purpose is to avoid code churn due to dances like the following: -/// \code -/// // Old code. -/// lvalue = rvalue; -/// -/// // Temporary code from an incremental patch. -/// OptionalDirectoryEntryRef MaybeF = rvalue; -/// lvalue = MaybeF ? &MaybeF.getDirectoryEntry() : nullptr; -/// -/// // Final code. -/// lvalue = rvalue; -/// \endcode -/// -/// FIXME: Once DirectoryEntryRef is "everywhere" and DirectoryEntry::LastRef -/// and DirectoryEntry::getName have been deleted, delete this class and -/// replace instances with OptionalDirectoryEntryRef. -class OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr - : public OptionalDirectoryEntryRef { -public: - OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr() = default; - OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr( - OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr &&) = default; - OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr( - const OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr &) = default; - OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr & - operator=(OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr &&) = default; - OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr & - operator=(const OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr &) = default; - - OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr(std::nullopt_t) {} - OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr(DirectoryEntryRef Ref) - : OptionalDirectoryEntryRef(Ref) {} - OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr( - OptionalDirectoryEntryRef MaybeRef) - : OptionalDirectoryEntryRef(MaybeRef) {} - - OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr & - operator=(std::nullopt_t) { - OptionalDirectoryEntryRef::operator=(std::nullopt); - return *this; - } - OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr &operator=(DirectoryEntryRef Ref) { - OptionalDirectoryEntryRef::operator=(Ref); - return *this; - } - OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr & - operator=(OptionalDirectoryEntryRef MaybeRef) { - OptionalDirectoryEntryRef::operator=(MaybeRef); - return *this; - } - - /// Degrade to 'const DirectoryEntry *' to allow DirectoryEntry::LastRef and - /// DirectoryEntry::getName have been deleted, delete this class and replace - /// instances with OptionalDirectoryEntryRef - operator const DirectoryEntry *() const { - return has_value() ? &(*this)->getDirEntry() : nullptr; - } -}; - -static_assert(std::is_trivially_copyable< - OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr>::value, - "OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr should be " - "trivially copyable"); - -} // end namespace clang - #endif // LLVM_CLANG_BASIC_DIRECTORYENTRY_H diff --git a/clang/include/clang/Basic/FPOptions.def b/clang/include/clang/Basic/FPOptions.def index 5b923a1944e509ad31736bf48d6932364bf2c797..79f04c89c9fedc14eaca6928e6677f9db260bb8d 100644 --- a/clang/include/clang/Basic/FPOptions.def +++ b/clang/include/clang/Basic/FPOptions.def @@ -28,4 +28,5 @@ OPTION(FPEvalMethod, LangOptions::FPEvalMethodKind, 2, AllowApproxFunc) OPTION(Float16ExcessPrecision, LangOptions::ExcessPrecisionKind, 2, FPEvalMethod) OPTION(BFloat16ExcessPrecision, LangOptions::ExcessPrecisionKind, 2, Float16ExcessPrecision) OPTION(MathErrno, bool, 1, BFloat16ExcessPrecision) +OPTION(ComplexRange, LangOptions::ComplexRangeKind, 2, MathErrno) #undef OPTION diff --git a/clang/include/clang/Basic/Features.def b/clang/include/clang/Basic/Features.def index adaf2e413f2f6deaf118197e96d1b2fb58ec7a4b..7473e00a7bd86bae6f92d4882070f2337a169c65 100644 --- a/clang/include/clang/Basic/Features.def +++ b/clang/include/clang/Basic/Features.def @@ -89,6 +89,8 @@ FEATURE(blocks, LangOpts.Blocks) FEATURE(c_thread_safety_attributes, true) FEATURE(cxx_exceptions, LangOpts.CXXExceptions) FEATURE(cxx_rtti, LangOpts.RTTI &&LangOpts.RTTIData) +EXTENSION(define_target_os_macros, + PP.getPreprocessorOpts().DefineTargetOSMacros) FEATURE(enumerator_attributes, true) FEATURE(nullability, true) FEATURE(nullability_on_arrays, true) @@ -102,6 +104,7 @@ FEATURE(scudo, LangOpts.Sanitize.hasOneOf(SanitizerKind::Scudo)) FEATURE(swiftasynccc, PP.getTargetInfo().checkCallingConvention(CC_SwiftAsync) == clang::TargetInfo::CCCR_OK) +FEATURE(pragma_stdc_cx_limited_range, true) // Objective-C features FEATURE(objc_arr, LangOpts.ObjCAutoRefCount) // FIXME: REMOVE? FEATURE(objc_arc, LangOpts.ObjCAutoRefCount) diff --git a/clang/include/clang/Basic/FileEntry.h b/clang/include/clang/Basic/FileEntry.h index bc65463735488417dc241961c63df4df4fb7ae52..35efa147950f0608476179f74d70742b69ca622b 100644 --- a/clang/include/clang/Basic/FileEntry.h +++ b/clang/include/clang/Basic/FileEntry.h @@ -279,72 +279,6 @@ template <> struct DenseMapInfo { namespace clang { -/// Wrapper around OptionalFileEntryRef that degrades to 'const FileEntry*', -/// facilitating incremental patches to propagate FileEntryRef. -/// -/// This class can be used as return value or field where it's convenient for -/// an OptionalFileEntryRef to degrade to a 'const FileEntry*'. The purpose -/// is to avoid code churn due to dances like the following: -/// \code -/// // Old code. -/// lvalue = rvalue; -/// -/// // Temporary code from an incremental patch. -/// OptionalFileEntryRef MaybeF = rvalue; -/// lvalue = MaybeF ? &MaybeF.getFileEntry() : nullptr; -/// -/// // Final code. -/// lvalue = rvalue; -/// \endcode -/// -/// FIXME: Once FileEntryRef is "everywhere" and FileEntry::LastRef and -/// FileEntry::getName have been deleted, delete this class and replace -/// instances with OptionalFileEntryRef. -class OptionalFileEntryRefDegradesToFileEntryPtr : public OptionalFileEntryRef { -public: - OptionalFileEntryRefDegradesToFileEntryPtr() = default; - OptionalFileEntryRefDegradesToFileEntryPtr( - OptionalFileEntryRefDegradesToFileEntryPtr &&) = default; - OptionalFileEntryRefDegradesToFileEntryPtr( - const OptionalFileEntryRefDegradesToFileEntryPtr &) = default; - OptionalFileEntryRefDegradesToFileEntryPtr & - operator=(OptionalFileEntryRefDegradesToFileEntryPtr &&) = default; - OptionalFileEntryRefDegradesToFileEntryPtr & - operator=(const OptionalFileEntryRefDegradesToFileEntryPtr &) = default; - - OptionalFileEntryRefDegradesToFileEntryPtr(std::nullopt_t) {} - OptionalFileEntryRefDegradesToFileEntryPtr(FileEntryRef Ref) - : OptionalFileEntryRef(Ref) {} - OptionalFileEntryRefDegradesToFileEntryPtr(OptionalFileEntryRef MaybeRef) - : OptionalFileEntryRef(MaybeRef) {} - - OptionalFileEntryRefDegradesToFileEntryPtr &operator=(std::nullopt_t) { - OptionalFileEntryRef::operator=(std::nullopt); - return *this; - } - OptionalFileEntryRefDegradesToFileEntryPtr &operator=(FileEntryRef Ref) { - OptionalFileEntryRef::operator=(Ref); - return *this; - } - OptionalFileEntryRefDegradesToFileEntryPtr & - operator=(OptionalFileEntryRef MaybeRef) { - OptionalFileEntryRef::operator=(MaybeRef); - return *this; - } - - /// Degrade to 'const FileEntry *' to allow FileEntry::LastRef and - /// FileEntry::getName have been deleted, delete this class and replace - /// instances with OptionalFileEntryRef - operator const FileEntry *() const { - return has_value() ? &(*this)->getFileEntry() : nullptr; - } -}; - -static_assert( - std::is_trivially_copyable< - OptionalFileEntryRefDegradesToFileEntryPtr>::value, - "OptionalFileEntryRefDegradesToFileEntryPtr should be trivially copyable"); - inline bool operator==(const FileEntry *LHS, const OptionalFileEntryRef &RHS) { return LHS == (RHS ? &RHS->getFileEntry() : nullptr); } @@ -394,6 +328,7 @@ class FileEntry { public: ~FileEntry(); + LLVM_DEPRECATED("Use FileEntryRef::getName() instead.", "") StringRef getName() const { return LastRef->getName(); } StringRef tryGetRealPathName() const { return RealPathName; } diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def index c3d5399905a3fdae2580eadcfdf47c520513df14..152d9f65f86dbe022596239d664cc645a667ba79 100644 --- a/clang/include/clang/Basic/LangOptions.def +++ b/clang/include/clang/Basic/LangOptions.def @@ -220,6 +220,8 @@ BENIGN_LANGOPT(NoSignedZero , 1, 0, "Permit Floating Point optimization wit BENIGN_LANGOPT(AllowRecip , 1, 0, "Permit Floating Point reciprocal") BENIGN_LANGOPT(ApproxFunc , 1, 0, "Permit Floating Point approximation") +ENUM_LANGOPT(ComplexRange, ComplexRangeKind, 2, CX_Full, "Enable use of range reduction for complex arithmetics.") + BENIGN_LANGOPT(ObjCGCBitmapPrint , 1, 0, "printing of GC's bitmap layout for __weak/__strong ivars") BENIGN_LANGOPT(AccessControl , 1, 1, "C++ access control") diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h index 2d167dd2bdf1287a4a4fa8a8e7a84697b961ca29..9f986fce2d44188f0414034ab511a2de980e6ca2 100644 --- a/clang/include/clang/Basic/LangOptions.h +++ b/clang/include/clang/Basic/LangOptions.h @@ -152,6 +152,7 @@ public: MSVC2019 = 1920, MSVC2019_5 = 1925, MSVC2019_8 = 1928, + MSVC2022_3 = 1933, }; enum SYCLMajorVersion { @@ -391,6 +392,8 @@ public: IncompleteOnly = 3, }; + enum ComplexRangeKind { CX_Full, CX_Limited, CX_Fortran }; + public: /// The used language standard. LangStandard::Kind LangStd; @@ -740,6 +743,7 @@ public: setAllowFEnvAccess(true); else setAllowFEnvAccess(LangOptions::FPM_Off); + setComplexRange(LO.getComplexRange()); } bool allowFPContractWithinStatement() const { diff --git a/clang/include/clang/Basic/Module.h b/clang/include/clang/Basic/Module.h index d29cc0b45d583e049e614de254761d99ac2efb2d..62786e3ac865e640960279afeda93e333fab596a 100644 --- a/clang/include/clang/Basic/Module.h +++ b/clang/include/clang/Basic/Module.h @@ -156,7 +156,7 @@ public: /// The build directory of this module. This is the directory in /// which the module is notionally built, and relative to which its headers /// are found. - OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr Directory; + OptionalDirectoryEntryRef Directory; /// The presumed file name for the module map defining this module. /// Only non-empty when building from preprocessed source. @@ -672,7 +672,7 @@ public: } /// The serialized AST file for this module, if one was created. - OptionalFileEntryRefDegradesToFileEntryPtr getASTFile() const { + OptionalFileEntryRef getASTFile() const { return getTopLevelModule()->ASTFile; } diff --git a/clang/include/clang/Basic/OpenACCKinds.h b/clang/include/clang/Basic/OpenACCKinds.h index 1a5bf7e0e831ce35db7480d5e61efac4c395fc6d..62c0a4c1a9dea41f09b14335cdb6b7022a8a82d7 100644 --- a/clang/include/clang/Basic/OpenACCKinds.h +++ b/clang/include/clang/Basic/OpenACCKinds.h @@ -34,7 +34,7 @@ enum class OpenACCDirectiveKind { // Misc. Loop, - // FIXME: 'cache' + Cache, // Combined Constructs. ParallelLoop, @@ -53,7 +53,7 @@ enum class OpenACCDirectiveKind { Shutdown, Set, Update, - // FIXME: wait construct. + Wait, // Procedure Calls in Compute Regions. Routine, diff --git a/clang/include/clang/Basic/SourceManager.h b/clang/include/clang/Basic/SourceManager.h index 985ea6354b82199f097fedb044c2829b5e9b1aea..d2ece14da0b11ab1e1448dd0ccf6515e8237994e 100644 --- a/clang/include/clang/Basic/SourceManager.h +++ b/clang/include/clang/Basic/SourceManager.h @@ -143,7 +143,7 @@ public: /// /// FIXME: Make non-optional using a virtual file as needed, remove \c /// Filename and use \c OrigEntry.getNameAsRequested() instead. - OptionalFileEntryRefDegradesToFileEntryPtr OrigEntry; + OptionalFileEntryRef OrigEntry; /// References the file which the contents were actually loaded from. /// @@ -1064,8 +1064,8 @@ public: /// Returns the FileEntry record for the provided FileID. const FileEntry *getFileEntryForID(FileID FID) const { - if (auto *Entry = getSLocEntryForFile(FID)) - return Entry->getFile().getContentCache().OrigEntry; + if (auto FE = getFileEntryRefForID(FID)) + return *FE; return nullptr; } @@ -1083,9 +1083,11 @@ public: std::optional getNonBuiltinFilenameForID(FileID FID) const; /// Returns the FileEntry record for the provided SLocEntry. - const FileEntry *getFileEntryForSLocEntry(const SrcMgr::SLocEntry &sloc) const - { - return sloc.getFile().getContentCache().OrigEntry; + const FileEntry * + getFileEntryForSLocEntry(const SrcMgr::SLocEntry &SLocEntry) const { + if (auto FE = SLocEntry.getFile().getContentCache().OrigEntry) + return *FE; + return nullptr; } /// Return a StringRef to the source buffer data for the diff --git a/clang/include/clang/Basic/SyncScope.h b/clang/include/clang/Basic/SyncScope.h index 7919f64c6daf97b0ac38a02247478f92bb10d3ca..bc7ec7b5cf777ef4556678445dc44fed078dcfb5 100644 --- a/clang/include/clang/Basic/SyncScope.h +++ b/clang/include/clang/Basic/SyncScope.h @@ -40,6 +40,11 @@ namespace clang { /// Update getAsString. /// enum class SyncScope { + SystemScope, + DeviceScope, + WorkgroupScope, + WavefrontScope, + SingleScope, HIPSingleThread, HIPWavefront, HIPWorkgroup, @@ -54,6 +59,16 @@ enum class SyncScope { inline llvm::StringRef getAsString(SyncScope S) { switch (S) { + case SyncScope::SystemScope: + return "system_scope"; + case SyncScope::DeviceScope: + return "device_scope"; + case SyncScope::WorkgroupScope: + return "workgroup_scope"; + case SyncScope::WavefrontScope: + return "wavefront_scope"; + case SyncScope::SingleScope: + return "single_scope"; case SyncScope::HIPSingleThread: return "hip_singlethread"; case SyncScope::HIPWavefront: @@ -77,7 +92,7 @@ inline llvm::StringRef getAsString(SyncScope S) { } /// Defines the kind of atomic scope models. -enum class AtomicScopeModelKind { None, OpenCL, HIP }; +enum class AtomicScopeModelKind { None, OpenCL, HIP, Generic }; /// Defines the interface for synch scope model. class AtomicScopeModel { @@ -205,6 +220,56 @@ public: } }; +/// Defines the generic atomic scope model. +class AtomicScopeGenericModel : public AtomicScopeModel { +public: + /// The enum values match predefined built-in macros __ATOMIC_SCOPE_*. + enum ID { + System = 0, + Device = 1, + Workgroup = 2, + Wavefront = 3, + Single = 4, + Last = Single + }; + + AtomicScopeGenericModel() = default; + + SyncScope map(unsigned S) const override { + switch (static_cast(S)) { + case Device: + return SyncScope::DeviceScope; + case System: + return SyncScope::SystemScope; + case Workgroup: + return SyncScope::WorkgroupScope; + case Wavefront: + return SyncScope::WavefrontScope; + case Single: + return SyncScope::SingleScope; + } + llvm_unreachable("Invalid language sync scope value"); + } + + bool isValid(unsigned S) const override { + return S >= static_cast(System) && + S <= static_cast(Last); + } + + ArrayRef getRuntimeValues() const override { + static_assert(Last == Single, "Does not include all sync scopes"); + static const unsigned Scopes[] = { + static_cast(Device), static_cast(System), + static_cast(Workgroup), static_cast(Wavefront), + static_cast(Single)}; + return llvm::ArrayRef(Scopes); + } + + unsigned getFallBackValue() const override { + return static_cast(System); + } +}; + inline std::unique_ptr AtomicScopeModel::create(AtomicScopeModelKind K) { switch (K) { @@ -214,6 +279,8 @@ AtomicScopeModel::create(AtomicScopeModelKind K) { return std::make_unique(); case AtomicScopeModelKind::HIP: return std::make_unique(); + case AtomicScopeModelKind::Generic: + return std::make_unique(); } llvm_unreachable("Invalid atomic scope model kind"); } diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h index 41f3c2e403cbef6d0fbd7c9640f810f418d7da43..ec0189627dfbd2c474803b19ae1ff5c45b6db9a6 100644 --- a/clang/include/clang/Basic/TargetInfo.h +++ b/clang/include/clang/Basic/TargetInfo.h @@ -266,7 +266,6 @@ protected: LLVM_PREFERRED_TYPE(bool) unsigned AllowAMDGPUUnsafeFPAtomics : 1; - LLVM_PREFERRED_TYPE(bool) unsigned ARMCDECoprocMask : 8; unsigned MaxOpenCLWorkGroupSize; diff --git a/clang/include/clang/Basic/TargetOSMacros.def b/clang/include/clang/Basic/TargetOSMacros.def new file mode 100644 index 0000000000000000000000000000000000000000..dfc2e033f6fd0db926d6882c92a25fc8bcfde07e --- /dev/null +++ b/clang/include/clang/Basic/TargetOSMacros.def @@ -0,0 +1,55 @@ +//===--- TargetOSMacros.def - Target OS macros ------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file specifies the predefined TARGET_OS_* conditional macros. +// A target macro `Name` should be defined if `Predicate` evaluates to true. +// The macro expects `const llvm::Triple &Triple` and the class `llvm::Triple` +// to be available for the predicate. +// +//===----------------------------------------------------------------------===// + +#ifndef TARGET_OS +#define TARGET_OS(Name, Predicate) +#endif + +// Windows targets. +TARGET_OS(TARGET_OS_WIN32, Triple.isOSWindows()) +TARGET_OS(TARGET_OS_WINDOWS, Triple.isOSWindows()) + +// Linux target. +TARGET_OS(TARGET_OS_LINUX, Triple.isOSLinux()) + +// Unix target. +TARGET_OS(TARGET_OS_UNIX, Triple.isOSNetBSD() || + Triple.isOSFreeBSD() || + Triple.isOSOpenBSD() || + Triple.isOSSolaris()) + +// Apple (Mac) targets. +TARGET_OS(TARGET_OS_MAC, Triple.isOSDarwin()) +TARGET_OS(TARGET_OS_OSX, Triple.isMacOSX()) +TARGET_OS(TARGET_OS_IPHONE, Triple.isiOS() || Triple.isTvOS() || + Triple.isWatchOS()) +// Triple::isiOS() also includes tvOS +TARGET_OS(TARGET_OS_IOS, Triple.getOS() == llvm::Triple::IOS) +TARGET_OS(TARGET_OS_TV, Triple.isTvOS()) +TARGET_OS(TARGET_OS_WATCH, Triple.isWatchOS()) +TARGET_OS(TARGET_OS_DRIVERKIT, Triple.isDriverKit()) +TARGET_OS(TARGET_OS_MACCATALYST, Triple.isMacCatalystEnvironment()) +TARGET_OS(TARGET_OS_SIMULATOR, Triple.isSimulatorEnvironment()) + +// Deprecated Apple target conditionals. +TARGET_OS(TARGET_OS_EMBEDDED, (Triple.isiOS() || Triple.isTvOS() \ + || Triple.isWatchOS()) \ + && !Triple.isMacCatalystEnvironment() \ + && !Triple.isSimulatorEnvironment()) +TARGET_OS(TARGET_OS_NANO, Triple.isWatchOS()) +TARGET_OS(TARGET_IPHONE_SIMULATOR, Triple.isSimulatorEnvironment()) +TARGET_OS(TARGET_OS_UIKITFORMAC, Triple.isMacCatalystEnvironment()) + +#undef TARGET_OS diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def index 5f9915d210221c4f8619f581c030368908077a6b..3f0e1e1a7d45ad2cdcf1aba4c578736913fdc093 100644 --- a/clang/include/clang/Basic/TokenKinds.def +++ b/clang/include/clang/Basic/TokenKinds.def @@ -911,6 +911,11 @@ PRAGMA_ANNOTATION(pragma_fenv_access_ms) // handles them. PRAGMA_ANNOTATION(pragma_fenv_round) +// Annotation for #pragma STDC CX_LIMITED_RANGE +// The lexer produces these so that they only take effect when the parser +// handles them. +PRAGMA_ANNOTATION(pragma_cx_limited_range) + // Annotation for #pragma float_control // The lexer produces these so that they only take effect when the parser // handles them. diff --git a/clang/include/clang/Basic/arm_sme.td b/clang/include/clang/Basic/arm_sme.td index 34dbfff6c4c85cf13fec471d34d918a04b98fdcf..fcff6fe35b7ba3f856d5b56ca05b5af1853d5c24 100644 --- a/clang/include/clang/Basic/arm_sme.td +++ b/clang/include/clang/Basic/arm_sme.td @@ -319,11 +319,37 @@ let TargetGuard = "sme2" in { // Spill and fill of ZT0 // let TargetGuard = "sme2" in { - def SVLDR_ZT : Inst<"svldr_zt", "viQ", "", MergeNone, "aarch64_sme_ldr_zt", [IsOverloadNone, IsStreamingCompatible, IsSharedZA, IsPreservesZA], [ImmCheck<0, ImmCheck0_0>]>; + def SVLDR_ZT : Inst<"svldr_zt", "viQ", "", MergeNone, "aarch64_sme_ldr_zt", [IsOverloadNone, IsStreamingCompatible, IsSharedZA], [ImmCheck<0, ImmCheck0_0>]>; def SVSTR_ZT : Inst<"svstr_zt", "vi%", "", MergeNone, "aarch64_sme_str_zt", [IsOverloadNone, IsStreamingCompatible, IsSharedZA, IsPreservesZA], [ImmCheck<0, ImmCheck0_0>]>; +} // // Zero ZT0 // +let TargetGuard = "sme2" in { def SVZERO_ZT : Inst<"svzero_zt", "vi", "", MergeNone, "aarch64_sme_zero_zt", [IsOverloadNone, IsStreamingCompatible, IsSharedZA], [ImmCheck<0, ImmCheck0_0>]>; } + +// +// lookup table expand four contiguous registers +// +let TargetGuard = "sme2" in { + def SVLUTI2_LANE_ZT_X4 : Inst<"svluti2_lane_zt_{d}_x4", "4.di[i", "cUcsUsiUibhf", MergeNone, "aarch64_sme_luti2_lane_zt_x4", [IsStreaming, IsSharedZA, IsPreservesZA], [ImmCheck<0, ImmCheck0_0>, ImmCheck<2, ImmCheck0_3>]>; + def SVLUTI4_LANE_ZT_X4 : Inst<"svluti4_lane_zt_{d}_x4", "4.di[i", "sUsiUibhf", MergeNone, "aarch64_sme_luti4_lane_zt_x4", [IsStreaming, IsSharedZA, IsPreservesZA], [ImmCheck<0, ImmCheck0_0>, ImmCheck<2, ImmCheck0_1>]>; +} + +// +// lookup table expand one register +// +let TargetGuard = "sme2" in { + def SVLUTI2_LANE_ZT : Inst<"svluti2_lane_zt_{d}", "di[i", "cUcsUsiUibhf", MergeNone, "aarch64_sme_luti2_lane_zt", [IsStreaming, IsSharedZA, IsPreservesZA], [ImmCheck<0, ImmCheck0_0>, ImmCheck<2, ImmCheck0_15>]>; + def SVLUTI4_LANE_ZT : Inst<"svluti4_lane_zt_{d}", "di[i", "cUcsUsiUibhf", MergeNone, "aarch64_sme_luti4_lane_zt", [IsStreaming, IsSharedZA, IsPreservesZA], [ImmCheck<0, ImmCheck0_0>, ImmCheck<2, ImmCheck0_7>]>; +} + +// +// lookup table expand two contiguous registers +// +let TargetGuard = "sme2" in { + def SVLUTI2_LANE_ZT_X2 : Inst<"svluti2_lane_zt_{d}_x2", "2.di[i", "cUcsUsiUibhf", MergeNone, "aarch64_sme_luti2_lane_zt_x2", [IsStreaming, IsSharedZA, IsPreservesZA], [ImmCheck<0, ImmCheck0_0>, ImmCheck<2, ImmCheck0_7>]>; + def SVLUTI4_LANE_ZT_X2 : Inst<"svluti4_lane_zt_{d}_x2", "2.di[i", "cUcsUsiUibhf", MergeNone, "aarch64_sme_luti4_lane_zt_x2", [IsStreaming, IsSharedZA, IsPreservesZA], [ImmCheck<0, ImmCheck0_0>, ImmCheck<2, ImmCheck0_3>]>; +} diff --git a/clang/include/clang/Basic/arm_sve.td b/clang/include/clang/Basic/arm_sve.td index 3f69a3df9e616ab7f41c81d7b0a3a38c86501eff..aa9b105364a51a1004873c95e4dda5ac811268df 100644 --- a/clang/include/clang/Basic/arm_sve.td +++ b/clang/include/clang/Basic/arm_sve.td @@ -1296,6 +1296,11 @@ def SVCREATE_3_BF16 : SInst<"svcreate3[_{d}]", "3ddd", "b", MergeNone, "", [IsT def SVCREATE_4_BF16 : SInst<"svcreate4[_{d}]", "4dddd", "b", MergeNone, "", [IsTupleCreate]>; } +let TargetGuard = "sve2p1" in { + def SVCREATE_2_B : SInst<"svcreate2[_{d}]", "2dd", "Pc", MergeNone, "", [IsTupleCreate]>; + def SVCREATE_4_B : SInst<"svcreate4[_{d}]", "4dddd", "Pc", MergeNone, "", [IsTupleCreate]>; +} + //////////////////////////////////////////////////////////////////////////////// // Vector insertion and extraction def SVGET_2 : SInst<"svget2[_{d}]", "d2i", "csilUcUsUiUlhfd", MergeNone, "", [IsTupleGet], [ImmCheck<1, ImmCheck0_1>]>; @@ -1316,6 +1321,13 @@ def SVSET_3_BF16 : SInst<"svset3[_{d}]", "33id", "b", MergeNone, "", [IsTupleSet def SVSET_4_BF16 : SInst<"svset4[_{d}]", "44id", "b", MergeNone, "", [IsTupleSet], [ImmCheck<1, ImmCheck0_3>]>; } +let TargetGuard = "sve2p1" in { + def SVGET_2_B : SInst<"svget2[_{d}]", "d2i", "Pc", MergeNone, "", [IsTupleGet], [ImmCheck<1, ImmCheck0_1>]>; + def SVGET_4_B : SInst<"svget4[_{d}]", "d4i", "Pc", MergeNone, "", [IsTupleGet], [ImmCheck<1, ImmCheck0_3>]>; + + def SVSET_2_B : SInst<"svset2[_{d}]", "22id", "Pc", MergeNone, "", [IsTupleSet], [ImmCheck<1, ImmCheck0_1>]>; + def SVSET_4_B : SInst<"svset4[_{d}]", "44id", "Pc", MergeNone, "", [IsTupleSet], [ImmCheck<1, ImmCheck0_3>]>; +} //////////////////////////////////////////////////////////////////////////////// // SVE2 WhileGE/GT let TargetGuard = "sve2" in { @@ -1923,18 +1935,25 @@ def SVBGRP : SInst<"svbgrp[_{d}]", "ddd", "UcUsUiUl", MergeNone, "aarch64_sv def SVBGRP_N : SInst<"svbgrp[_n_{d}]", "dda", "UcUsUiUl", MergeNone, "aarch64_sve_bgrp_x">; } -let TargetGuard = "sve2p1" in { -def SVFCLAMP : SInst<"svclamp[_{d}]", "dddd", "hfd", MergeNone, "aarch64_sve_fclamp", [], []>; -def SVPTRUE_COUNT : SInst<"svptrue_{d}", "}v", "QcQsQiQl", MergeNone, "aarch64_sve_ptrue_{d}", [IsOverloadNone], []>; -def SVPFALSE_COUNT_ALIAS : SInst<"svpfalse_c", "}v", "", MergeNone, "", [IsOverloadNone]>; +let TargetGuard = "sve2p1|sme" in { +def SVPSEL_B : SInst<"svpsel_lane_b8", "PPPm", "Pc", MergeNone, "", [IsStreamingCompatible], []>; +def SVPSEL_H : SInst<"svpsel_lane_b16", "PPPm", "Ps", MergeNone, "", [IsStreamingCompatible], []>; +def SVPSEL_S : SInst<"svpsel_lane_b32", "PPPm", "Pi", MergeNone, "", [IsStreamingCompatible], []>; +def SVPSEL_D : SInst<"svpsel_lane_b64", "PPPm", "Pl", MergeNone, "", [IsStreamingCompatible], []>; +def SVPSEL_COUNT_ALIAS_B : SInst<"svpsel_lane_c8", "}}Pm", "Pc", MergeNone, "", [IsStreamingCompatible], []>; +def SVPSEL_COUNT_ALIAS_H : SInst<"svpsel_lane_c16", "}}Pm", "Ps", MergeNone, "", [IsStreamingCompatible], []>; +def SVPSEL_COUNT_ALIAS_S : SInst<"svpsel_lane_c32", "}}Pm", "Pi", MergeNone, "", [IsStreamingCompatible], []>; +def SVPSEL_COUNT_ALIAS_D : SInst<"svpsel_lane_c64", "}}Pm", "Pl", MergeNone, "", [IsStreamingCompatible], []>; +} -def SVPEXT_SINGLE : SInst<"svpext_lane_{d}", "P}i", "QcQsQiQl", MergeNone, "aarch64_sve_pext", [], [ImmCheck<1, ImmCheck0_3>]>; -def SVPEXT_X2 : SInst<"svpext_lane_{d}_x2", "2.P}i", "QcQsQiQl", MergeNone, "aarch64_sve_pext_x2", [], [ImmCheck<1, ImmCheck0_1>]>; +let TargetGuard = "sve2p1|sme2" in { +//FIXME: Replace IsStreamingCompatible with IsStreamingOrHasSVE2p1 when available +def SVPEXT_SINGLE : SInst<"svpext_lane_{d}", "P}i", "QcQsQiQl", MergeNone, "aarch64_sve_pext", [IsStreamingCompatible], [ImmCheck<1, ImmCheck0_3>]>; +def SVPEXT_X2 : SInst<"svpext_lane_{d}_x2", "2.P}i", "QcQsQiQl", MergeNone, "aarch64_sve_pext_x2", [IsStreamingCompatible], [ImmCheck<1, ImmCheck0_1>]>; +} -def SVPSEL_COUNT_ALIAS_B : SInst<"svpsel_lane_c8", "}}Pm", "Pc", MergeNone, "", [], []>; -def SVPSEL_COUNT_ALIAS_H : SInst<"svpsel_lane_c16", "}}Pm", "Ps", MergeNone, "", [], []>; -def SVPSEL_COUNT_ALIAS_S : SInst<"svpsel_lane_c32", "}}Pm", "Pi", MergeNone, "", [], []>; -def SVPSEL_COUNT_ALIAS_D : SInst<"svpsel_lane_c64", "}}Pm", "Pl", MergeNone, "", [], []>; +let TargetGuard = "sve2p1" in { +def SVFCLAMP : SInst<"svclamp[_{d}]", "dddd", "hfd", MergeNone, "aarch64_sve_fclamp", [], []>; def SVWHILEGE_COUNT : SInst<"svwhilege_{d}", "}lli", "QcQsQiQl", MergeNone, "aarch64_sve_whilege_{d}", [IsOverloadNone], [ImmCheck<2, ImmCheck2_4_Mul2>]>; def SVWHILEGT_COUNT : SInst<"svwhilegt_{d}", "}lli", "QcQsQiQl", MergeNone, "aarch64_sve_whilegt_{d}", [IsOverloadNone], [ImmCheck<2, ImmCheck2_4_Mul2>]>; @@ -2035,16 +2054,17 @@ let TargetGuard = "sve2p1" in { def SVSCLAMP : SInst<"svclamp[_{d}]", "dddd", "csil", MergeNone, "aarch64_sve_sclamp", [], []>; def SVUCLAMP : SInst<"svclamp[_{d}]", "dddd", "UcUsUiUl", MergeNone, "aarch64_sve_uclamp", [], []>; -def SVPSEL_B : SInst<"svpsel_lane_b8", "PPPm", "Pc", MergeNone, "", [], []>; -def SVPSEL_H : SInst<"svpsel_lane_b16", "PPPm", "Ps", MergeNone, "", [], []>; -def SVPSEL_S : SInst<"svpsel_lane_b32", "PPPm", "Pi", MergeNone, "", [], []>; -def SVPSEL_D : SInst<"svpsel_lane_b64", "PPPm", "Pl", MergeNone, "", [], []>; - def SVCNTP_COUNT : SInst<"svcntp_{d}", "n}i", "QcQsQiQl", MergeNone, "aarch64_sve_cntp_{d}", [IsOverloadNone], [ImmCheck<1, ImmCheck2_4_Mul2>]>; defm SVREVD : SInstZPZ<"svrevd", "csilUcUsUiUl", "aarch64_sve_revd">; } +let TargetGuard = "sve2p1|sme2" in { + //FIXME: Replace IsStreamingCompatible with IsStreamingOrHasSVE2p1 when available + def SVPTRUE_COUNT : SInst<"svptrue_{d}", "}v", "QcQsQiQl", MergeNone, "aarch64_sve_ptrue_{d}", [IsOverloadNone, IsStreamingCompatible], []>; + + def SVPFALSE_COUNT_ALIAS : SInst<"svpfalse_c", "}v", "", MergeNone, "", [IsOverloadNone, IsStreamingCompatible]>; +} let TargetGuard = "sve2p1,b16b16" in { defm SVMUL_BF : SInstZPZZ<"svmul", "b", "aarch64_sve_fmul", "aarch64_sve_fmul_u">; @@ -2130,6 +2150,24 @@ let TargetGuard = "sme2" in { def SVURSHL_X2 : SInst<"svrshl[_{d}_x2]", "222", "UcUsUiUl", MergeNone, "aarch64_sve_urshl_x2", [IsStreaming], []>; def SVSRSHL_X4 : SInst<"svrshl[_{d}_x4]", "444", "csil", MergeNone, "aarch64_sve_srshl_x4", [IsStreaming], []>; def SVURSHL_X4 : SInst<"svrshl[_{d}_x4]", "444", "UcUsUiUl", MergeNone, "aarch64_sve_urshl_x4", [IsStreaming], []>; + + def SVQRSHRN_X4 : SInst<"svqrshrn[_n]_{0}[_{d}_x4]", "q4i", "il", MergeNone, "aarch64_sve_sqrshrn_x4", [IsStreaming], [ImmCheck<1, ImmCheckShiftRight, 0>]>; + def SVUQRSHRN_X4 : SInst<"svqrshrn[_n]_{0}[_{d}_x4]", "b4i", "UiUl", MergeNone, "aarch64_sve_uqrshrn_x4", [IsStreaming], [ImmCheck<1, ImmCheckShiftRight, 0>]>; + + // SQRSHR / UQRSHR + def SVQRSHR_X2 : SInst<"svqrshr[_n]_{0}[_{d}_x2]", "h2i", "i", MergeNone, "aarch64_sve_sqrshr_x2", [IsStreaming], [ImmCheck<1, ImmCheck1_16>]>; + def SVUQRSHR_X2 : SInst<"svqrshr[_n]_{0}[_{d}_x2]", "e2i", "Ui", MergeNone, "aarch64_sve_uqrshr_x2", [IsStreaming], [ImmCheck<1, ImmCheck1_16>]>; + def SVQRSHR_X4 : SInst<"svqrshr[_n]_{0}[_{d}_x4]", "q4i", "il", MergeNone, "aarch64_sve_sqrshr_x4", [IsStreaming], [ImmCheck<1, ImmCheckShiftRight, 0>]>; + def SVUQRSHR_X4 : SInst<"svqrshr[_n]_{0}[_{d}_x4]", "b4i", "UiUl", MergeNone, "aarch64_sve_uqrshr_x4", [IsStreaming], [ImmCheck<1, ImmCheckShiftRight, 0>]>; + + // SQRSHRU + def SVSQRSHRU_X2 : SInst<"svqrshru[_n]_{0}[_{d}_x2]", "e2i", "i", MergeNone, "aarch64_sve_sqrshru_x2", [IsStreaming], [ImmCheck<1, ImmCheck1_16>]>; + def SVSQRSHRU_X4 : SInst<"svqrshru[_n]_{0}[_{d}_x4]", "b4i", "il", MergeNone, "aarch64_sve_sqrshru_x4", [IsStreaming], [ImmCheck<1, ImmCheckShiftRight, 0>]>; + + def SVSQRSHRUN_X4 : SInst<"svqrshrun[_n]_{0}[_{d}_x4]", "b4i", "il", MergeNone, "aarch64_sve_sqrshrun_x4", [IsStreaming], [ImmCheck<1, ImmCheckShiftRight, 0>]>; + + def REINTERPRET_SVBOOL_TO_SVCOUNT : Inst<"svreinterpret[_c]", "}P", "Pc", MergeNone, "", [IsStreamingCompatible], []>; + def REINTERPRET_SVCOUNT_TO_SVBOOL : Inst<"svreinterpret[_b]", "P}", "Pc", MergeNone, "", [IsStreamingCompatible], []>; } let TargetGuard = "sve2p1" in { @@ -2164,3 +2202,74 @@ let TargetGuard = "sve2p1" in { defm SVPMOV_TO_VEC_LANE_S : PMOV_TO_VEC<"svpmov", "iUi", "aarch64_sve_pmov_to_vector_lane", [], ImmCheck1_3>; defm SVPMOV_TO_VEC_LANE_D : PMOV_TO_VEC<"svpmov", "lUl", "aarch64_sve_pmov_to_vector_lane" ,[], ImmCheck1_7>; } + +// +// Multi-vector convert to/from floating-point. +// +let TargetGuard = "sme2" in { + def SVCVT_F16_X2 : SInst<"svcvt_f16[_f32_x2]", "e2", "f", MergeNone, "aarch64_sve_fcvt_x2", [IsStreaming],[]>; + def SVCVT_BF16_X2 : SInst<"svcvt_bf16[_f32_x2]", "$2", "f", MergeNone, "aarch64_sve_bfcvt_x2", [IsOverloadNone, IsStreaming],[]>; + + def SVCVT_F32_U32_X2 : SInst<"svcvt_{d}[_u32_x2]", "2.d2.u", "f", MergeNone, "aarch64_sve_fcvtu_x2", [IsStreaming], []>; + def SVCVT_U32_F32_X2 : SInst<"svcvt_u32[_{d}_x2]", "2.u2.d", "f", MergeNone, "aarch64_sve_ucvtf_x2", [IsStreaming], []>; + def SVCVT_F32_S32_X2 : SInst<"svcvt_{d}[_s32_x2]", "2.d2.x", "f", MergeNone, "aarch64_sve_fcvts_x2", [IsStreaming], []>; + def SVCVT_S32_F32_X2 : SInst<"svcvt_s32[_{d}_x2]", "2.x2.d", "f", MergeNone, "aarch64_sve_scvtf_x2", [IsStreaming], []>; + + def SVCVT_F32_U32_X4 : SInst<"svcvt_{d}[_u32_x4]", "4.d4.u", "f", MergeNone, "aarch64_sve_fcvtu_x4", [IsStreaming], []>; + def SVCVT_U32_F32_X4 : SInst<"svcvt_u32[_{d}_x4]", "4.u4.d", "f", MergeNone, "aarch64_sve_ucvtf_x4", [IsStreaming], []>; + def SVCVT_F32_S32_X4 : SInst<"svcvt_{d}[_s32_x4]", "4.d4.x", "f", MergeNone, "aarch64_sve_fcvts_x4", [IsStreaming], []>; + def SVCVT_S32_F32_X4 : SInst<"svcvt_s32[_{d}_x4]", "4.x4.d", "f", MergeNone, "aarch64_sve_scvtf_x4", [IsStreaming], []>; +} + +// +// Multi-vector floating-point convert from single-precision to interleaved half-precision/BFloat16 +// +let TargetGuard = "sme2" in { + def SVCVTN_F16_X2 : SInst<"svcvtn_f16[_f32_x2]", "e2", "f", MergeNone, "aarch64_sve_fcvtn_x2", [IsStreaming],[]>; + def SVCVTN_BF16_X2 : SInst<"svcvtn_bf16[_f32_x2]", "$2", "f", MergeNone, "aarch64_sve_bfcvtn_x2", [IsOverloadNone, IsStreaming],[]>; +} + +// +// Multi-vector saturating extract narrow +// +let TargetGuard = "sme2" in { + def SVQCVT_S16_S32_X2 : SInst<"svqcvt_s16[_{d}_x2]", "h2.d", "i", MergeNone, "aarch64_sve_sqcvt_x2", [IsStreaming], []>; + def SVQCVT_U16_U32_X2 : SInst<"svqcvt_u16[_{d}_x2]", "e2.d", "Ui", MergeNone, "aarch64_sve_uqcvt_x2", [IsStreaming], []>; + def SVQCVT_U16_S32_X2 : SInst<"svqcvt_u16[_{d}_x2]", "e2.d", "i", MergeNone, "aarch64_sve_sqcvtu_x2", [IsStreaming], []>; + + def SVQCVT_S8_S32_X4 : SInst<"svqcvt_s8[_{d}_x4]", "q4.d", "i", MergeNone, "aarch64_sve_sqcvt_x4", [IsStreaming], []>; + def SVQCVT_U8_U32_X4 : SInst<"svqcvt_u8[_{d}_x4]", "b4.d", "Ui", MergeNone, "aarch64_sve_uqcvt_x4", [IsStreaming], []>; + def SVQCVT_U8_S32_X4 : SInst<"svqcvt_u8[_{d}_x4]", "b4.d", "i", MergeNone, "aarch64_sve_sqcvtu_x4", [IsStreaming], []>; + + def SVQCVT_S16_S64_X4 : SInst<"svqcvt_s16[_{d}_x4]", "q4.d", "l", MergeNone, "aarch64_sve_sqcvt_x4", [IsStreaming], []>; + def SVQCVT_U16_U64_X4 : SInst<"svqcvt_u16[_{d}_x4]", "b4.d", "Ul", MergeNone, "aarch64_sve_uqcvt_x4", [IsStreaming], []>; + def SVQCVT_U16_S64_X4 : SInst<"svqcvt_u16[_{d}_x4]", "b4.d", "l", MergeNone, "aarch64_sve_sqcvtu_x4", [IsStreaming], []>; +} + +// +// Multi-vector saturating extract narrow and interleave +// +let TargetGuard = "sme2" in { + def SVQCVTN_S16_S32_X2 : SInst<"svqcvtn_s16[_{d}_x2]", "h2.d", "i", MergeNone, "aarch64_sve_sqcvtn_x2", [IsStreamingCompatible], []>; + def SVQCVTN_U16_U32_X2 : SInst<"svqcvtn_u16[_{d}_x2]", "e2.d", "Ui", MergeNone, "aarch64_sve_uqcvtn_x2", [IsStreamingCompatible], []>; + def SVQCVTN_U16_S32_X2 : SInst<"svqcvtn_u16[_{d}_x2]", "e2.d", "i", MergeNone, "aarch64_sve_sqcvtun_x2", [IsStreamingCompatible], []>; + + def SVQCVTN_S8_S32_X4 : SInst<"svqcvtn_s8[_{d}_x4]", "q4.d", "i", MergeNone, "aarch64_sve_sqcvtn_x4", [IsStreaming], []>; + def SVQCVTN_U8_U32_X4 : SInst<"svqcvtn_u8[_{d}_x4]", "b4.d", "Ui", MergeNone, "aarch64_sve_uqcvtn_x4", [IsStreaming], []>; + def SVQCVTN_U8_S32_X4 : SInst<"svqcvtn_u8[_{d}_x4]", "b4.d", "i", MergeNone, "aarch64_sve_sqcvtun_x4", [IsStreaming], []>; + + def SVQCVTN_S16_S64_X4 : SInst<"svqcvtn_s16[_{d}_x4]", "q4.d", "l", MergeNone, "aarch64_sve_sqcvtn_x4", [IsStreaming], []>; + def SVQCVTN_U16_U64_X4 : SInst<"svqcvtn_u16[_{d}_x4]", "b4.d", "Ul", MergeNone, "aarch64_sve_uqcvtn_x4", [IsStreaming], []>; + def SVQCVTN_U16_S64_X4 : SInst<"svqcvtn_u16[_{d}_x4]", "b4.d", "l", MergeNone, "aarch64_sve_sqcvtun_x4", [IsStreaming], []>; +} + +// +// Multi-vector unpack +// + +let TargetGuard = "sme2" in { + def SVSUNPK_X2 : SInst<"svunpk_{d}[_{1}_x2]", "2h", "sil", MergeNone, "aarch64_sve_sunpk_x2", [IsStreaming], []>; + def SVUUNPK_X2 : SInst<"svunpk_{d}[_{1}_x2]", "2h", "UsUiUl", MergeNone, "aarch64_sve_uunpk_x2", [IsStreaming], []>; + def SVSUNPK_X4 : SInst<"svunpk_{d}[_{3}_x4]", "42.h", "sil", MergeNone, "aarch64_sve_sunpk_x4", [IsStreaming], []>; + def SVUUNPK_X4 : SInst<"svunpk_{d}[_{3}_x4]", "42.h", "UsUiUl", MergeNone, "aarch64_sve_uunpk_x4", [IsStreaming], []>; +} diff --git a/clang/include/clang/Basic/arm_sve_sme_incl.td b/clang/include/clang/Basic/arm_sve_sme_incl.td index 21dac067ab66e615354da7701e08162bc06f886e..040ce95a57de3dc43385269897de2e0816c5da40 100644 --- a/clang/include/clang/Basic/arm_sve_sme_incl.td +++ b/clang/include/clang/Basic/arm_sve_sme_incl.td @@ -93,6 +93,7 @@ // m: uint32_t // n: uint64_t +// [: svuint8_t // t: svint32_t // z: svuint32_t // g: svuint64_t diff --git a/clang/include/clang/Driver/Multilib.h b/clang/include/clang/Driver/Multilib.h index 6a9533e6dd831f15ffd5acf3d5db6d4a50692adb..9a2cc9bb1ba134a1f1a47f690df1b6554bdc3f8d 100644 --- a/clang/include/clang/Driver/Multilib.h +++ b/clang/include/clang/Driver/Multilib.h @@ -130,7 +130,7 @@ public: /// Select compatible variants, \returns false if none are compatible bool select(const Multilib::flags_list &Flags, - llvm::SmallVector &) const; + llvm::SmallVectorImpl &) const; unsigned size() const { return Multilibs.size(); } diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 1d04e4f6e7e6d96af64d8a0ca78b35a7d16fd1b5..25c76cf2ad2c84ad15c2ac6a39390043477afd91 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -994,7 +994,7 @@ def all__load : Flag<["-"], "all_load">; def allowable__client : Separate<["-"], "allowable_client">; def ansi : Flag<["-", "--"], "ansi">, Group; def arch__errors__fatal : Flag<["-"], "arch_errors_fatal">; -def arch : Separate<["-"], "arch">, Flags<[NoXarchOption]>; +def arch : Separate<["-"], "arch">, Flags<[NoXarchOption,TargetSpecific]>; def arch__only : Separate<["-"], "arch_only">; def autocomplete : Joined<["--"], "autocomplete=">; def bind__at__load : Flag<["-"], "bind_at_load">; @@ -1010,6 +1010,30 @@ defm offload_uniform_block : BoolFOption<"offload-uniform-block", NegFlag, BothFlags<[], [ClangOption], " that kernels are launched with uniform block sizes (default true for CUDA/HIP and false otherwise)">>; +def fcx_limited_range : Joined<["-"], "fcx-limited-range">, + Group, Visibility<[ClangOption, CC1Option]>, + HelpText<"Basic algebraic expansions of complex arithmetic operations " + "involving are enabled.">; + +def fno_cx_limited_range : Joined<["-"], "fno-cx-limited-range">, + Group, Visibility<[ClangOption, CC1Option]>, + HelpText<"Basic algebraic expansions of complex arithmetic operations " + "involving are disabled.">; + +def fcx_fortran_rules : Joined<["-"], "fcx-fortran-rules">, + Group, Visibility<[ClangOption, CC1Option]>, + HelpText<"Range reduction is enabled for complex arithmetic operations.">; + +def fno_cx_fortran_rules : Joined<["-"], "fno-cx-fortran-rules">, + Group, Visibility<[ClangOption, CC1Option]>, + HelpText<"Range reduction is disabled for complex arithmetic operations.">; + +def complex_range_EQ : Joined<["-"], "complex-range=">, Group, + Visibility<[CC1Option]>, + Values<"full,limited,fortran">, NormalizedValuesScope<"LangOptions">, + NormalizedValues<["CX_Full", "CX_Limited", "CX_Fortran"]>, + MarshallingInfoEnum, "CX_Full">; + // OpenCL-only Options def cl_opt_disable : Flag<["-"], "cl-opt-disable">, Group, Visibility<[ClangOption, CC1Option]>, @@ -1818,6 +1842,9 @@ def fcomment_block_commands : CommaJoined<["-"], "fcomment-block-commands=">, Gr Visibility<[ClangOption, CC1Option]>, HelpText<"Treat each comma separated argument in as a documentation comment block command">, MetaVarName<"">, MarshallingInfoStringVector>; +defm define_target_os_macros : OptInCC1FFlag<"define-target-os-macros", + "Enable", "Disable", " predefined target OS macros", + [ClangOption, CC1Option]>; def fparse_all_comments : Flag<["-"], "fparse-all-comments">, Group, Visibility<[ClangOption, CC1Option]>, MarshallingInfoFlag>; @@ -6344,9 +6371,6 @@ defm stack_arrays : BoolOptionWithoutMarshalling<"f", "stack-arrays", defm loop_versioning : BoolOptionWithoutMarshalling<"f", "version-loops-for-stride", PosFlag, NegFlag>; -defm alias_analysis : BoolOptionWithoutMarshalling<"f", "alias-analysis", - PosFlag, - NegFlag>; } // let Visibility = [FC1Option, FlangOption] def J : JoinedOrSeparate<["-"], "J">, @@ -6354,6 +6378,12 @@ def J : JoinedOrSeparate<["-"], "J">, Group, Alias; +let Visibility = [FlangOption] in { +def no_fortran_main : Flag<["-"], "fno-fortran-main">, + Visibility<[FlangOption]>, Group, + HelpText<"Do not include Fortran_main.a (provided by Flang) when linking">; +} // let Visibility = [ FlangOption ] + //===----------------------------------------------------------------------===// // FC1 Options //===----------------------------------------------------------------------===// diff --git a/clang/include/clang/Frontend/FrontendActions.h b/clang/include/clang/Frontend/FrontendActions.h index 3940e00eeb8dba7924a04ae6e20a2a05daa29534..fcce31ac0590ff678adec7999a7cb5d0c3552cfd 100644 --- a/clang/include/clang/Frontend/FrontendActions.h +++ b/clang/include/clang/Frontend/FrontendActions.h @@ -151,6 +151,9 @@ class GenerateModuleInterfaceAction : public GenerateModuleAction { private: bool BeginSourceFileAction(CompilerInstance &CI) override; + std::unique_ptr CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; + std::unique_ptr CreateOutputFile(CompilerInstance &CI, StringRef InFile) override; }; diff --git a/clang/include/clang/IndexSerialization/SerializablePathCollection.h b/clang/include/clang/IndexSerialization/SerializablePathCollection.h index 06948db6fc95f2a97eee547b2d75eecc08461a13..6337a81196688f04523961f3da46de094f6c1fbd 100644 --- a/clang/include/clang/IndexSerialization/SerializablePathCollection.h +++ b/clang/include/clang/IndexSerialization/SerializablePathCollection.h @@ -110,7 +110,7 @@ public: /// Stores path to \p FE if it hasn't been stored yet. /// \returns index to array exposed by getPathsBuffer(). - size_t tryStoreFilePath(const clang::FileEntry &FE); + size_t tryStoreFilePath(FileEntryRef FE); private: /// Stores \p Path if it is non-empty. diff --git a/clang/include/clang/Lex/HeaderSearch.h b/clang/include/clang/Lex/HeaderSearch.h index a100598c80155fa5d5259bcd3601b0890c032744..a2c33842924b101b81b724decde96438be1bdd36 100644 --- a/clang/include/clang/Lex/HeaderSearch.h +++ b/clang/include/clang/Lex/HeaderSearch.h @@ -247,16 +247,13 @@ class HeaderSearch { /// \#include search path information. Requests for \#include "x" search the /// directory of the \#including file first, then each directory in SearchDirs /// consecutively. Requests for search the current dir first, then each - /// directory in SearchDirs, starting at AngledDirIdx, consecutively. If - /// NoCurDirSearch is true, then the check for the file in the current - /// directory is suppressed. + /// directory in SearchDirs, starting at AngledDirIdx, consecutively. std::vector SearchDirs; /// Whether the DirectoryLookup at the corresponding index in SearchDirs has /// been successfully used to lookup a file. std::vector SearchDirsUsage; unsigned AngledDirIdx = 0; unsigned SystemDirIdx = 0; - bool NoCurDirSearch = false; /// Maps HeaderMap keys to SearchDir indices. When HeaderMaps are used /// heavily, SearchDirs can start with thousands of HeaderMaps, so this Index @@ -373,7 +370,7 @@ public: /// Interface for setting the file search paths. void SetSearchPaths(std::vector dirs, unsigned angledDirIdx, - unsigned systemDirIdx, bool noCurDirSearch, + unsigned systemDirIdx, llvm::DenseMap searchDirToHSEntry); /// Add an additional search path. diff --git a/clang/include/clang/Lex/ModuleMap.h b/clang/include/clang/Lex/ModuleMap.h index 32e7e8f899e502cf6953f094121b16e91dc71177..867cb6eab42f2d7bf04bfa8e32c5e073170f7816 100644 --- a/clang/include/clang/Lex/ModuleMap.h +++ b/clang/include/clang/Lex/ModuleMap.h @@ -82,7 +82,7 @@ class ModuleMap { /// The directory used for Clang-supplied, builtin include headers, /// such as "stdint.h". - OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr BuiltinIncludeDir; + OptionalDirectoryEntryRef BuiltinIncludeDir; /// Language options used to parse the module map itself. /// @@ -408,16 +408,12 @@ public: /// Set the target information. void setTarget(const TargetInfo &Target); - /// Set the directory that contains Clang-supplied include - /// files, such as our stdarg.h or tgmath.h. - void setBuiltinIncludeDir(DirectoryEntryRef Dir) { - BuiltinIncludeDir = Dir; - } + /// Set the directory that contains Clang-supplied include files, such as our + /// stdarg.h or tgmath.h. + void setBuiltinIncludeDir(DirectoryEntryRef Dir) { BuiltinIncludeDir = Dir; } /// Get the directory that contains Clang-supplied include files. - OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr getBuiltinDir() const { - return BuiltinIncludeDir; - } + OptionalDirectoryEntryRef getBuiltinDir() const { return BuiltinIncludeDir; } /// Is this a compiler builtin header? bool isBuiltinHeader(FileEntryRef File); diff --git a/clang/include/clang/Lex/PPCallbacks.h b/clang/include/clang/Lex/PPCallbacks.h index 94f96cf9c512541b5670c906075c38a9b94f89cc..e3942af7be2803026c3243d1a6b5bd9e5721c90a 100644 --- a/clang/include/clang/Lex/PPCallbacks.h +++ b/clang/include/clang/Lex/PPCallbacks.h @@ -22,11 +22,11 @@ #include "llvm/ADT/StringRef.h" namespace clang { - class Token; - class IdentifierInfo; - class MacroDefinition; - class MacroDirective; - class MacroArgs; +class Token; +class IdentifierInfo; +class MacroDefinition; +class MacroDirective; +class MacroArgs; /// This interface provides a way to observe the actions of the /// preprocessor as it does its thing. diff --git a/clang/include/clang/Lex/PreprocessorLexer.h b/clang/include/clang/Lex/PreprocessorLexer.h index eebaad7d50db3b1759c7ccb43b3b00d25e74e106..d71fe708ab20a20a7bd7928e474e835d5031076b 100644 --- a/clang/include/clang/Lex/PreprocessorLexer.h +++ b/clang/include/clang/Lex/PreprocessorLexer.h @@ -157,7 +157,7 @@ public: /// getFileEntry - Return the FileEntry corresponding to this FileID. Like /// getFileID(), this only works for lexers with attached preprocessors. - OptionalFileEntryRefDegradesToFileEntryPtr getFileEntry() const; + OptionalFileEntryRef getFileEntry() const; /// Iterator that traverses the current stack of preprocessor /// conditional directives (\#if/\#ifdef/\#ifndef). diff --git a/clang/include/clang/Lex/PreprocessorOptions.h b/clang/include/clang/Lex/PreprocessorOptions.h index 058194bcde72e51a8003b04ec4a48ac5df5e8df0..f841e4a028df50d3030a21145fa8d9af8bb047a3 100644 --- a/clang/include/clang/Lex/PreprocessorOptions.h +++ b/clang/include/clang/Lex/PreprocessorOptions.h @@ -76,6 +76,9 @@ public: /// predefines. bool UsePredefines = true; + /// Indicates whether to predefine target OS macros. + bool DefineTargetOSMacros = false; + /// Whether we should maintain a detailed record of all macro /// definitions and expansions. bool DetailedRecord = false; diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index ca29ce46873e8a4a9fef861fb5c6a0548a934385..2dbe090bd0932fc5afe59b25ffaf4f5910f2de70 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -769,6 +769,10 @@ private: /// #pragma STDC FENV_ROUND... void HandlePragmaFEnvRound(); + /// Handle the annotation token produced for + /// #pragma STDC CX_LIMITED_RANGE... + void HandlePragmaCXLimitedRange(); + /// Handle the annotation token produced for /// #pragma float_control void HandlePragmaFloatControl(); @@ -3538,7 +3542,13 @@ public: private: void ParseOpenACCDirective(); - ExprResult ParseOpenACCRoutineName(); + /// Helper that parses an ID Expression based on the language options. + ExprResult ParseOpenACCIDExpression(); + /// Parses the variable list for the `cache` construct. + void ParseOpenACCCacheVarList(); + /// Parses a single variable in a variable list for the 'cache' construct. + bool ParseOpenACCCacheVar(); + bool ParseOpenACCWaitArgument(); private: //===--------------------------------------------------------------------===// diff --git a/clang/include/clang/Sema/HLSLExternalSemaSource.h b/clang/include/clang/Sema/HLSLExternalSemaSource.h index 4b6bc96f72e225c8e3d1790359294f3715c0e8f4..c0bfff327139f8c6a3b80a009ca8ddd7159622d6 100644 --- a/clang/include/clang/Sema/HLSLExternalSemaSource.h +++ b/clang/include/clang/Sema/HLSLExternalSemaSource.h @@ -30,9 +30,9 @@ class HLSLExternalSemaSource : public ExternalSemaSource { void defineHLSLVectorAlias(); void defineTrivialHLSLTypes(); - void forwardDeclareHLSLTypes(); + void defineHLSLTypesWithForwardDeclarations(); - void completeBufferType(CXXRecordDecl *Record); + void onCompletion(CXXRecordDecl *Record, CompletionFunction Fn); public: ~HLSLExternalSemaSource() override; diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index e745c01ae0ae0f830a55ace3d33712b903ad1ad3..1d7b4c729ce84e0968f78d5250c70438e86e927a 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -7311,8 +7311,7 @@ public: /// ActOnLambdaExpr - This is called when the body of a lambda expression /// was successfully completed. - ExprResult ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body, - Scope *CurScope); + ExprResult ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body); /// Does copying/destroying the captured variable have side effects? bool CaptureHasSideEffects(const sema::Capture &From); @@ -8561,6 +8560,10 @@ public: TemplateParameterList *Params, TemplateArgumentLoc &Arg); + void NoteTemplateLocation(const NamedDecl &Decl, + std::optional ParamRange = {}); + void NoteTemplateParameterLocation(const NamedDecl &Decl); + ExprResult BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg, QualType ParamType, @@ -11019,6 +11022,11 @@ public: /// \#pragma STDC FENV_ACCESS void ActOnPragmaFEnvAccess(SourceLocation Loc, bool IsEnabled); + /// ActOnPragmaCXLimitedRange - Called on well formed + /// \#pragma STDC CX_LIMITED_RANGE + void ActOnPragmaCXLimitedRange(SourceLocation Loc, + LangOptions::ComplexRangeKind Range); + /// Called on well formed '\#pragma clang fp' that has option 'exceptions'. void ActOnPragmaFPExceptions(SourceLocation Loc, LangOptions::FPExceptionModeKind); @@ -13841,6 +13849,8 @@ private: CallExpr *TheCall); bool CheckMVEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); bool CheckSVEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); + bool ParseSVEImmChecks(CallExpr *TheCall, + SmallVector, 3> &ImmChecks); bool CheckCDEBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall); bool CheckARMCoprocessorImmediate(const TargetInfo &TI, const Expr *CoprocArg, diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h index 7eefdca6815cdadb81a8fd34bbdae8c2d0760800..9bb89ec9410911afb362830ffdd35ff1059af899 100644 --- a/clang/include/clang/Serialization/ASTReader.h +++ b/clang/include/clang/Serialization/ASTReader.h @@ -2415,12 +2415,7 @@ public: BitsUnpacker(BitsUnpacker &&) = delete; BitsUnpacker operator=(const BitsUnpacker &) = delete; BitsUnpacker operator=(BitsUnpacker &&) = delete; - ~BitsUnpacker() { -#ifndef NDEBUG - while (isValid()) - assert(!getNextBit() && "There are unprocessed bits!"); -#endif - } + ~BitsUnpacker() = default; void updateValue(uint32_t V) { Value = V; diff --git a/clang/include/clang/Serialization/ModuleFile.h b/clang/include/clang/Serialization/ModuleFile.h index 48be8676cc26a4cc4a1e47e9a843dd6c655cf72a..9a14129d72ff33a7cafaf1082c33a9869af8e8f9 100644 --- a/clang/include/clang/Serialization/ModuleFile.h +++ b/clang/include/clang/Serialization/ModuleFile.h @@ -104,7 +104,7 @@ public: return File; } - OptionalFileEntryRefDegradesToFileEntryPtr getFile() const { + OptionalFileEntryRef getFile() const { if (auto *P = Val.getPointer()) return FileEntryRef(*P); return std::nullopt; @@ -123,8 +123,8 @@ public: /// other modules. class ModuleFile { public: - ModuleFile(ModuleKind Kind, unsigned Generation) - : Kind(Kind), Generation(Generation) {} + ModuleFile(ModuleKind Kind, FileEntryRef File, unsigned Generation) + : Kind(Kind), File(File), Generation(Generation) {} ~ModuleFile(); // === General information === @@ -176,7 +176,7 @@ public: bool DidReadTopLevelSubmodule = false; /// The file entry for the module file. - OptionalFileEntryRefDegradesToFileEntryPtr File; + FileEntryRef File; /// The signature of the module file, which may be used instead of the size /// and modification time to identify this particular file. diff --git a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td index 1d224786372e823a88e0caf66d83a7fc9bdfff27..e7774e5a9392d23670db293c23f7adddcf0ba9d3 100644 --- a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td +++ b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td @@ -36,6 +36,7 @@ def CoreAlpha : Package<"core">, ParentPackage; // Note: OptIn is *not* intended for checkers that are too noisy to be on by // default. Such checkers belong in the alpha package. def OptIn : Package<"optin">; +def CoreOptIn : Package<"core">, ParentPackage; // In the Portability package reside checkers for finding code that relies on // implementation-defined behavior. Such checks are wanted for cross-platform @@ -439,6 +440,18 @@ def UndefinedNewArraySizeChecker : Checker<"NewArraySize">, } // end "core.uninitialized" +//===----------------------------------------------------------------------===// +// Optin checkers for core language features +//===----------------------------------------------------------------------===// + +let ParentPackage = CoreOptIn in { + +def EnumCastOutOfRangeChecker : Checker<"EnumCastOutOfRange">, + HelpText<"Check integer to enumeration casts for out of range values">, + Documentation; + +} // end "optin.core" + //===----------------------------------------------------------------------===// // Unix API checkers. //===----------------------------------------------------------------------===// @@ -774,10 +787,6 @@ def DeleteWithNonVirtualDtorChecker : Checker<"DeleteWithNonVirtualDtor">, "destructor in their base class">, Documentation; -def EnumCastOutOfRangeChecker : Checker<"EnumCastOutOfRange">, - HelpText<"Check integer to enumeration casts for out of range values">, - Documentation; - def IteratorModeling : Checker<"IteratorModeling">, HelpText<"Models iterators of C++ containers">, Dependencies<[ContainerModeling]>, diff --git a/clang/include/module.modulemap b/clang/include/module.modulemap index 7dbb7cf02b4f82c19f428348ff9b2f302b4fa294..52395ee9b0fc9ffca68550876c54d846941f3ebb 100644 --- a/clang/include/module.modulemap +++ b/clang/include/module.modulemap @@ -68,6 +68,7 @@ module Clang_Basic { textual header "clang/Basic/BuiltinsX86_64.def" textual header "clang/Basic/BuiltinsXCore.def" textual header "clang/Basic/CodeGenOptions.def" + textual header "clang/Basic/DebugOptions.def" textual header "clang/Basic/DiagnosticOptions.def" textual header "clang/Basic/Features.def" textual header "clang/Basic/FPOptions.def" diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index c5c2edf1bfe3aba2337aa4a5afa57bf54f2cb476..527ea6042daa0344237ed90e46e8729520db2c3b 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -4150,6 +4150,7 @@ FunctionDecl::setFunctionTemplateSpecialization(ASTContext &C, assert(TSK != TSK_Undeclared && "Must specify the type of function template specialization"); assert((TemplateOrSpecialization.isNull() || + getFriendObjectKind() != FOK_None || TSK == TSK_ExplicitSpecialization) && "Member specialization must be an explicit specialization"); FunctionTemplateSpecializationInfo *Info = diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 55c6b732b7081f40c1584d14fb05949873978712..b125fc676da8419e737761b7db2a711df54adb46 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -4887,6 +4887,7 @@ unsigned AtomicExpr::getNumSubExprs(AtomicOp Op) { case AO__atomic_load_n: return 2; + case AO__scoped_atomic_load_n: case AO__opencl_atomic_load: case AO__hip_atomic_load: case AO__c11_atomic_store: @@ -4921,6 +4922,26 @@ unsigned AtomicExpr::getNumSubExprs(AtomicOp Op) { case AO__atomic_fetch_max: return 3; + case AO__scoped_atomic_load: + case AO__scoped_atomic_store: + case AO__scoped_atomic_store_n: + case AO__scoped_atomic_fetch_add: + case AO__scoped_atomic_fetch_sub: + case AO__scoped_atomic_fetch_and: + case AO__scoped_atomic_fetch_or: + case AO__scoped_atomic_fetch_xor: + case AO__scoped_atomic_fetch_nand: + case AO__scoped_atomic_add_fetch: + case AO__scoped_atomic_sub_fetch: + case AO__scoped_atomic_and_fetch: + case AO__scoped_atomic_or_fetch: + case AO__scoped_atomic_xor_fetch: + case AO__scoped_atomic_nand_fetch: + case AO__scoped_atomic_min_fetch: + case AO__scoped_atomic_max_fetch: + case AO__scoped_atomic_fetch_min: + case AO__scoped_atomic_fetch_max: + case AO__scoped_atomic_exchange_n: case AO__hip_atomic_exchange: case AO__hip_atomic_fetch_add: case AO__hip_atomic_fetch_sub: @@ -4942,6 +4963,7 @@ unsigned AtomicExpr::getNumSubExprs(AtomicOp Op) { case AO__atomic_exchange: return 4; + case AO__scoped_atomic_exchange: case AO__c11_atomic_compare_exchange_strong: case AO__c11_atomic_compare_exchange_weak: return 5; @@ -4952,6 +4974,10 @@ unsigned AtomicExpr::getNumSubExprs(AtomicOp Op) { case AO__atomic_compare_exchange: case AO__atomic_compare_exchange_n: return 6; + + case AO__scoped_atomic_compare_exchange: + case AO__scoped_atomic_compare_exchange_n: + return 7; } llvm_unreachable("unknown atomic op"); } diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 986302e1fd225f2194880f02c49a5c5b2715443f..f6aeee1a4e935d0f42caf5e0504bf8bc840e4bce 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -641,6 +641,10 @@ namespace { return false; } + /// Whether we're in a context where [[msvc::constexpr]] evaluation is + /// permitted. See MSConstexprDocs for description of permitted contexts. + bool CanEvalMSConstexpr = false; + private: APValue &createLocal(APValue::LValueBase Base, const void *Key, QualType T, ScopeKind Scope); @@ -674,6 +678,19 @@ namespace { private: llvm::TimeTraceScope TimeScope; }; + + /// RAII object used to change the current ability of + /// [[msvc::constexpr]] evaulation. + struct MSConstexprContextRAII { + CallStackFrame &Frame; + bool OldValue; + explicit MSConstexprContextRAII(CallStackFrame &Frame, bool Value) + : Frame(Frame), OldValue(Frame.CanEvalMSConstexpr) { + Frame.CanEvalMSConstexpr = Value; + } + + ~MSConstexprContextRAII() { Frame.CanEvalMSConstexpr = OldValue; } + }; } static bool HandleDestruction(EvalInfo &Info, const Expr *E, @@ -5546,11 +5563,14 @@ static EvalStmtResult EvaluateStmt(StmtResult &Result, EvalInfo &Info, case Stmt::LabelStmtClass: return EvaluateStmt(Result, Info, cast(S)->getSubStmt(), Case); - case Stmt::AttributedStmtClass: - // As a general principle, C++11 attributes can be ignored without - // any semantic impact. - return EvaluateStmt(Result, Info, cast(S)->getSubStmt(), - Case); + case Stmt::AttributedStmtClass: { + const auto *AS = cast(S); + const auto *SS = AS->getSubStmt(); + MSConstexprContextRAII ConstexprContext( + *Info.CurrentCall, hasSpecificAttr(AS->getAttrs()) && + isa(SS)); + return EvaluateStmt(Result, Info, SS, Case); + } case Stmt::CaseStmtClass: case Stmt::DefaultStmtClass: @@ -5621,7 +5641,9 @@ static bool CheckConstexprFunction(EvalInfo &Info, SourceLocation CallLoc, } // Can we evaluate this function call? - if (Definition && Definition->isConstexpr() && Body) + if (Definition && Body && + (Definition->isConstexpr() || (Info.CurrentCall->CanEvalMSConstexpr && + Definition->hasAttr()))) return true; if (Info.getLangOpts().CPlusPlus11) { @@ -8492,14 +8514,24 @@ bool LValueExprEvaluator::VisitVarDecl(const Expr *E, const VarDecl *VD) { return false; if (auto *FD = Info.CurrentCall->LambdaCaptureFields.lookup(VD)) { + const auto *MD = cast(Info.CurrentCall->Callee); + + // Static lambda function call operators can't have captures. We already + // diagnosed this, so bail out here. + if (MD->isStatic()) { + assert(Info.CurrentCall->This == nullptr && + "This should not be set for a static call operator"); + return false; + } + // Start with 'Result' referring to the complete closure object... - if (auto *MD = cast(Info.CurrentCall->Callee); - MD->isExplicitObjectMemberFunction()) { + if (MD->isExplicitObjectMemberFunction()) { APValue *RefValue = Info.getParamSlot(Info.CurrentCall->Arguments, MD->getParamDecl(0)); Result.setFrom(Info.Ctx, *RefValue); } else Result = *Info.CurrentCall->This; + // ... then update it to refer to the field of the closure object // that represents the capture. if (!HandleLValueMember(Info, E, Result, FD)) diff --git a/clang/lib/AST/Interp/ByteCodeEmitter.cpp b/clang/lib/AST/Interp/ByteCodeEmitter.cpp index 89b7708c0c2a12fcdcdfdf84fc0158d1a95b3dfd..045263447cbc9120b3437f867062abf21b1b33cb 100644 --- a/clang/lib/AST/Interp/ByteCodeEmitter.cpp +++ b/clang/lib/AST/Interp/ByteCodeEmitter.cpp @@ -61,6 +61,11 @@ ByteCodeEmitter::compileFunc(const FunctionDecl *FuncDecl) { MD->getParent()->getCaptureFields(LC, LTC); for (auto Cap : LC) { + // Static lambdas cannot have any captures. If this one does, + // it has already been diagnosed and we can only ignore it. + if (MD->isStatic()) + return nullptr; + unsigned Offset = R->getField(Cap.second)->Offset; this->LambdaCaptures[Cap.first] = { Offset, Cap.second->getType()->isReferenceType()}; diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp index f45e8624a7741a536c82564f910a698387a1f8ed..f7f8e6c73d84e21369343ff5eac81602a725480c 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -15,7 +15,6 @@ #include "Function.h" #include "PrimType.h" #include "Program.h" -#include "State.h" using namespace clang; using namespace clang::interp; diff --git a/clang/lib/AST/Interp/Context.cpp b/clang/lib/AST/Interp/Context.cpp index cb96e56fb5e1ad87f521f853e805b4cef877b6c4..4fe6d1173f427e7923a91bb5e944c2cf45e37ed5 100644 --- a/clang/lib/AST/Interp/Context.cpp +++ b/clang/lib/AST/Interp/Context.cpp @@ -168,7 +168,7 @@ bool Context::Run(State &Parent, const Function *Func, APValue &Result) { } // State gets destroyed here, so the Stk.clear() below doesn't accidentally - // remove values the State's destructor might accedd. + // remove values the State's destructor might access. } Stk.clear(); diff --git a/clang/lib/AST/Interp/IntegralAP.h b/clang/lib/AST/Interp/IntegralAP.h index 9019f32e6cef2a34077c5499ef1f30eeb2cf5de3..d5f46409d231d48cbc99f15c199e7c787439de92 100644 --- a/clang/lib/AST/Interp/IntegralAP.h +++ b/clang/lib/AST/Interp/IntegralAP.h @@ -182,17 +182,13 @@ public: } static bool increment(IntegralAP A, IntegralAP *R) { - // FIXME: Implement. - assert(false); - *R = IntegralAP(A.V - 1); - return false; + IntegralAP One(1, A.bitWidth()); + return add(A, One, A.bitWidth() + 1, R); } static bool decrement(IntegralAP A, IntegralAP *R) { - // FIXME: Implement. - assert(false); - *R = IntegralAP(A.V - 1); - return false; + IntegralAP One(1, A.bitWidth()); + return sub(A, One, A.bitWidth() + 1, R); } static bool add(IntegralAP A, IntegralAP B, unsigned OpBits, IntegralAP *R) { diff --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h index 4f7778bdd2ff33371db54d2f9d7c5b444a302e35..a240d74d63425e813859d1248aac5e603de8651a 100644 --- a/clang/lib/AST/Interp/Interp.h +++ b/clang/lib/AST/Interp/Interp.h @@ -1619,7 +1619,11 @@ bool CastFloatingIntegral(InterpState &S, CodePtr OpPC) { QualType Type = E->getType(); S.CCEDiag(E, diag::note_constexpr_overflow) << F.getAPFloat() << Type; - return S.noteUndefinedBehavior(); + if (S.noteUndefinedBehavior()) { + S.Stk.push(T(Result)); + return true; + } + return false; } S.Stk.push(T(Result)); @@ -1822,10 +1826,12 @@ inline bool ArrayElemPtr(InterpState &S, CodePtr OpPC) { /// Just takes a pointer and checks if its' an incomplete /// array type. inline bool ArrayDecay(InterpState &S, CodePtr OpPC) { - const Pointer &Ptr = S.Stk.peek(); + const Pointer &Ptr = S.Stk.pop(); - if (!Ptr.isUnknownSizeArray()) + if (!Ptr.isUnknownSizeArray()) { + S.Stk.push(Ptr.atIndex(0)); return true; + } const SourceInfo &E = S.Current->getSource(OpPC); S.FFDiag(E, diag::note_constexpr_unsupported_unsized_array); diff --git a/clang/lib/AST/Interp/InterpBuiltin.cpp b/clang/lib/AST/Interp/InterpBuiltin.cpp index 9cf206ecc212adba28c6f4a9b346901434171720..b55b1569a259835f1a8f2b0a910ebd359d7f6f9f 100644 --- a/clang/lib/AST/Interp/InterpBuiltin.cpp +++ b/clang/lib/AST/Interp/InterpBuiltin.cpp @@ -34,6 +34,19 @@ PrimType getIntPrimType(const InterpState &S) { llvm_unreachable("Int isn't 16 or 32 bit?"); } +PrimType getLongPrimType(const InterpState &S) { + const TargetInfo &TI = S.getCtx().getTargetInfo(); + unsigned LongWidth = TI.getLongWidth(); + + if (LongWidth == 64) + return PT_Sint64; + else if (LongWidth == 32) + return PT_Sint32; + else if (LongWidth == 16) + return PT_Sint16; + llvm_unreachable("long isn't 16, 32 or 64 bit?"); +} + /// Peek an integer value from the stack into an APSInt. static APSInt peekToAPSInt(InterpStack &Stk, PrimType T, size_t Offset = 0) { if (Offset == 0) @@ -110,6 +123,19 @@ static void pushAPSInt(InterpState &S, const APSInt &Val) { } } +/// Pushes \p Val to the stack, as a target-dependent 'long'. +static void pushLong(InterpState &S, int64_t Val) { + PrimType LongType = getLongPrimType(S); + if (LongType == PT_Sint64) + S.Stk.push>(Integral<64, true>::from(Val)); + else if (LongType == PT_Sint32) + S.Stk.push>(Integral<32, true>::from(Val)); + else if (LongType == PT_Sint16) + S.Stk.push>(Integral<16, true>::from(Val)); + else + llvm_unreachable("Long isn't 16, 32 or 64 bit?"); +} + static void pushSizeT(InterpState &S, uint64_t Val) { const TargetInfo &TI = S.getCtx().getTargetInfo(); unsigned SizeTWidth = TI.getTypeWidth(TI.getSizeType()); @@ -533,6 +559,60 @@ static bool interp__builtin_classify_type(InterpState &S, CodePtr OpPC, return true; } +// __builtin_expect(long, long) +// __builtin_expect_with_probability(long, long, double) +static bool interp__builtin_expect(InterpState &S, CodePtr OpPC, + const InterpFrame *Frame, + const Function *Func, const CallExpr *Call) { + // The return value is simply the value of the first parameter. + // We ignore the probability. + unsigned NumArgs = Call->getNumArgs(); + assert(NumArgs == 2 || NumArgs == 3); + + PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType()); + unsigned Offset = align(primSize(getLongPrimType(S))) * 2; + if (NumArgs == 3) + Offset += align(primSize(PT_Float)); + + APSInt Val = peekToAPSInt(S.Stk, ArgT, Offset); + pushLong(S, Val.getSExtValue()); + return true; +} + +/// rotateleft(value, amount) +static bool interp__builtin_rotate(InterpState &S, CodePtr OpPC, + const InterpFrame *Frame, + const Function *Func, const CallExpr *Call, + bool Right) { + PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType()); + assert(ArgT == *S.getContext().classify(Call->getArg(1)->getType())); + + APSInt Amount = peekToAPSInt(S.Stk, ArgT); + APSInt Value = peekToAPSInt(S.Stk, ArgT, align(primSize(ArgT)) * 2); + + APSInt Result; + if (Right) + Result = APSInt(Value.rotr(Amount.urem(Value.getBitWidth())), + /*IsUnsigned=*/true); + else // Left. + Result = APSInt(Value.rotl(Amount.urem(Value.getBitWidth())), + /*IsUnsigned=*/true); + + pushAPSInt(S, Result); + return true; +} + +static bool interp__builtin_ffs(InterpState &S, CodePtr OpPC, + const InterpFrame *Frame, const Function *Func, + const CallExpr *Call) { + PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType()); + APSInt Value = peekToAPSInt(S.Stk, ArgT); + + uint64_t N = Value.countr_zero(); + pushInt(S, N == Value.getBitWidth() ? 0 : N + 1); + return true; +} + bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F, const CallExpr *Call) { InterpFrame *Frame = S.Current; @@ -702,6 +782,45 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F, return false; break; + case Builtin::BI__builtin_expect: + case Builtin::BI__builtin_expect_with_probability: + if (!interp__builtin_expect(S, OpPC, Frame, F, Call)) + return false; + break; + + case Builtin::BI__builtin_rotateleft8: + case Builtin::BI__builtin_rotateleft16: + case Builtin::BI__builtin_rotateleft32: + case Builtin::BI__builtin_rotateleft64: + case Builtin::BI_rotl8: // Microsoft variants of rotate left + case Builtin::BI_rotl16: + case Builtin::BI_rotl: + case Builtin::BI_lrotl: + case Builtin::BI_rotl64: + if (!interp__builtin_rotate(S, OpPC, Frame, F, Call, /*Right=*/false)) + return false; + break; + + case Builtin::BI__builtin_rotateright8: + case Builtin::BI__builtin_rotateright16: + case Builtin::BI__builtin_rotateright32: + case Builtin::BI__builtin_rotateright64: + case Builtin::BI_rotr8: // Microsoft variants of rotate right + case Builtin::BI_rotr16: + case Builtin::BI_rotr: + case Builtin::BI_lrotr: + case Builtin::BI_rotr64: + if (!interp__builtin_rotate(S, OpPC, Frame, F, Call, /*Right=*/true)) + return false; + break; + + case Builtin::BI__builtin_ffs: + case Builtin::BI__builtin_ffsl: + case Builtin::BI__builtin_ffsll: + if (!interp__builtin_ffs(S, OpPC, Frame, F, Call)) + return false; + break; + default: return false; } diff --git a/clang/lib/AST/Interp/InterpFrame.cpp b/clang/lib/AST/Interp/InterpFrame.cpp index b06923114c7a24ee5587f8e1f7ce18385ce70747..d460d7ea3710a88e0f99c19f10ecb0acce29fddc 100644 --- a/clang/lib/AST/Interp/InterpFrame.cpp +++ b/clang/lib/AST/Interp/InterpFrame.cpp @@ -228,7 +228,7 @@ Pointer InterpFrame::getParamPointer(unsigned Off) { SourceInfo InterpFrame::getSource(CodePtr PC) const { // Implicitly created functions don't have any code we could point at, // so return the call site. - if (Func && Func->getDecl()->isImplicit() && Caller) + if (Func && (!Func->hasBody() || Func->getDecl()->isImplicit()) && Caller) return Caller->getSource(RetPC); return S.getSource(Func, PC); @@ -243,7 +243,7 @@ SourceLocation InterpFrame::getLocation(CodePtr PC) const { } SourceRange InterpFrame::getRange(CodePtr PC) const { - if (Func && Func->getDecl()->isImplicit() && Caller) + if (Func && (!Func->hasBody() || Func->getDecl()->isImplicit()) && Caller) return Caller->getRange(RetPC); return S.getRange(Func, PC); diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp index 50ab6ea59be9d0311e7f5c84a372e93d2c8eb414..c59a66e103a6e3b929fa950f93414bd58c185de0 100644 --- a/clang/lib/AST/MicrosoftMangle.cpp +++ b/clang/lib/AST/MicrosoftMangle.cpp @@ -3809,14 +3809,14 @@ void MicrosoftMangleContextImpl::mangleCXXRTTICompleteObjectLocator( llvm::raw_svector_ostream Stream(VFTableMangling); mangleCXXVFTable(Derived, BasePath, Stream); - if (VFTableMangling.startswith("??@")) { - assert(VFTableMangling.endswith("@")); + if (VFTableMangling.starts_with("??@")) { + assert(VFTableMangling.ends_with("@")); Out << VFTableMangling << "??_R4@"; return; } - assert(VFTableMangling.startswith("??_7") || - VFTableMangling.startswith("??_S")); + assert(VFTableMangling.starts_with("??_7") || + VFTableMangling.starts_with("??_S")); Out << "??_R4" << VFTableMangling.str().drop_front(4); } diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index a51c8b938f411c066655a5d478c72178388fb51b..706991f4fb501c493a07bc861fd9028832ea0d99 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -2942,8 +2942,8 @@ void MicrosoftRecordLayoutBuilder::layoutNonVirtualBase( } if (!FoundBase) { - if (MDCUsesEBO && BaseDecl->isEmpty()) { - assert(BaseLayout.getNonVirtualSize() == CharUnits::Zero()); + if (MDCUsesEBO && BaseDecl->isEmpty() && + (BaseLayout.getNonVirtualSize() == CharUnits::Zero())) { BaseOffset = CharUnits::Zero(); } else { // Otherwise, lay the base out at the end of the MDC. diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp index ab4a013de5f552c2f04e9a511de01bea3c021e9f..c04cb313c3387a3bd3169a61360e4b422e2eb5af 100644 --- a/clang/lib/AST/StmtPrinter.cpp +++ b/clang/lib/AST/StmtPrinter.cpp @@ -1841,6 +1841,7 @@ void StmtPrinter::VisitAtomicExpr(AtomicExpr *Node) { PrintExpr(Node->getPtr()); if (Node->getOp() != AtomicExpr::AO__c11_atomic_load && Node->getOp() != AtomicExpr::AO__atomic_load_n && + Node->getOp() != AtomicExpr::AO__scoped_atomic_load_n && Node->getOp() != AtomicExpr::AO__opencl_atomic_load && Node->getOp() != AtomicExpr::AO__hip_atomic_load) { OS << ", "; diff --git a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp index 042402a129d103e7ccaefbbd2f89f9190dc9cff5..b98037b73645225ab3cf9a35d648181ef275854f 100644 --- a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp +++ b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp @@ -300,9 +300,12 @@ static void insertIfFunction(const Decl &D, } static MemberExpr *getMemberForAccessor(const CXXMemberCallExpr &C) { - if (!C.getMethodDecl()) + // Use getCalleeDecl instead of getMethodDecl in order to handle + // pointer-to-member calls. + const auto *MethodDecl = dyn_cast_or_null(C.getCalleeDecl()); + if (!MethodDecl) return nullptr; - auto *Body = dyn_cast_or_null(C.getMethodDecl()->getBody()); + auto *Body = dyn_cast_or_null(MethodDecl->getBody()); if (!Body || Body->size() != 1) return nullptr; if (auto *RS = dyn_cast(*Body->body_begin())) diff --git a/clang/lib/Analysis/FlowSensitive/HTMLLogger.cpp b/clang/lib/Analysis/FlowSensitive/HTMLLogger.cpp index 7430ef599e032d0c897461a777903d099948932f..2a7bfce5350159dfd6503f041b679a9533a3fb97 100644 --- a/clang/lib/Analysis/FlowSensitive/HTMLLogger.cpp +++ b/clang/lib/Analysis/FlowSensitive/HTMLLogger.cpp @@ -351,9 +351,10 @@ private: if (Invalid) return; - static constexpr unsigned Missing = -1; // TokenInfo stores the BB and set of elements that a token is part of. struct TokenInfo { + enum : unsigned { Missing = static_cast(-1) }; + // The basic block this is part of. // This is the BB of the stmt with the smallest containing range. unsigned BB = Missing; diff --git a/clang/lib/Analysis/ThreadSafety.cpp b/clang/lib/Analysis/ThreadSafety.cpp index 7fdf22c2f3919cb34134efb7a3decf9531578329..e25b843c9bf83e2c93d706e64a6a0741cc034330 100644 --- a/clang/lib/Analysis/ThreadSafety.cpp +++ b/clang/lib/Analysis/ThreadSafety.cpp @@ -1010,6 +1010,8 @@ class ThreadSafetyAnalyzer { ThreadSafetyHandler &Handler; const FunctionDecl *CurrentFunction; LocalVariableMap LocalVarMap; + // Maps constructed objects to `this` placeholder prior to initialization. + llvm::SmallDenseMap ConstructedObjects; FactManager FactMan; std::vector BlockInfo; @@ -1543,8 +1545,6 @@ class BuildLockset : public ConstStmtVisitor { FactSet FSet; // The fact set for the function on exit. const FactSet &FunctionExitFSet; - /// Maps constructed objects to `this` placeholder prior to initialization. - llvm::SmallDenseMap ConstructedObjects; LocalVariableMap::Context LVarCtx; unsigned CtxIndex; @@ -1808,7 +1808,7 @@ void BuildLockset::handleCall(const Expr *Exp, const NamedDecl *D, std::pair Placeholder = Analyzer->SxBuilder.createThisPlaceholder(Exp); [[maybe_unused]] auto inserted = - ConstructedObjects.insert({Exp, Placeholder.first}); + Analyzer->ConstructedObjects.insert({Exp, Placeholder.first}); assert(inserted.second && "Are we visiting the same expression again?"); if (isa(Exp)) Self = Placeholder.first; @@ -2128,10 +2128,10 @@ void BuildLockset::VisitDeclStmt(const DeclStmt *S) { E = EWC->getSubExpr()->IgnoreParens(); E = UnpackConstruction(E); - if (auto Object = ConstructedObjects.find(E); - Object != ConstructedObjects.end()) { + if (auto Object = Analyzer->ConstructedObjects.find(E); + Object != Analyzer->ConstructedObjects.end()) { Object->second->setClangDecl(VD); - ConstructedObjects.erase(Object); + Analyzer->ConstructedObjects.erase(Object); } } } @@ -2140,11 +2140,11 @@ void BuildLockset::VisitDeclStmt(const DeclStmt *S) { void BuildLockset::VisitMaterializeTemporaryExpr( const MaterializeTemporaryExpr *Exp) { if (const ValueDecl *ExtD = Exp->getExtendingDecl()) { - if (auto Object = - ConstructedObjects.find(UnpackConstruction(Exp->getSubExpr())); - Object != ConstructedObjects.end()) { + if (auto Object = Analyzer->ConstructedObjects.find( + UnpackConstruction(Exp->getSubExpr())); + Object != Analyzer->ConstructedObjects.end()) { Object->second->setClangDecl(ExtD); - ConstructedObjects.erase(Object); + Analyzer->ConstructedObjects.erase(Object); } } } @@ -2487,15 +2487,15 @@ void ThreadSafetyAnalyzer::runAnalysis(AnalysisDeclContext &AC) { // Clean up constructed object even if there are no attributes to // keep the number of objects in limbo as small as possible. - if (auto Object = LocksetBuilder.ConstructedObjects.find( + if (auto Object = ConstructedObjects.find( TD.getBindTemporaryExpr()->getSubExpr()); - Object != LocksetBuilder.ConstructedObjects.end()) { + Object != ConstructedObjects.end()) { const auto *DD = TD.getDestructorDecl(AC.getASTContext()); if (DD->hasAttrs()) // TODO: the location here isn't quite correct. LocksetBuilder.handleCall(nullptr, DD, Object->second, TD.getBindTemporaryExpr()->getEndLoc()); - LocksetBuilder.ConstructedObjects.erase(Object); + ConstructedObjects.erase(Object); } break; } diff --git a/clang/lib/Analysis/UninitializedValues.cpp b/clang/lib/Analysis/UninitializedValues.cpp index b796f7674cc1daeed867198289c594a87e1e8e32..e9111ded64eb1f8b46969bd5b1986f1f16e1839e 100644 --- a/clang/lib/Analysis/UninitializedValues.cpp +++ b/clang/lib/Analysis/UninitializedValues.cpp @@ -64,7 +64,7 @@ static bool isTrackedVar(const VarDecl *vd, const DeclContext *dc) { QualType ty = vd->getType(); if (const auto *RD = ty->getAsRecordDecl()) return recordIsNotEmpty(RD); - return ty->isScalarType() || ty->isVectorType() || ty->isRVVType(); + return ty->isScalarType() || ty->isVectorType() || ty->isRVVSizelessBuiltinType(); } return false; } diff --git a/clang/lib/Analysis/UnsafeBufferUsage.cpp b/clang/lib/Analysis/UnsafeBufferUsage.cpp index e332a3609290aace02af6ea0e023dd21d18d0cb8..70eec1cee57f8e1d52263999dbf55c5e9375d963 100644 --- a/clang/lib/Analysis/UnsafeBufferUsage.cpp +++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp @@ -1028,6 +1028,46 @@ public: } }; +// Representing a pointer type expression of the form `Ptr += n` in an +// Unspecified Untyped Context (UUC): +class UUCAddAssignGadget : public FixableGadget { +private: + static constexpr const char *const UUCAddAssignTag = + "PointerAddAssignUnderUUC"; + static constexpr const char *const OffsetTag = "Offset"; + + const BinaryOperator *Node; // the `Ptr += n` node + const Expr *Offset = nullptr; + +public: + UUCAddAssignGadget(const MatchFinder::MatchResult &Result) + : FixableGadget(Kind::UUCAddAssign), + Node(Result.Nodes.getNodeAs(UUCAddAssignTag)), + Offset(Result.Nodes.getNodeAs(OffsetTag)) { + assert(Node != nullptr && "Expecting a non-null matching result"); + } + + static bool classof(const Gadget *G) { + return G->getKind() == Kind::UUCAddAssign; + } + + static Matcher matcher() { + return stmt(isInUnspecifiedUntypedContext(expr(ignoringImpCasts( + binaryOperator(hasOperatorName("+="), + hasLHS(declRefExpr(toSupportedVariable())), + hasRHS(expr().bind(OffsetTag))) + .bind(UUCAddAssignTag))))); + } + + virtual std::optional getFixits(const Strategy &S) const override; + + virtual const Stmt *getBaseStmt() const override { return Node; } + + virtual DeclUseList getClaimedVarUseSites() const override { + return {dyn_cast(Node->getLHS())}; + } +}; + // Representing a fixable expression of the form `*(ptr + 123)` or `*(123 + // ptr)`: class DerefSimplePtrArithFixableGadget : public FixableGadget { @@ -1312,6 +1352,16 @@ PointerInitGadget::getFixits(const Strategy &S) const { return std::nullopt; } +static bool isNonNegativeIntegerExpr(const Expr *Expr, const VarDecl *VD, + const ASTContext &Ctx) { + if (auto ConstVal = Expr->getIntegerConstantExpr(Ctx)) { + if (ConstVal->isNegative()) + return false; + } else if (!Expr->getType()->isUnsignedIntegerType()) + return false; + return true; +} + std::optional ULCArraySubscriptGadget::getFixits(const Strategy &S) const { if (const auto *DRE = @@ -1319,14 +1369,12 @@ ULCArraySubscriptGadget::getFixits(const Strategy &S) const { if (const auto *VD = dyn_cast(DRE->getDecl())) { switch (S.lookup(VD)) { case Strategy::Kind::Span: { + // If the index has a negative constant value, we give up as no valid // fix-it can be generated: const ASTContext &Ctx = // FIXME: we need ASTContext to be passed in! VD->getASTContext(); - if (auto ConstVal = Node->getIdx()->getIntegerConstantExpr(Ctx)) { - if (ConstVal->isNegative()) - return std::nullopt; - } else if (!Node->getIdx()->getType()->isUnsignedIntegerType()) + if (!isNonNegativeIntegerExpr(Node->getIdx(), VD, Ctx)) return std::nullopt; // no-op is a good fix-it, otherwise return FixItList{}; @@ -1405,10 +1453,8 @@ static std::optional getPastLoc(const NodeTy *Node, const LangOptions &LangOpts) { SourceLocation Loc = Lexer::getLocForEndOfToken(Node->getEndLoc(), 0, SM, LangOpts); - if (Loc.isValid()) return Loc; - return std::nullopt; } @@ -1488,7 +1534,7 @@ static bool hasUnsupportedSpecifiers(const VarDecl *VD, // returned by this function is the last location of the last token. static SourceRange getSourceRangeToTokenEnd(const Decl *D, const SourceManager &SM, - LangOptions LangOpts) { + const LangOptions &LangOpts) { SourceLocation Begin = D->getBeginLoc(); SourceLocation End = // `D->getEndLoc` should always return the starting location of the @@ -1766,6 +1812,47 @@ fixUPCAddressofArraySubscriptWithSpan(const UnaryOperator *Node) { FixItHint::CreateReplacement(Node->getSourceRange(), SS.str())}; } +std::optional +UUCAddAssignGadget::getFixits(const Strategy &S) const { + DeclUseList DREs = getClaimedVarUseSites(); + + if (DREs.size() != 1) + return std::nullopt; // In cases of `Ptr += n` where `Ptr` is not a DRE, we + // give up + if (const VarDecl *VD = dyn_cast(DREs.front()->getDecl())) { + if (S.lookup(VD) == Strategy::Kind::Span) { + FixItList Fixes; + + const Stmt *AddAssignNode = getBaseStmt(); + StringRef varName = VD->getName(); + const ASTContext &Ctx = VD->getASTContext(); + + if (!isNonNegativeIntegerExpr(Offset, VD, Ctx)) + return std::nullopt; + + // To transform UUC(p += n) to UUC(p = p.subspan(..)): + bool NotParenExpr = + (Offset->IgnoreParens()->getBeginLoc() == Offset->getBeginLoc()); + std::string SS = varName.str() + " = " + varName.str() + ".subspan"; + if (NotParenExpr) + SS += "("; + + std::optional AddAssignLocation = getEndCharLoc( + AddAssignNode, Ctx.getSourceManager(), Ctx.getLangOpts()); + if (!AddAssignLocation) + return std::nullopt; + + Fixes.push_back(FixItHint::CreateReplacement( + SourceRange(AddAssignNode->getBeginLoc(), Node->getOperatorLoc()), + SS)); + if (NotParenExpr) + Fixes.push_back(FixItHint::CreateInsertion( + Offset->getEndLoc().getLocWithOffset(1), ")")); + return Fixes; + } + } + return std::nullopt; // Not in the cases that we can handle for now, give up. +} std::optional UPCPreIncrementGadget::getFixits(const Strategy &S) const { DeclUseList DREs = getClaimedVarUseSites(); diff --git a/clang/lib/Basic/CodeGenOptions.cpp b/clang/lib/Basic/CodeGenOptions.cpp index 0c609cfa61de18561626e4f0753e0e15cd1c866c..182d0a2fa4d88f212ce607284f3db9b06ef477cb 100644 --- a/clang/lib/Basic/CodeGenOptions.cpp +++ b/clang/lib/Basic/CodeGenOptions.cpp @@ -20,4 +20,39 @@ CodeGenOptions::CodeGenOptions() { memcpy(CoverageVersion, "408*", 4); } +void CodeGenOptions::resetNonModularOptions(StringRef ModuleFormat) { + // First reset all CodeGen options only. The Debug options are handled later. +#define DEBUGOPT(Name, Bits, Default) +#define VALUE_DEBUGOPT(Name, Bits, Default) +#define ENUM_DEBUGOPT(Name, Type, Bits, Default) +#define CODEGENOPT(Name, Bits, Default) Name = Default; +#define ENUM_CODEGENOPT(Name, Type, Bits, Default) set##Name(Default); +#include "clang/Basic/CodeGenOptions.def" + + // Next reset all debug options that can always be reset, because they never + // affect the PCM. +#define DEBUGOPT(Name, Bits, Default) +#define VALUE_DEBUGOPT(Name, Bits, Default) +#define ENUM_DEBUGOPT(Name, Type, Bits, Default) +#define BENIGN_DEBUGOPT(Name, Bits, Default) Name = Default; +#define BENIGN_VALUE_DEBUGOPT(Name, Bits, Default) Name = Default; +#define BENIGN_ENUM_DEBUGOPT(Name, Type, Bits, Default) set##Name(Default); +#include "clang/Basic/DebugOptions.def" + + // Conditionally reset debug options that only matter when the debug info is + // emitted into the PCM (-gmodules). + if (ModuleFormat == "raw" && !DebugTypeExtRefs) { +#define DEBUGOPT(Name, Bits, Default) Name = Default; +#define VALUE_DEBUGOPT(Name, Bits, Default) Name = Default; +#define ENUM_DEBUGOPT(Name, Type, Bits, Default) set##Name(Default); +#define BENIGN_DEBUGOPT(Name, Bits, Default) +#define BENIGN_VALUE_DEBUGOPT(Name, Bits, Default) +#define BENIGN_ENUM_DEBUGOPT(Name, Type, Bits, Default) +#include "clang/Basic/DebugOptions.def" + } + + RelocationModel = llvm::Reloc::PIC_; + memcpy(CoverageVersion, "408*", 4); +} + } // end namespace clang diff --git a/clang/lib/Basic/Cuda.cpp b/clang/lib/Basic/Cuda.cpp index 65840b9f20252b62bee800895fa7dd991735b5cc..1b1da6a1356f2c4de266660eb57882388a8dd918 100644 --- a/clang/lib/Basic/Cuda.cpp +++ b/clang/lib/Basic/Cuda.cpp @@ -39,6 +39,8 @@ static const CudaVersionMapEntry CudaNameVersionMap[] = { CUDA_ENTRY(11, 8), CUDA_ENTRY(12, 0), CUDA_ENTRY(12, 1), + CUDA_ENTRY(12, 2), + CUDA_ENTRY(12, 3), {"", CudaVersion::NEW, llvm::VersionTuple(std::numeric_limits::max())}, {"unknown", CudaVersion::UNKNOWN, {}} // End of list tombstone. }; @@ -93,6 +95,7 @@ static const CudaArchToStringMap arch_names[] = { SM(87), // Jetson/Drive AGX Orin SM(89), // Ada Lovelace SM(90), // Hopper + SM(90a), // Hopper GFX(600), // gfx600 GFX(601), // gfx601 GFX(602), // gfx602 @@ -209,6 +212,8 @@ CudaVersion MinVersionForCudaArch(CudaArch A) { case CudaArch::SM_89: case CudaArch::SM_90: return CudaVersion::CUDA_118; + case CudaArch::SM_90a: + return CudaVersion::CUDA_120; default: llvm_unreachable("invalid enum"); } diff --git a/clang/lib/Basic/Module.cpp b/clang/lib/Basic/Module.cpp index e4ac1abf12a7f8e340aabd49802ba83b34afa9f4..7523e509a47108c207559585d0e988371c1532ef 100644 --- a/clang/lib/Basic/Module.cpp +++ b/clang/lib/Basic/Module.cpp @@ -89,7 +89,7 @@ static bool isPlatformEnvironment(const TargetInfo &Target, StringRef Feature) { // where both are valid examples of the same platform+environment but in the // variant (2) the simulator is hardcoded as part of the platform name. Both // forms above should match for "iossimulator" requirement. - if (Target.getTriple().isOSDarwin() && PlatformEnv.endswith("simulator")) + if (Target.getTriple().isOSDarwin() && PlatformEnv.ends_with("simulator")) return PlatformEnv == Feature || CmpPlatformEnv(PlatformEnv, Feature); return PlatformEnv == Feature; diff --git a/clang/lib/Basic/Targets/AArch64.cpp b/clang/lib/Basic/Targets/AArch64.cpp index c31f2e0bee54393e188233d6555a97aacb9f4d07..e3e08b571667cce2df44ebc0658b2f4f68bcd2d8 100644 --- a/clang/lib/Basic/Targets/AArch64.cpp +++ b/clang/lib/Basic/Targets/AArch64.cpp @@ -574,11 +574,12 @@ void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts, else if (*ArchInfo == llvm::AArch64::ARMV9_5A) getTargetDefinesARMV95A(Opts, Builder); - // All of the __sync_(bool|val)_compare_and_swap_(1|2|4|8) builtins work. + // All of the __sync_(bool|val)_compare_and_swap_(1|2|4|8|16) builtins work. Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1"); Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2"); Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4"); Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8"); + Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16"); // Allow detection of fast FMA support. Builder.defineMacro("__FP_FAST_FMA", "1"); diff --git a/clang/lib/Basic/Targets/AMDGPU.cpp b/clang/lib/Basic/Targets/AMDGPU.cpp index 409ae32ab4242151c22e223a94e2909d8ae5bd05..719fc51bfc286fb57247ea71b2c7626ce49e7e83 100644 --- a/clang/lib/Basic/Targets/AMDGPU.cpp +++ b/clang/lib/Basic/Targets/AMDGPU.cpp @@ -37,50 +37,50 @@ static const char *const DataLayoutStringAMDGCN = "-ni:7:8"; const LangASMap AMDGPUTargetInfo::AMDGPUDefIsGenMap = { - Generic, // Default - Global, // opencl_global - Local, // opencl_local - Constant, // opencl_constant - Private, // opencl_private - Generic, // opencl_generic - Global, // opencl_global_device - Global, // opencl_global_host - Global, // cuda_device - Constant, // cuda_constant - Local, // cuda_shared - Global, // sycl_global - Global, // sycl_global_device - Global, // sycl_global_host - Local, // sycl_local - Private, // sycl_private - Generic, // ptr32_sptr - Generic, // ptr32_uptr - Generic, // ptr64 - Generic, // hlsl_groupshared + llvm::AMDGPUAS::FLAT_ADDRESS, // Default + llvm::AMDGPUAS::GLOBAL_ADDRESS, // opencl_global + llvm::AMDGPUAS::LOCAL_ADDRESS, // opencl_local + llvm::AMDGPUAS::CONSTANT_ADDRESS, // opencl_constant + llvm::AMDGPUAS::PRIVATE_ADDRESS, // opencl_private + llvm::AMDGPUAS::FLAT_ADDRESS, // opencl_generic + llvm::AMDGPUAS::GLOBAL_ADDRESS, // opencl_global_device + llvm::AMDGPUAS::GLOBAL_ADDRESS, // opencl_global_host + llvm::AMDGPUAS::GLOBAL_ADDRESS, // cuda_device + llvm::AMDGPUAS::CONSTANT_ADDRESS, // cuda_constant + llvm::AMDGPUAS::LOCAL_ADDRESS, // cuda_shared + llvm::AMDGPUAS::GLOBAL_ADDRESS, // sycl_global + llvm::AMDGPUAS::GLOBAL_ADDRESS, // sycl_global_device + llvm::AMDGPUAS::GLOBAL_ADDRESS, // sycl_global_host + llvm::AMDGPUAS::LOCAL_ADDRESS, // sycl_local + llvm::AMDGPUAS::PRIVATE_ADDRESS, // sycl_private + llvm::AMDGPUAS::FLAT_ADDRESS, // ptr32_sptr + llvm::AMDGPUAS::FLAT_ADDRESS, // ptr32_uptr + llvm::AMDGPUAS::FLAT_ADDRESS, // ptr64 + llvm::AMDGPUAS::FLAT_ADDRESS, // hlsl_groupshared }; const LangASMap AMDGPUTargetInfo::AMDGPUDefIsPrivMap = { - Private, // Default - Global, // opencl_global - Local, // opencl_local - Constant, // opencl_constant - Private, // opencl_private - Generic, // opencl_generic - Global, // opencl_global_device - Global, // opencl_global_host - Global, // cuda_device - Constant, // cuda_constant - Local, // cuda_shared + llvm::AMDGPUAS::PRIVATE_ADDRESS, // Default + llvm::AMDGPUAS::GLOBAL_ADDRESS, // opencl_global + llvm::AMDGPUAS::LOCAL_ADDRESS, // opencl_local + llvm::AMDGPUAS::CONSTANT_ADDRESS, // opencl_constant + llvm::AMDGPUAS::PRIVATE_ADDRESS, // opencl_private + llvm::AMDGPUAS::FLAT_ADDRESS, // opencl_generic + llvm::AMDGPUAS::GLOBAL_ADDRESS, // opencl_global_device + llvm::AMDGPUAS::GLOBAL_ADDRESS, // opencl_global_host + llvm::AMDGPUAS::GLOBAL_ADDRESS, // cuda_device + llvm::AMDGPUAS::CONSTANT_ADDRESS, // cuda_constant + llvm::AMDGPUAS::LOCAL_ADDRESS, // cuda_shared // SYCL address space values for this map are dummy - Generic, // sycl_global - Generic, // sycl_global_device - Generic, // sycl_global_host - Generic, // sycl_local - Generic, // sycl_private - Generic, // ptr32_sptr - Generic, // ptr32_uptr - Generic, // ptr64 - Generic, // hlsl_groupshared + llvm::AMDGPUAS::FLAT_ADDRESS, // sycl_global + llvm::AMDGPUAS::FLAT_ADDRESS, // sycl_global_device + llvm::AMDGPUAS::FLAT_ADDRESS, // sycl_global_host + llvm::AMDGPUAS::FLAT_ADDRESS, // sycl_local + llvm::AMDGPUAS::FLAT_ADDRESS, // sycl_private + llvm::AMDGPUAS::FLAT_ADDRESS, // ptr32_sptr + llvm::AMDGPUAS::FLAT_ADDRESS, // ptr32_uptr + llvm::AMDGPUAS::FLAT_ADDRESS, // ptr64 + llvm::AMDGPUAS::FLAT_ADDRESS, // hlsl_groupshared }; } // namespace targets diff --git a/clang/lib/Basic/Targets/AMDGPU.h b/clang/lib/Basic/Targets/AMDGPU.h index 300d9691d8a0f2207ebc6eb64bd5626c12e55a17..1819ba544ccf84b51cff4c24bf9bed42fdcd327b 100644 --- a/clang/lib/Basic/Targets/AMDGPU.h +++ b/clang/lib/Basic/Targets/AMDGPU.h @@ -17,6 +17,7 @@ #include "clang/Basic/TargetInfo.h" #include "clang/Basic/TargetOptions.h" #include "llvm/ADT/StringSet.h" +#include "llvm/Support/AMDGPUAddrSpace.h" #include "llvm/Support/Compiler.h" #include "llvm/TargetParser/TargetParser.h" #include "llvm/TargetParser/Triple.h" @@ -29,13 +30,6 @@ class LLVM_LIBRARY_VISIBILITY AMDGPUTargetInfo final : public TargetInfo { static const char *const GCCRegNames[]; - enum AddrSpace { - Generic = 0, - Global = 1, - Local = 3, - Constant = 4, - Private = 5 - }; static const LangASMap AMDGPUDefIsGenMap; static const LangASMap AMDGPUDefIsPrivMap; @@ -106,7 +100,8 @@ public: return 32; unsigned TargetAS = getTargetAddressSpace(AS); - if (TargetAS == Private || TargetAS == Local) + if (TargetAS == llvm::AMDGPUAS::PRIVATE_ADDRESS || + TargetAS == llvm::AMDGPUAS::LOCAL_ADDRESS) return 32; return 64; @@ -376,7 +371,7 @@ public: } std::optional getConstantAddressSpace() const override { - return getLangASFromTargetAS(Constant); + return getLangASFromTargetAS(llvm::AMDGPUAS::CONSTANT_ADDRESS); } const llvm::omp::GV &getGridValue() const override { @@ -392,7 +387,7 @@ public: /// \returns Target specific vtbl ptr address space. unsigned getVtblPtrAddressSpace() const override { - return static_cast(Constant); + return static_cast(llvm::AMDGPUAS::CONSTANT_ADDRESS); } /// \returns If a target requires an address within a target specific address @@ -405,9 +400,9 @@ public: getDWARFAddressSpace(unsigned AddressSpace) const override { const unsigned DWARF_Private = 1; const unsigned DWARF_Local = 2; - if (AddressSpace == Private) { + if (AddressSpace == llvm::AMDGPUAS::PRIVATE_ADDRESS) { return DWARF_Private; - } else if (AddressSpace == Local) { + } else if (AddressSpace == llvm::AMDGPUAS::LOCAL_ADDRESS) { return DWARF_Local; } else { return std::nullopt; diff --git a/clang/lib/Basic/Targets/NVPTX.cpp b/clang/lib/Basic/Targets/NVPTX.cpp index 3a4a75b0348f2094c84f4343bc98fccb69e51887..5c601812f617596526cc6d2a0e22cbc23bb5e05d 100644 --- a/clang/lib/Basic/Targets/NVPTX.cpp +++ b/clang/lib/Basic/Targets/NVPTX.cpp @@ -262,11 +262,14 @@ void NVPTXTargetInfo::getTargetDefines(const LangOptions &Opts, case CudaArch::SM_89: return "890"; case CudaArch::SM_90: + case CudaArch::SM_90a: return "900"; } llvm_unreachable("unhandled CudaArch"); }(); Builder.defineMacro("__CUDA_ARCH__", CUDAArchCode); + if (GPU == CudaArch::SM_90a) + Builder.defineMacro("__CUDA_ARCH_FEAT_SM90_ALL", "1"); } } diff --git a/clang/lib/Basic/Targets/OSTargets.cpp b/clang/lib/Basic/Targets/OSTargets.cpp index 627bc912fa2310464745d1555e49f64874cde1f2..899aefa6173acfe131a436852f4d4e2661768b68 100644 --- a/clang/lib/Basic/Targets/OSTargets.cpp +++ b/clang/lib/Basic/Targets/OSTargets.cpp @@ -224,6 +224,9 @@ static void addVisualCDefines(const LangOptions &Opts, MacroBuilder &Builder) { else if (Opts.CPlusPlus14) Builder.defineMacro("_MSVC_LANG", "201402L"); } + + if (Opts.isCompatibleWithMSVC(LangOptions::MSVC2022_3)) + Builder.defineMacro("_MSVC_CONSTEXPR_ATTRIBUTE"); } if (Opts.MicrosoftExt) { diff --git a/clang/lib/Basic/Targets/RISCV.cpp b/clang/lib/Basic/Targets/RISCV.cpp index 13f934e9947212c67535d7fd4cb0e8434e7611e3..45d23022b5306b3c5e5ec41d637520dccc0cde72 100644 --- a/clang/lib/Basic/Targets/RISCV.cpp +++ b/clang/lib/Basic/Targets/RISCV.cpp @@ -131,7 +131,7 @@ static unsigned getVersionValue(unsigned MajorVersion, unsigned MinorVersion) { void RISCVTargetInfo::getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const { Builder.defineMacro("__riscv"); - bool Is64Bit = getTriple().getArch() == llvm::Triple::riscv64; + bool Is64Bit = getTriple().isRISCV64(); Builder.defineMacro("__riscv_xlen", Is64Bit ? "64" : "32"); StringRef CodeModel = getTargetOpts().CodeModel; unsigned FLen = ISAInfo->getFLen(); @@ -281,7 +281,7 @@ bool RISCVTargetInfo::initFeatureMap( unsigned XLen = 32; - if (getTriple().getArch() == llvm::Triple::riscv64) { + if (getTriple().isRISCV64()) { Features["64bit"] = true; XLen = 64; } else { @@ -304,11 +304,18 @@ bool RISCVTargetInfo::initFeatureMap( // RISCVISAInfo makes implications for ISA features std::vector ImpliedFeatures = (*ParseResult)->toFeatureVector(); - // Add non-ISA features like `relax` and `save-restore` back - for (const std::string &Feature : NewFeaturesVec) - if (!llvm::is_contained(ImpliedFeatures, Feature)) - ImpliedFeatures.push_back(Feature); + // parseFeatures normalizes the feature set by dropping any explicit + // negatives, and non-extension features. We need to preserve the later + // for correctness and want to preserve the former for consistency. + for (auto &Feature : NewFeaturesVec) { + StringRef ExtName = Feature; + assert(ExtName.size() > 1 && (ExtName[0] == '+' || ExtName[0] == '-')); + ExtName = ExtName.drop_front(1); // Drop '+' or '-' + if (!llvm::is_contained(ImpliedFeatures, ("+" + ExtName).str()) && + !llvm::is_contained(ImpliedFeatures, ("-" + ExtName).str())) + ImpliedFeatures.push_back(Feature); + } return TargetInfo::initFeatureMap(Features, Diags, CPU, ImpliedFeatures); } @@ -336,7 +343,7 @@ RISCVTargetInfo::getVScaleRange(const LangOptions &LangOpts) const { /// Return true if has this feature, need to sync with handleTargetFeatures. bool RISCVTargetInfo::hasFeature(StringRef Feature) const { - bool Is64Bit = getTriple().getArch() == llvm::Triple::riscv64; + bool Is64Bit = getTriple().isRISCV64(); auto Result = llvm::StringSwitch>(Feature) .Case("riscv", true) .Case("riscv32", !Is64Bit) @@ -347,10 +354,7 @@ bool RISCVTargetInfo::hasFeature(StringRef Feature) const { if (Result) return *Result; - if (ISAInfo->isSupportedExtensionFeature(Feature)) - return ISAInfo->hasExtension(Feature); - - return false; + return ISAInfo->hasExtension(Feature); } /// Perform initialization based on the user configured set of features. diff --git a/clang/lib/Basic/Targets/SystemZ.h b/clang/lib/Basic/Targets/SystemZ.h index 9ba255745cf2cc52676208d062cb8cff31bc801a..e4ec338880f21095693fabe84780ff30ebacdef1 100644 --- a/clang/lib/Basic/Targets/SystemZ.h +++ b/clang/lib/Basic/Targets/SystemZ.h @@ -60,7 +60,7 @@ public: resetDataLayout("E-m:e-i1:8:16-i8:8:16-i64:64-f128:64" "-v128:64-a:8:16-n32:64"); } - MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64; + MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 128; HasStrictFP = true; } diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp index 8c666e2cb463c6ccfee6259d1339d693893f9a07..77455c075cab0d9dadd52756f3a47bd62d55835d 100644 --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -982,7 +982,7 @@ void EmitAssemblyHelper::RunOptimizationPipeline( getInstrProfOptions(CodeGenOpts, LangOpts)) PB.registerPipelineStartEPCallback( [Options](ModulePassManager &MPM, OptimizationLevel Level) { - MPM.addPass(InstrProfiling(*Options, false)); + MPM.addPass(InstrProfilingLoweringPass(*Options, false)); }); // TODO: Consider passing the MemoryProfileOutput to the pass builder via diff --git a/clang/lib/CodeGen/CGAtomic.cpp b/clang/lib/CodeGen/CGAtomic.cpp index 6005d5c51c0e1ac9be09d8dc3d80c8deaf2503dd..52e6ddb7d6afb05c217ade3f6c49016550a5e0dd 100644 --- a/clang/lib/CodeGen/CGAtomic.cpp +++ b/clang/lib/CodeGen/CGAtomic.cpp @@ -383,8 +383,7 @@ static void emitAtomicCmpXchg(CodeGenFunction &CGF, AtomicExpr *E, bool IsWeak, llvm::Value *Desired = CGF.Builder.CreateLoad(Val2); llvm::AtomicCmpXchgInst *Pair = CGF.Builder.CreateAtomicCmpXchg( - Ptr.getPointer(), Expected, Desired, SuccessOrder, FailureOrder, - Scope); + Ptr, Expected, Desired, SuccessOrder, FailureOrder, Scope); Pair->setVolatile(E->isVolatile()); Pair->setWeak(IsWeak); @@ -508,9 +507,11 @@ static llvm::Value *EmitPostAtomicMinMax(CGBuilderTy &Builder, default: llvm_unreachable("Unexpected min/max operation"); case AtomicExpr::AO__atomic_max_fetch: + case AtomicExpr::AO__scoped_atomic_max_fetch: Pred = IsSigned ? llvm::CmpInst::ICMP_SGT : llvm::CmpInst::ICMP_UGT; break; case AtomicExpr::AO__atomic_min_fetch: + case AtomicExpr::AO__scoped_atomic_min_fetch: Pred = IsSigned ? llvm::CmpInst::ICMP_SLT : llvm::CmpInst::ICMP_ULT; break; } @@ -545,7 +546,9 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, Address Dest, FailureOrder, Size, Order, Scope); return; case AtomicExpr::AO__atomic_compare_exchange: - case AtomicExpr::AO__atomic_compare_exchange_n: { + case AtomicExpr::AO__atomic_compare_exchange_n: + case AtomicExpr::AO__scoped_atomic_compare_exchange: + case AtomicExpr::AO__scoped_atomic_compare_exchange_n: { if (llvm::ConstantInt *IsWeakC = dyn_cast(IsWeak)) { emitAtomicCmpXchgFailureSet(CGF, E, IsWeakC->getZExtValue(), Dest, Ptr, Val1, Val2, FailureOrder, Size, Order, Scope); @@ -578,7 +581,9 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, Address Dest, case AtomicExpr::AO__opencl_atomic_load: case AtomicExpr::AO__hip_atomic_load: case AtomicExpr::AO__atomic_load_n: - case AtomicExpr::AO__atomic_load: { + case AtomicExpr::AO__atomic_load: + case AtomicExpr::AO__scoped_atomic_load_n: + case AtomicExpr::AO__scoped_atomic_load: { llvm::LoadInst *Load = CGF.Builder.CreateLoad(Ptr); Load->setAtomic(Order, Scope); Load->setVolatile(E->isVolatile()); @@ -590,7 +595,9 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, Address Dest, case AtomicExpr::AO__opencl_atomic_store: case AtomicExpr::AO__hip_atomic_store: case AtomicExpr::AO__atomic_store: - case AtomicExpr::AO__atomic_store_n: { + case AtomicExpr::AO__atomic_store_n: + case AtomicExpr::AO__scoped_atomic_store: + case AtomicExpr::AO__scoped_atomic_store_n: { llvm::Value *LoadVal1 = CGF.Builder.CreateLoad(Val1); llvm::StoreInst *Store = CGF.Builder.CreateStore(LoadVal1, Ptr); Store->setAtomic(Order, Scope); @@ -603,10 +610,13 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, Address Dest, case AtomicExpr::AO__opencl_atomic_exchange: case AtomicExpr::AO__atomic_exchange_n: case AtomicExpr::AO__atomic_exchange: + case AtomicExpr::AO__scoped_atomic_exchange_n: + case AtomicExpr::AO__scoped_atomic_exchange: Op = llvm::AtomicRMWInst::Xchg; break; case AtomicExpr::AO__atomic_add_fetch: + case AtomicExpr::AO__scoped_atomic_add_fetch: PostOp = E->getValueType()->isFloatingType() ? llvm::Instruction::FAdd : llvm::Instruction::Add; [[fallthrough]]; @@ -614,11 +624,13 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, Address Dest, case AtomicExpr::AO__hip_atomic_fetch_add: case AtomicExpr::AO__opencl_atomic_fetch_add: case AtomicExpr::AO__atomic_fetch_add: + case AtomicExpr::AO__scoped_atomic_fetch_add: Op = E->getValueType()->isFloatingType() ? llvm::AtomicRMWInst::FAdd : llvm::AtomicRMWInst::Add; break; case AtomicExpr::AO__atomic_sub_fetch: + case AtomicExpr::AO__scoped_atomic_sub_fetch: PostOp = E->getValueType()->isFloatingType() ? llvm::Instruction::FSub : llvm::Instruction::Sub; [[fallthrough]]; @@ -626,17 +638,20 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, Address Dest, case AtomicExpr::AO__hip_atomic_fetch_sub: case AtomicExpr::AO__opencl_atomic_fetch_sub: case AtomicExpr::AO__atomic_fetch_sub: + case AtomicExpr::AO__scoped_atomic_fetch_sub: Op = E->getValueType()->isFloatingType() ? llvm::AtomicRMWInst::FSub : llvm::AtomicRMWInst::Sub; break; case AtomicExpr::AO__atomic_min_fetch: + case AtomicExpr::AO__scoped_atomic_min_fetch: PostOpMinMax = true; [[fallthrough]]; case AtomicExpr::AO__c11_atomic_fetch_min: case AtomicExpr::AO__hip_atomic_fetch_min: case AtomicExpr::AO__opencl_atomic_fetch_min: case AtomicExpr::AO__atomic_fetch_min: + case AtomicExpr::AO__scoped_atomic_fetch_min: Op = E->getValueType()->isFloatingType() ? llvm::AtomicRMWInst::FMin : (E->getValueType()->isSignedIntegerType() @@ -645,12 +660,14 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, Address Dest, break; case AtomicExpr::AO__atomic_max_fetch: + case AtomicExpr::AO__scoped_atomic_max_fetch: PostOpMinMax = true; [[fallthrough]]; case AtomicExpr::AO__c11_atomic_fetch_max: case AtomicExpr::AO__hip_atomic_fetch_max: case AtomicExpr::AO__opencl_atomic_fetch_max: case AtomicExpr::AO__atomic_fetch_max: + case AtomicExpr::AO__scoped_atomic_fetch_max: Op = E->getValueType()->isFloatingType() ? llvm::AtomicRMWInst::FMax : (E->getValueType()->isSignedIntegerType() @@ -659,47 +676,55 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, Address Dest, break; case AtomicExpr::AO__atomic_and_fetch: + case AtomicExpr::AO__scoped_atomic_and_fetch: PostOp = llvm::Instruction::And; [[fallthrough]]; case AtomicExpr::AO__c11_atomic_fetch_and: case AtomicExpr::AO__hip_atomic_fetch_and: case AtomicExpr::AO__opencl_atomic_fetch_and: case AtomicExpr::AO__atomic_fetch_and: + case AtomicExpr::AO__scoped_atomic_fetch_and: Op = llvm::AtomicRMWInst::And; break; case AtomicExpr::AO__atomic_or_fetch: + case AtomicExpr::AO__scoped_atomic_or_fetch: PostOp = llvm::Instruction::Or; [[fallthrough]]; case AtomicExpr::AO__c11_atomic_fetch_or: case AtomicExpr::AO__hip_atomic_fetch_or: case AtomicExpr::AO__opencl_atomic_fetch_or: case AtomicExpr::AO__atomic_fetch_or: + case AtomicExpr::AO__scoped_atomic_fetch_or: Op = llvm::AtomicRMWInst::Or; break; case AtomicExpr::AO__atomic_xor_fetch: + case AtomicExpr::AO__scoped_atomic_xor_fetch: PostOp = llvm::Instruction::Xor; [[fallthrough]]; case AtomicExpr::AO__c11_atomic_fetch_xor: case AtomicExpr::AO__hip_atomic_fetch_xor: case AtomicExpr::AO__opencl_atomic_fetch_xor: case AtomicExpr::AO__atomic_fetch_xor: + case AtomicExpr::AO__scoped_atomic_fetch_xor: Op = llvm::AtomicRMWInst::Xor; break; case AtomicExpr::AO__atomic_nand_fetch: + case AtomicExpr::AO__scoped_atomic_nand_fetch: PostOp = llvm::Instruction::And; // the NOT is special cased below [[fallthrough]]; case AtomicExpr::AO__c11_atomic_fetch_nand: case AtomicExpr::AO__atomic_fetch_nand: + case AtomicExpr::AO__scoped_atomic_fetch_nand: Op = llvm::AtomicRMWInst::Nand; break; } llvm::Value *LoadVal1 = CGF.Builder.CreateLoad(Val1); llvm::AtomicRMWInst *RMWI = - CGF.Builder.CreateAtomicRMW(Op, Ptr.getPointer(), LoadVal1, Order, Scope); + CGF.Builder.CreateAtomicRMW(Op, Ptr, LoadVal1, Order, Scope); RMWI->setVolatile(E->isVolatile()); // For __atomic_*_fetch operations, perform the operation again to @@ -712,7 +737,8 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, Address Dest, else if (PostOp) Result = CGF.Builder.CreateBinOp((llvm::Instruction::BinaryOps)PostOp, RMWI, LoadVal1); - if (E->getOp() == AtomicExpr::AO__atomic_nand_fetch) + if (E->getOp() == AtomicExpr::AO__atomic_nand_fetch || + E->getOp() == AtomicExpr::AO__scoped_atomic_nand_fetch) Result = CGF.Builder.CreateNot(Result); CGF.Builder.CreateStore(Result, Dest); } @@ -862,20 +888,24 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) { llvm_unreachable("Already handled above with EmitAtomicInit!"); case AtomicExpr::AO__atomic_load_n: + case AtomicExpr::AO__scoped_atomic_load_n: case AtomicExpr::AO__c11_atomic_load: case AtomicExpr::AO__opencl_atomic_load: case AtomicExpr::AO__hip_atomic_load: break; case AtomicExpr::AO__atomic_load: + case AtomicExpr::AO__scoped_atomic_load: Dest = EmitPointerWithAlignment(E->getVal1()); break; case AtomicExpr::AO__atomic_store: + case AtomicExpr::AO__scoped_atomic_store: Val1 = EmitPointerWithAlignment(E->getVal1()); break; case AtomicExpr::AO__atomic_exchange: + case AtomicExpr::AO__scoped_atomic_exchange: Val1 = EmitPointerWithAlignment(E->getVal1()); Dest = EmitPointerWithAlignment(E->getVal2()); break; @@ -888,14 +918,19 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) { case AtomicExpr::AO__hip_atomic_compare_exchange_strong: case AtomicExpr::AO__opencl_atomic_compare_exchange_weak: case AtomicExpr::AO__opencl_atomic_compare_exchange_strong: + case AtomicExpr::AO__scoped_atomic_compare_exchange: + case AtomicExpr::AO__scoped_atomic_compare_exchange_n: Val1 = EmitPointerWithAlignment(E->getVal1()); - if (E->getOp() == AtomicExpr::AO__atomic_compare_exchange) + if (E->getOp() == AtomicExpr::AO__atomic_compare_exchange || + E->getOp() == AtomicExpr::AO__scoped_atomic_compare_exchange) Val2 = EmitPointerWithAlignment(E->getVal2()); else Val2 = EmitValToTemp(*this, E->getVal2()); OrderFail = EmitScalarExpr(E->getOrderFail()); if (E->getOp() == AtomicExpr::AO__atomic_compare_exchange_n || - E->getOp() == AtomicExpr::AO__atomic_compare_exchange) + E->getOp() == AtomicExpr::AO__atomic_compare_exchange || + E->getOp() == AtomicExpr::AO__scoped_atomic_compare_exchange_n || + E->getOp() == AtomicExpr::AO__scoped_atomic_compare_exchange) IsWeak = EmitScalarExpr(E->getWeak()); break; @@ -935,6 +970,14 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) { case AtomicExpr::AO__opencl_atomic_fetch_min: case AtomicExpr::AO__hip_atomic_fetch_max: case AtomicExpr::AO__hip_atomic_fetch_min: + case AtomicExpr::AO__scoped_atomic_fetch_add: + case AtomicExpr::AO__scoped_atomic_fetch_max: + case AtomicExpr::AO__scoped_atomic_fetch_min: + case AtomicExpr::AO__scoped_atomic_fetch_sub: + case AtomicExpr::AO__scoped_atomic_add_fetch: + case AtomicExpr::AO__scoped_atomic_max_fetch: + case AtomicExpr::AO__scoped_atomic_min_fetch: + case AtomicExpr::AO__scoped_atomic_sub_fetch: ShouldCastToIntPtrTy = !MemTy->isFloatingType(); [[fallthrough]]; @@ -964,6 +1007,16 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) { case AtomicExpr::AO__opencl_atomic_fetch_xor: case AtomicExpr::AO__opencl_atomic_store: case AtomicExpr::AO__opencl_atomic_exchange: + case AtomicExpr::AO__scoped_atomic_fetch_and: + case AtomicExpr::AO__scoped_atomic_fetch_nand: + case AtomicExpr::AO__scoped_atomic_fetch_or: + case AtomicExpr::AO__scoped_atomic_fetch_xor: + case AtomicExpr::AO__scoped_atomic_and_fetch: + case AtomicExpr::AO__scoped_atomic_nand_fetch: + case AtomicExpr::AO__scoped_atomic_or_fetch: + case AtomicExpr::AO__scoped_atomic_xor_fetch: + case AtomicExpr::AO__scoped_atomic_store_n: + case AtomicExpr::AO__scoped_atomic_exchange_n: Val1 = EmitValToTemp(*this, E->getVal1()); break; } @@ -1040,6 +1093,22 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) { case AtomicExpr::AO__opencl_atomic_fetch_or: case AtomicExpr::AO__opencl_atomic_fetch_sub: case AtomicExpr::AO__opencl_atomic_fetch_xor: + case AtomicExpr::AO__scoped_atomic_fetch_add: + case AtomicExpr::AO__scoped_atomic_fetch_and: + case AtomicExpr::AO__scoped_atomic_fetch_max: + case AtomicExpr::AO__scoped_atomic_fetch_min: + case AtomicExpr::AO__scoped_atomic_fetch_nand: + case AtomicExpr::AO__scoped_atomic_fetch_or: + case AtomicExpr::AO__scoped_atomic_fetch_sub: + case AtomicExpr::AO__scoped_atomic_fetch_xor: + case AtomicExpr::AO__scoped_atomic_add_fetch: + case AtomicExpr::AO__scoped_atomic_and_fetch: + case AtomicExpr::AO__scoped_atomic_max_fetch: + case AtomicExpr::AO__scoped_atomic_min_fetch: + case AtomicExpr::AO__scoped_atomic_nand_fetch: + case AtomicExpr::AO__scoped_atomic_or_fetch: + case AtomicExpr::AO__scoped_atomic_sub_fetch: + case AtomicExpr::AO__scoped_atomic_xor_fetch: // For these, only library calls for certain sizes exist. UseOptimizedLibcall = true; break; @@ -1048,6 +1117,10 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) { case AtomicExpr::AO__atomic_store: case AtomicExpr::AO__atomic_exchange: case AtomicExpr::AO__atomic_compare_exchange: + case AtomicExpr::AO__scoped_atomic_load: + case AtomicExpr::AO__scoped_atomic_store: + case AtomicExpr::AO__scoped_atomic_exchange: + case AtomicExpr::AO__scoped_atomic_compare_exchange: // Use the generic version if we don't know that the operand will be // suitably aligned for the optimized version. if (Misaligned) @@ -1072,6 +1145,10 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) { case AtomicExpr::AO__opencl_atomic_exchange: case AtomicExpr::AO__opencl_atomic_compare_exchange_weak: case AtomicExpr::AO__opencl_atomic_compare_exchange_strong: + case AtomicExpr::AO__scoped_atomic_load_n: + case AtomicExpr::AO__scoped_atomic_store_n: + case AtomicExpr::AO__scoped_atomic_exchange_n: + case AtomicExpr::AO__scoped_atomic_compare_exchange_n: // Only use optimized library calls for sizes for which they exist. // FIXME: Size == 16 optimized library functions exist too. if (Size == 1 || Size == 2 || Size == 4 || Size == 8) @@ -1132,6 +1209,8 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) { case AtomicExpr::AO__hip_atomic_compare_exchange_strong: case AtomicExpr::AO__opencl_atomic_compare_exchange_weak: case AtomicExpr::AO__opencl_atomic_compare_exchange_strong: + case AtomicExpr::AO__scoped_atomic_compare_exchange: + case AtomicExpr::AO__scoped_atomic_compare_exchange_n: LibCallName = "__atomic_compare_exchange"; RetTy = getContext().BoolTy; HaveRetTy = true; @@ -1151,6 +1230,8 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) { case AtomicExpr::AO__c11_atomic_exchange: case AtomicExpr::AO__hip_atomic_exchange: case AtomicExpr::AO__opencl_atomic_exchange: + case AtomicExpr::AO__scoped_atomic_exchange: + case AtomicExpr::AO__scoped_atomic_exchange_n: LibCallName = "__atomic_exchange"; AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(), MemTy, E->getExprLoc(), TInfo.Width); @@ -1162,6 +1243,8 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) { case AtomicExpr::AO__c11_atomic_store: case AtomicExpr::AO__hip_atomic_store: case AtomicExpr::AO__opencl_atomic_store: + case AtomicExpr::AO__scoped_atomic_store: + case AtomicExpr::AO__scoped_atomic_store_n: LibCallName = "__atomic_store"; RetTy = getContext().VoidTy; HaveRetTy = true; @@ -1175,17 +1258,21 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) { case AtomicExpr::AO__c11_atomic_load: case AtomicExpr::AO__hip_atomic_load: case AtomicExpr::AO__opencl_atomic_load: + case AtomicExpr::AO__scoped_atomic_load: + case AtomicExpr::AO__scoped_atomic_load_n: LibCallName = "__atomic_load"; break; // T __atomic_add_fetch_N(T *mem, T val, int order) // T __atomic_fetch_add_N(T *mem, T val, int order) case AtomicExpr::AO__atomic_add_fetch: + case AtomicExpr::AO__scoped_atomic_add_fetch: PostOp = llvm::Instruction::Add; [[fallthrough]]; case AtomicExpr::AO__atomic_fetch_add: case AtomicExpr::AO__c11_atomic_fetch_add: case AtomicExpr::AO__hip_atomic_fetch_add: case AtomicExpr::AO__opencl_atomic_fetch_add: + case AtomicExpr::AO__scoped_atomic_fetch_add: LibCallName = "__atomic_fetch_add"; AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(), LoweredMemTy, E->getExprLoc(), TInfo.Width); @@ -1193,12 +1280,14 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) { // T __atomic_and_fetch_N(T *mem, T val, int order) // T __atomic_fetch_and_N(T *mem, T val, int order) case AtomicExpr::AO__atomic_and_fetch: + case AtomicExpr::AO__scoped_atomic_and_fetch: PostOp = llvm::Instruction::And; [[fallthrough]]; case AtomicExpr::AO__atomic_fetch_and: case AtomicExpr::AO__c11_atomic_fetch_and: case AtomicExpr::AO__hip_atomic_fetch_and: case AtomicExpr::AO__opencl_atomic_fetch_and: + case AtomicExpr::AO__scoped_atomic_fetch_and: LibCallName = "__atomic_fetch_and"; AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(), MemTy, E->getExprLoc(), TInfo.Width); @@ -1206,12 +1295,14 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) { // T __atomic_or_fetch_N(T *mem, T val, int order) // T __atomic_fetch_or_N(T *mem, T val, int order) case AtomicExpr::AO__atomic_or_fetch: + case AtomicExpr::AO__scoped_atomic_or_fetch: PostOp = llvm::Instruction::Or; [[fallthrough]]; case AtomicExpr::AO__atomic_fetch_or: case AtomicExpr::AO__c11_atomic_fetch_or: case AtomicExpr::AO__hip_atomic_fetch_or: case AtomicExpr::AO__opencl_atomic_fetch_or: + case AtomicExpr::AO__scoped_atomic_fetch_or: LibCallName = "__atomic_fetch_or"; AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(), MemTy, E->getExprLoc(), TInfo.Width); @@ -1219,12 +1310,14 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) { // T __atomic_sub_fetch_N(T *mem, T val, int order) // T __atomic_fetch_sub_N(T *mem, T val, int order) case AtomicExpr::AO__atomic_sub_fetch: + case AtomicExpr::AO__scoped_atomic_sub_fetch: PostOp = llvm::Instruction::Sub; [[fallthrough]]; case AtomicExpr::AO__atomic_fetch_sub: case AtomicExpr::AO__c11_atomic_fetch_sub: case AtomicExpr::AO__hip_atomic_fetch_sub: case AtomicExpr::AO__opencl_atomic_fetch_sub: + case AtomicExpr::AO__scoped_atomic_fetch_sub: LibCallName = "__atomic_fetch_sub"; AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(), LoweredMemTy, E->getExprLoc(), TInfo.Width); @@ -1232,21 +1325,25 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) { // T __atomic_xor_fetch_N(T *mem, T val, int order) // T __atomic_fetch_xor_N(T *mem, T val, int order) case AtomicExpr::AO__atomic_xor_fetch: + case AtomicExpr::AO__scoped_atomic_xor_fetch: PostOp = llvm::Instruction::Xor; [[fallthrough]]; case AtomicExpr::AO__atomic_fetch_xor: case AtomicExpr::AO__c11_atomic_fetch_xor: case AtomicExpr::AO__hip_atomic_fetch_xor: case AtomicExpr::AO__opencl_atomic_fetch_xor: + case AtomicExpr::AO__scoped_atomic_fetch_xor: LibCallName = "__atomic_fetch_xor"; AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(), MemTy, E->getExprLoc(), TInfo.Width); break; case AtomicExpr::AO__atomic_min_fetch: + case AtomicExpr::AO__scoped_atomic_min_fetch: PostOpMinMax = true; [[fallthrough]]; case AtomicExpr::AO__atomic_fetch_min: case AtomicExpr::AO__c11_atomic_fetch_min: + case AtomicExpr::AO__scoped_atomic_fetch_min: case AtomicExpr::AO__hip_atomic_fetch_min: case AtomicExpr::AO__opencl_atomic_fetch_min: LibCallName = E->getValueType()->isSignedIntegerType() @@ -1256,12 +1353,14 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) { LoweredMemTy, E->getExprLoc(), TInfo.Width); break; case AtomicExpr::AO__atomic_max_fetch: + case AtomicExpr::AO__scoped_atomic_max_fetch: PostOpMinMax = true; [[fallthrough]]; case AtomicExpr::AO__atomic_fetch_max: case AtomicExpr::AO__c11_atomic_fetch_max: case AtomicExpr::AO__hip_atomic_fetch_max: case AtomicExpr::AO__opencl_atomic_fetch_max: + case AtomicExpr::AO__scoped_atomic_fetch_max: LibCallName = E->getValueType()->isSignedIntegerType() ? "__atomic_fetch_max" : "__atomic_fetch_umax"; @@ -1271,10 +1370,12 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) { // T __atomic_nand_fetch_N(T *mem, T val, int order) // T __atomic_fetch_nand_N(T *mem, T val, int order) case AtomicExpr::AO__atomic_nand_fetch: + case AtomicExpr::AO__scoped_atomic_nand_fetch: PostOp = llvm::Instruction::And; // the NOT is special cased below [[fallthrough]]; case AtomicExpr::AO__atomic_fetch_nand: case AtomicExpr::AO__c11_atomic_fetch_nand: + case AtomicExpr::AO__scoped_atomic_fetch_nand: LibCallName = "__atomic_fetch_nand"; AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(), MemTy, E->getExprLoc(), TInfo.Width); @@ -1331,7 +1432,8 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) { llvm::Value *LoadVal1 = Args[1].getRValue(*this).getScalarVal(); ResVal = Builder.CreateBinOp(PostOp, ResVal, LoadVal1); } - if (E->getOp() == AtomicExpr::AO__atomic_nand_fetch) + if (E->getOp() == AtomicExpr::AO__atomic_nand_fetch || + E->getOp() == AtomicExpr::AO__scoped_atomic_nand_fetch) ResVal = Builder.CreateNot(ResVal); Builder.CreateStore(ResVal, Dest.withElementType(ResVal->getType())); @@ -1348,12 +1450,16 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) { E->getOp() == AtomicExpr::AO__opencl_atomic_store || E->getOp() == AtomicExpr::AO__hip_atomic_store || E->getOp() == AtomicExpr::AO__atomic_store || - E->getOp() == AtomicExpr::AO__atomic_store_n; + E->getOp() == AtomicExpr::AO__atomic_store_n || + E->getOp() == AtomicExpr::AO__scoped_atomic_store || + E->getOp() == AtomicExpr::AO__scoped_atomic_store_n; bool IsLoad = E->getOp() == AtomicExpr::AO__c11_atomic_load || E->getOp() == AtomicExpr::AO__opencl_atomic_load || E->getOp() == AtomicExpr::AO__hip_atomic_load || E->getOp() == AtomicExpr::AO__atomic_load || - E->getOp() == AtomicExpr::AO__atomic_load_n; + E->getOp() == AtomicExpr::AO__atomic_load_n || + E->getOp() == AtomicExpr::AO__scoped_atomic_load || + E->getOp() == AtomicExpr::AO__scoped_atomic_load_n; if (isa(Order)) { auto ord = cast(Order)->getZExtValue(); @@ -1740,8 +1846,7 @@ std::pair AtomicInfo::EmitAtomicCompareExchangeOp( llvm::AtomicOrdering Success, llvm::AtomicOrdering Failure, bool IsWeak) { // Do the atomic store. Address Addr = getAtomicAddressAsAtomicIntPointer(); - auto *Inst = CGF.Builder.CreateAtomicCmpXchg(Addr.getPointer(), - ExpectedVal, DesiredVal, + auto *Inst = CGF.Builder.CreateAtomicCmpXchg(Addr, ExpectedVal, DesiredVal, Success, Failure); // Other decoration. Inst->setVolatile(LVal.isVolatileQualified()); diff --git a/clang/lib/CodeGen/CGBuilder.h b/clang/lib/CodeGen/CGBuilder.h index 68535920088c49b0018de7d72d3e0cc6d6bdb59c..bf5ab171d720d9b148544ac6467652a5efea0edb 100644 --- a/clang/lib/CodeGen/CGBuilder.h +++ b/clang/lib/CodeGen/CGBuilder.h @@ -126,25 +126,22 @@ public: return CreateAlignedStore(getInt1(Value), Addr, CharUnits::One()); } - // Temporarily use old signature; clang will be updated to an Address overload - // in a subsequent patch. llvm::AtomicCmpXchgInst * - CreateAtomicCmpXchg(llvm::Value *Ptr, llvm::Value *Cmp, llvm::Value *New, + CreateAtomicCmpXchg(Address Addr, llvm::Value *Cmp, llvm::Value *New, llvm::AtomicOrdering SuccessOrdering, llvm::AtomicOrdering FailureOrdering, llvm::SyncScope::ID SSID = llvm::SyncScope::System) { return CGBuilderBaseTy::CreateAtomicCmpXchg( - Ptr, Cmp, New, llvm::MaybeAlign(), SuccessOrdering, FailureOrdering, - SSID); + Addr.getPointer(), Cmp, New, Addr.getAlignment().getAsAlign(), + SuccessOrdering, FailureOrdering, SSID); } - // Temporarily use old signature; clang will be updated to an Address overload - // in a subsequent patch. llvm::AtomicRMWInst * - CreateAtomicRMW(llvm::AtomicRMWInst::BinOp Op, llvm::Value *Ptr, - llvm::Value *Val, llvm::AtomicOrdering Ordering, + CreateAtomicRMW(llvm::AtomicRMWInst::BinOp Op, Address Addr, llvm::Value *Val, + llvm::AtomicOrdering Ordering, llvm::SyncScope::ID SSID = llvm::SyncScope::System) { - return CGBuilderBaseTy::CreateAtomicRMW(Op, Ptr, Val, llvm::MaybeAlign(), + return CGBuilderBaseTy::CreateAtomicRMW(Op, Addr.getPointer(), Val, + Addr.getAlignment().getAsAlign(), Ordering, SSID); } diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index a0f4172002613773653f40e89dc3dc3640c63469..83d0a72aac5495f55d960f066bfff6bc4a201324 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -188,8 +188,7 @@ static Value *EmitFromInt(CodeGenFunction &CGF, llvm::Value *V, return V; } -static llvm::Value *CheckAtomicAlignment(CodeGenFunction &CGF, - const CallExpr *E) { +static Address CheckAtomicAlignment(CodeGenFunction &CGF, const CallExpr *E) { ASTContext &Ctx = CGF.getContext(); Address Ptr = CGF.EmitPointerWithAlignment(E->getArg(0)); unsigned Bytes = Ptr.getElementType()->isPointerTy() @@ -199,8 +198,10 @@ static llvm::Value *CheckAtomicAlignment(CodeGenFunction &CGF, if (Align % Bytes != 0) { DiagnosticsEngine &Diags = CGF.CGM.getDiags(); Diags.Report(E->getBeginLoc(), diag::warn_sync_op_misaligned); + // Force address to be at least naturally-aligned. + return Ptr.withAlignment(CharUnits::fromQuantity(Bytes)); } - return Ptr.getPointer(); + return Ptr; } /// Utility to insert an atomic instruction based on Intrinsic::ID @@ -215,19 +216,17 @@ static Value *MakeBinaryAtomicValue( E->getArg(0)->getType()->getPointeeType())); assert(CGF.getContext().hasSameUnqualifiedType(T, E->getArg(1)->getType())); - llvm::Value *DestPtr = CheckAtomicAlignment(CGF, E); + Address DestAddr = CheckAtomicAlignment(CGF, E); llvm::IntegerType *IntType = llvm::IntegerType::get( CGF.getLLVMContext(), CGF.getContext().getTypeSize(T)); - llvm::Value *Args[2]; - Args[0] = DestPtr; - Args[1] = CGF.EmitScalarExpr(E->getArg(1)); - llvm::Type *ValueType = Args[1]->getType(); - Args[1] = EmitToInt(CGF, Args[1], T, IntType); + llvm::Value *Val = CGF.EmitScalarExpr(E->getArg(1)); + llvm::Type *ValueType = Val->getType(); + Val = EmitToInt(CGF, Val, T, IntType); - llvm::Value *Result = CGF.Builder.CreateAtomicRMW( - Kind, Args[0], Args[1], Ordering); + llvm::Value *Result = + CGF.Builder.CreateAtomicRMW(Kind, DestAddr, Val, Ordering); return EmitFromInt(CGF, Result, T, ValueType); } @@ -270,20 +269,18 @@ static RValue EmitBinaryAtomicPost(CodeGenFunction &CGF, E->getArg(0)->getType()->getPointeeType())); assert(CGF.getContext().hasSameUnqualifiedType(T, E->getArg(1)->getType())); - llvm::Value *DestPtr = CheckAtomicAlignment(CGF, E); + Address DestAddr = CheckAtomicAlignment(CGF, E); llvm::IntegerType *IntType = llvm::IntegerType::get( CGF.getLLVMContext(), CGF.getContext().getTypeSize(T)); - llvm::Value *Args[2]; - Args[1] = CGF.EmitScalarExpr(E->getArg(1)); - llvm::Type *ValueType = Args[1]->getType(); - Args[1] = EmitToInt(CGF, Args[1], T, IntType); - Args[0] = DestPtr; + llvm::Value *Val = CGF.EmitScalarExpr(E->getArg(1)); + llvm::Type *ValueType = Val->getType(); + Val = EmitToInt(CGF, Val, T, IntType); llvm::Value *Result = CGF.Builder.CreateAtomicRMW( - Kind, Args[0], Args[1], llvm::AtomicOrdering::SequentiallyConsistent); - Result = CGF.Builder.CreateBinOp(Op, Result, Args[1]); + Kind, DestAddr, Val, llvm::AtomicOrdering::SequentiallyConsistent); + Result = CGF.Builder.CreateBinOp(Op, Result, Val); if (Invert) Result = CGF.Builder.CreateBinOp(llvm::Instruction::Xor, Result, @@ -309,20 +306,18 @@ static RValue EmitBinaryAtomicPost(CodeGenFunction &CGF, static Value *MakeAtomicCmpXchgValue(CodeGenFunction &CGF, const CallExpr *E, bool ReturnBool) { QualType T = ReturnBool ? E->getArg(1)->getType() : E->getType(); - llvm::Value *DestPtr = CheckAtomicAlignment(CGF, E); + Address DestAddr = CheckAtomicAlignment(CGF, E); llvm::IntegerType *IntType = llvm::IntegerType::get( CGF.getLLVMContext(), CGF.getContext().getTypeSize(T)); - Value *Args[3]; - Args[0] = DestPtr; - Args[1] = CGF.EmitScalarExpr(E->getArg(1)); - llvm::Type *ValueType = Args[1]->getType(); - Args[1] = EmitToInt(CGF, Args[1], T, IntType); - Args[2] = EmitToInt(CGF, CGF.EmitScalarExpr(E->getArg(2)), T, IntType); + Value *Cmp = CGF.EmitScalarExpr(E->getArg(1)); + llvm::Type *ValueType = Cmp->getType(); + Cmp = EmitToInt(CGF, Cmp, T, IntType); + Value *New = EmitToInt(CGF, CGF.EmitScalarExpr(E->getArg(2)), T, IntType); Value *Pair = CGF.Builder.CreateAtomicCmpXchg( - Args[0], Args[1], Args[2], llvm::AtomicOrdering::SequentiallyConsistent, + DestAddr, Cmp, New, llvm::AtomicOrdering::SequentiallyConsistent, llvm::AtomicOrdering::SequentiallyConsistent); if (ReturnBool) // Extract boolean success flag and zext it to int. @@ -358,7 +353,8 @@ Value *EmitAtomicCmpXchgForMSIntrin(CodeGenFunction &CGF, const CallExpr *E, assert(CGF.getContext().hasSameUnqualifiedType(E->getType(), E->getArg(2)->getType())); - auto *Destination = CGF.EmitScalarExpr(E->getArg(0)); + Address DestAddr = CheckAtomicAlignment(CGF, E); + auto *Comparand = CGF.EmitScalarExpr(E->getArg(2)); auto *Exchange = CGF.EmitScalarExpr(E->getArg(1)); @@ -372,8 +368,7 @@ Value *EmitAtomicCmpXchgForMSIntrin(CodeGenFunction &CGF, const CallExpr *E, // _Interlocked* operations in the future, we will have to remove the volatile // marker. auto *Result = CGF.Builder.CreateAtomicCmpXchg( - Destination, Comparand, Exchange, - SuccessOrdering, FailureOrdering); + DestAddr, Comparand, Exchange, SuccessOrdering, FailureOrdering); Result->setVolatile(true); return CGF.Builder.CreateExtractValue(Result, 0); } @@ -386,29 +381,34 @@ Value *EmitAtomicCmpXchgForMSIntrin(CodeGenFunction &CGF, const CallExpr *E, // __int64 _ExchangeHigh, // __int64 _ExchangeLow, // __int64 * _ComparandResult); +// +// Note that Destination is assumed to be at least 16-byte aligned, despite +// being typed int64. + static Value *EmitAtomicCmpXchg128ForMSIntrin(CodeGenFunction &CGF, const CallExpr *E, AtomicOrdering SuccessOrdering) { assert(E->getNumArgs() == 4); - llvm::Value *Destination = CGF.EmitScalarExpr(E->getArg(0)); + llvm::Value *DestPtr = CGF.EmitScalarExpr(E->getArg(0)); llvm::Value *ExchangeHigh = CGF.EmitScalarExpr(E->getArg(1)); llvm::Value *ExchangeLow = CGF.EmitScalarExpr(E->getArg(2)); - llvm::Value *ComparandPtr = CGF.EmitScalarExpr(E->getArg(3)); + Address ComparandAddr = CGF.EmitPointerWithAlignment(E->getArg(3)); - assert(Destination->getType()->isPointerTy()); + assert(DestPtr->getType()->isPointerTy()); assert(!ExchangeHigh->getType()->isPointerTy()); assert(!ExchangeLow->getType()->isPointerTy()); - assert(ComparandPtr->getType()->isPointerTy()); // For Release ordering, the failure ordering should be Monotonic. auto FailureOrdering = SuccessOrdering == AtomicOrdering::Release ? AtomicOrdering::Monotonic : SuccessOrdering; - // Convert to i128 pointers and values. + // Convert to i128 pointers and values. Alignment is also overridden for + // destination pointer. llvm::Type *Int128Ty = llvm::IntegerType::get(CGF.getLLVMContext(), 128); - Address ComparandResult(ComparandPtr, Int128Ty, - CGF.getContext().toCharUnitsFromBits(128)); + Address DestAddr(DestPtr, Int128Ty, + CGF.getContext().toCharUnitsFromBits(128)); + ComparandAddr = ComparandAddr.withElementType(Int128Ty); // (((i128)hi) << 64) | ((i128)lo) ExchangeHigh = CGF.Builder.CreateZExt(ExchangeHigh, Int128Ty); @@ -418,9 +418,9 @@ static Value *EmitAtomicCmpXchg128ForMSIntrin(CodeGenFunction &CGF, llvm::Value *Exchange = CGF.Builder.CreateOr(ExchangeHigh, ExchangeLow); // Load the comparand for the instruction. - llvm::Value *Comparand = CGF.Builder.CreateLoad(ComparandResult); + llvm::Value *Comparand = CGF.Builder.CreateLoad(ComparandAddr); - auto *CXI = CGF.Builder.CreateAtomicCmpXchg(Destination, Comparand, Exchange, + auto *CXI = CGF.Builder.CreateAtomicCmpXchg(DestAddr, Comparand, Exchange, SuccessOrdering, FailureOrdering); // The atomic instruction is marked volatile for consistency with MSVC. This @@ -431,7 +431,7 @@ static Value *EmitAtomicCmpXchg128ForMSIntrin(CodeGenFunction &CGF, // Store the result as an outparameter. CGF.Builder.CreateStore(CGF.Builder.CreateExtractValue(CXI, 0), - ComparandResult); + ComparandAddr); // Get the success boolean and zero extend it to i8. Value *Success = CGF.Builder.CreateExtractValue(CXI, 1); @@ -443,24 +443,21 @@ static Value *EmitAtomicIncrementValue(CodeGenFunction &CGF, const CallExpr *E, assert(E->getArg(0)->getType()->isPointerType()); auto *IntTy = CGF.ConvertType(E->getType()); + Address DestAddr = CheckAtomicAlignment(CGF, E); auto *Result = CGF.Builder.CreateAtomicRMW( - AtomicRMWInst::Add, - CGF.EmitScalarExpr(E->getArg(0)), - ConstantInt::get(IntTy, 1), - Ordering); + AtomicRMWInst::Add, DestAddr, ConstantInt::get(IntTy, 1), Ordering); return CGF.Builder.CreateAdd(Result, ConstantInt::get(IntTy, 1)); } -static Value *EmitAtomicDecrementValue(CodeGenFunction &CGF, const CallExpr *E, +static Value *EmitAtomicDecrementValue( + CodeGenFunction &CGF, const CallExpr *E, AtomicOrdering Ordering = AtomicOrdering::SequentiallyConsistent) { assert(E->getArg(0)->getType()->isPointerType()); auto *IntTy = CGF.ConvertType(E->getType()); + Address DestAddr = CheckAtomicAlignment(CGF, E); auto *Result = CGF.Builder.CreateAtomicRMW( - AtomicRMWInst::Sub, - CGF.EmitScalarExpr(E->getArg(0)), - ConstantInt::get(IntTy, 1), - Ordering); + AtomicRMWInst::Sub, DestAddr, ConstantInt::get(IntTy, 1), Ordering); return CGF.Builder.CreateSub(Result, ConstantInt::get(IntTy, 1)); } @@ -1215,8 +1212,7 @@ static llvm::Value *EmitBitTestIntrinsic(CodeGenFunction &CGF, Mask = CGF.Builder.CreateNot(Mask); RMWOp = llvm::AtomicRMWInst::And; } - OldByte = CGF.Builder.CreateAtomicRMW(RMWOp, ByteAddr.getPointer(), Mask, - Ordering); + OldByte = CGF.Builder.CreateAtomicRMW(RMWOp, ByteAddr, Mask, Ordering); } else { // Emit a plain load for the non-interlocked intrinsics. OldByte = CGF.Builder.CreateLoad(ByteAddr, "bittest.byte"); @@ -4456,14 +4452,13 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, case Builtin::BI__sync_lock_release_4: case Builtin::BI__sync_lock_release_8: case Builtin::BI__sync_lock_release_16: { - Value *Ptr = CheckAtomicAlignment(*this, E); + Address Ptr = CheckAtomicAlignment(*this, E); QualType ElTy = E->getArg(0)->getType()->getPointeeType(); - CharUnits StoreSize = getContext().getTypeSizeInChars(ElTy); - llvm::Type *ITy = - llvm::IntegerType::get(getLLVMContext(), StoreSize.getQuantity() * 8); + + llvm::Type *ITy = llvm::IntegerType::get(getLLVMContext(), + getContext().getTypeSize(ElTy)); llvm::StoreInst *Store = - Builder.CreateAlignedStore(llvm::Constant::getNullValue(ITy), Ptr, - StoreSize); + Builder.CreateStore(llvm::Constant::getNullValue(ITy), Ptr); Store->setAtomic(llvm::AtomicOrdering::Release); return RValue::get(nullptr); } @@ -4514,7 +4509,9 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, bool Volatile = PtrTy->castAs()->getPointeeType().isVolatileQualified(); - Value *Ptr = EmitScalarExpr(E->getArg(0)); + Address Ptr = + EmitPointerWithAlignment(E->getArg(0)).withElementType(Int8Ty); + Value *NewVal = Builder.getInt8(1); Value *Order = EmitScalarExpr(E->getArg(1)); if (isa(Order)) { @@ -5035,7 +5032,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, llvm::IntegerType *IntType = IntegerType::get( getLLVMContext(), getContext().getTypeSize(E->getType())); - llvm::Value *Destination = EmitScalarExpr(E->getArg(0)); + Address DestAddr = CheckAtomicAlignment(*this, E); llvm::Value *Exchange = EmitScalarExpr(E->getArg(1)); RTy = Exchange->getType(); @@ -5048,7 +5045,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, BuiltinID == Builtin::BI_InterlockedCompareExchangePointer_nf ? AtomicOrdering::Monotonic : AtomicOrdering::SequentiallyConsistent; - auto Result = Builder.CreateAtomicCmpXchg(Destination, Comparand, Exchange, + auto Result = Builder.CreateAtomicCmpXchg(DestAddr, Comparand, Exchange, Ordering, Ordering); Result->setVolatile(true); @@ -10214,6 +10211,22 @@ Value *CodeGenFunction::EmitAArch64SVEBuiltinExpr(unsigned BuiltinID, switch (BuiltinID) { default: return nullptr; + + case SVE::BI__builtin_sve_svreinterpret_b: { + auto SVCountTy = + llvm::TargetExtType::get(getLLVMContext(), "aarch64.svcount"); + Function *CastFromSVCountF = + CGM.getIntrinsic(Intrinsic::aarch64_sve_convert_to_svbool, SVCountTy); + return Builder.CreateCall(CastFromSVCountF, Ops[0]); + } + case SVE::BI__builtin_sve_svreinterpret_c: { + auto SVCountTy = + llvm::TargetExtType::get(getLLVMContext(), "aarch64.svcount"); + Function *CastToSVCountF = + CGM.getIntrinsic(Intrinsic::aarch64_sve_convert_from_svbool, SVCountTy); + return Builder.CreateCall(CastToSVCountF, Ops[0]); + } + case SVE::BI__builtin_sve_svpsel_lane_b8: case SVE::BI__builtin_sve_svpsel_lane_b16: case SVE::BI__builtin_sve_svpsel_lane_b32: @@ -11901,12 +11914,12 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID, } case clang::AArch64::BI_InterlockedAdd: { - Value *Arg0 = EmitScalarExpr(E->getArg(0)); - Value *Arg1 = EmitScalarExpr(E->getArg(1)); - AtomicRMWInst *RMWI = Builder.CreateAtomicRMW( - AtomicRMWInst::Add, Arg0, Arg1, - llvm::AtomicOrdering::SequentiallyConsistent); - return Builder.CreateAdd(RMWI, Arg1); + Address DestAddr = CheckAtomicAlignment(*this, E); + Value *Val = EmitScalarExpr(E->getArg(1)); + AtomicRMWInst *RMWI = + Builder.CreateAtomicRMW(AtomicRMWInst::Add, DestAddr, Val, + llvm::AtomicOrdering::SequentiallyConsistent); + return Builder.CreateAdd(RMWI, Val); } } @@ -18219,7 +18232,7 @@ Value *CodeGenFunction::EmitAMDGPUBuiltinExpr(unsigned BuiltinID, break; } - Value *Ptr = EmitScalarExpr(E->getArg(0)); + Address Ptr = CheckAtomicAlignment(*this, E); Value *Val = EmitScalarExpr(E->getArg(1)); ProcessOrderScopeAMDGCN(EmitScalarExpr(E->getArg(2)), @@ -19108,9 +19121,10 @@ Value *CodeGenFunction::EmitNVPTXBuiltinExpr(unsigned BuiltinID, case NVPTX::BI__nvvm_atom_add_gen_f: case NVPTX::BI__nvvm_atom_add_gen_d: { - Value *Ptr = EmitScalarExpr(E->getArg(0)); + Address DestAddr = EmitPointerWithAlignment(E->getArg(0)); Value *Val = EmitScalarExpr(E->getArg(1)); - return Builder.CreateAtomicRMW(llvm::AtomicRMWInst::FAdd, Ptr, Val, + + return Builder.CreateAtomicRMW(llvm::AtomicRMWInst::FAdd, DestAddr, Val, AtomicOrdering::SequentiallyConsistent); } diff --git a/clang/lib/CodeGen/CGCUDANV.cpp b/clang/lib/CodeGen/CGCUDANV.cpp index 66147f656071f5383a54effe15652293b49f49b2..520b0c4f117673f76b93279d7bdaa0f26a21784f 100644 --- a/clang/lib/CodeGen/CGCUDANV.cpp +++ b/clang/lib/CodeGen/CGCUDANV.cpp @@ -1132,26 +1132,39 @@ void CGNVCUDARuntime::createOffloadingEntries() { for (KernelInfo &I : EmittedKernels) llvm::offloading::emitOffloadingEntry( M, KernelHandles[I.Kernel->getName()], - getDeviceSideName(cast(I.D)), 0, - DeviceVarFlags::OffloadGlobalEntry, Section); + getDeviceSideName(cast(I.D)), /*Flags=*/0, /*Data=*/0, + llvm::offloading::OffloadGlobalEntry, Section); for (VarInfo &I : DeviceVars) { uint64_t VarSize = CGM.getDataLayout().getTypeAllocSize(I.Var->getValueType()); + int32_t Flags = + (I.Flags.isExtern() + ? static_cast(llvm::offloading::OffloadGlobalExtern) + : 0) | + (I.Flags.isConstant() + ? static_cast(llvm::offloading::OffloadGlobalConstant) + : 0) | + (I.Flags.isNormalized() + ? static_cast(llvm::offloading::OffloadGlobalNormalized) + : 0); if (I.Flags.getKind() == DeviceVarFlags::Variable) { llvm::offloading::emitOffloadingEntry( M, I.Var, getDeviceSideName(I.D), VarSize, - I.Flags.isManaged() ? DeviceVarFlags::OffloadGlobalManagedEntry - : DeviceVarFlags::OffloadGlobalEntry, - Section); + (I.Flags.isManaged() ? llvm::offloading::OffloadGlobalManagedEntry + : llvm::offloading::OffloadGlobalEntry) | + Flags, + /*Data=*/0, Section); } else if (I.Flags.getKind() == DeviceVarFlags::Surface) { llvm::offloading::emitOffloadingEntry( M, I.Var, getDeviceSideName(I.D), VarSize, - DeviceVarFlags::OffloadGlobalSurfaceEntry, Section); + llvm::offloading::OffloadGlobalSurfaceEntry | Flags, + I.Flags.getSurfTexType(), Section); } else if (I.Flags.getKind() == DeviceVarFlags::Texture) { llvm::offloading::emitOffloadingEntry( M, I.Var, getDeviceSideName(I.D), VarSize, - DeviceVarFlags::OffloadGlobalTextureEntry, Section); + llvm::offloading::OffloadGlobalTextureEntry | Flags, + I.Flags.getSurfTexType(), Section); } } } diff --git a/clang/lib/CodeGen/CGCUDARuntime.h b/clang/lib/CodeGen/CGCUDARuntime.h index 9a9c6d26cc63c40c4d74c39337afb77563fa4daa..c7af8f1cf0fe95ee7d1e7ded0cec6507198f6967 100644 --- a/clang/lib/CodeGen/CGCUDARuntime.h +++ b/clang/lib/CodeGen/CGCUDARuntime.h @@ -17,6 +17,7 @@ #include "clang/AST/GlobalDecl.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Frontend/Offloading/Utility.h" #include "llvm/IR/GlobalValue.h" namespace llvm { @@ -52,19 +53,6 @@ public: Texture, // Builtin texture }; - /// The kind flag for an offloading entry. - enum OffloadEntryKindFlag : uint32_t { - /// Mark the entry as a global entry. This indicates the presense of a - /// kernel if the size field is zero and a variable otherwise. - OffloadGlobalEntry = 0x0, - /// Mark the entry as a managed global variable. - OffloadGlobalManagedEntry = 0x1, - /// Mark the entry as a surface variable. - OffloadGlobalSurfaceEntry = 0x2, - /// Mark the entry as a texture variable. - OffloadGlobalTextureEntry = 0x3, - }; - private: unsigned Kind : 2; unsigned Extern : 1; diff --git a/clang/lib/CodeGen/CGCall.h b/clang/lib/CodeGen/CGCall.h index aee86a3242fd3f4468740464fc13f09be9e0d06b..1c0d15dc932ad80f8ca6a684bcbf3380857c0f59 100644 --- a/clang/lib/CodeGen/CGCall.h +++ b/clang/lib/CodeGen/CGCall.h @@ -20,6 +20,7 @@ #include "clang/AST/CanonicalType.h" #include "clang/AST/GlobalDecl.h" #include "clang/AST/Type.h" +#include "llvm/ADT/STLForwardCompat.h" #include "llvm/IR/Value.h" namespace llvm { @@ -406,15 +407,13 @@ enum class FnInfoOpts { }; inline FnInfoOpts operator|(FnInfoOpts A, FnInfoOpts B) { - return static_cast( - static_cast>(A) | - static_cast>(B)); + return static_cast(llvm::to_underlying(A) | + llvm::to_underlying(B)); } inline FnInfoOpts operator&(FnInfoOpts A, FnInfoOpts B) { - return static_cast( - static_cast>(A) & - static_cast>(B)); + return static_cast(llvm::to_underlying(A) & + llvm::to_underlying(B)); } inline FnInfoOpts operator|=(FnInfoOpts A, FnInfoOpts B) { diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index 602e325e560f98d465c4417f10cddb6878eed87a..37d7a6755d3908c051440edb25f38a4f1c02d216 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -69,29 +69,6 @@ static uint32_t getDeclAlignIfRequired(const Decl *D, const ASTContext &Ctx) { return D->hasAttr() ? D->getMaxAlignment() : 0; } -/// Given a VarDecl corresponding to either the definition or -/// declaration of a C++ static data member, if it has a constant -/// initializer and is evaluatable, return the evaluated value. -/// Returns std::nullopt otherwise. -static std::optional -evaluateConstantInitializer(const clang::VarDecl *VD, - const clang::ASTContext &Ctx) { - assert(VD != nullptr); - - if (!VD->isStaticDataMember()) - return std::nullopt; - - if (!VD->isUsableInConstantExpressions(Ctx)) - return std::nullopt; - - auto const *InitExpr = VD->getAnyInitializer(); - Expr::EvalResult Result; - if (!InitExpr->EvaluateAsConstantExpr(Result, Ctx)) - return std::nullopt; - - return Result.Val; -} - CGDebugInfo::CGDebugInfo(CodeGenModule &CGM) : CGM(CGM), DebugKind(CGM.getCodeGenOpts().getDebugInfo()), DebugTypeExtRefs(CGM.getCodeGenOpts().DebugTypeExtRefs), @@ -577,14 +554,16 @@ void CGDebugInfo::CreateCompileUnit() { // If the main file name provided is identical to the input file name, and // if the input file is a preprocessed source, use the module name for // debug info. The module name comes from the name specified in the first - // linemarker if the input is a preprocessed source. + // linemarker if the input is a preprocessed source. In this case we don't + // know the content to compute a checksum. if (MainFile->getName() == MainFileName && FrontendOptions::getInputKindForExtension( MainFile->getName().rsplit('.').second) - .isPreprocessed()) + .isPreprocessed()) { MainFileName = CGM.getModule().getName().str(); - - CSKind = computeChecksum(SM.getMainFileID(), Checksum); + } else { + CSKind = computeChecksum(SM.getMainFileID(), Checksum); + } } llvm::dwarf::SourceLanguage LangTag; @@ -1724,7 +1703,6 @@ CGDebugInfo::CreateRecordStaticField(const VarDecl *Var, llvm::DIType *RecordTy, llvm::DIDerivedType *GV = DBuilder.createStaticMemberType( RecordTy, VName, VUnit, LineNumber, VTy, Flags, C, Tag, Align); StaticDataMemberCache[Var->getCanonicalDecl()].reset(GV); - StaticDataMemberDefinitionsToEmit.push_back(Var->getCanonicalDecl()); return GV; } @@ -5628,41 +5606,6 @@ void CGDebugInfo::EmitGlobalVariable(const ValueDecl *VD, const APValue &Init) { TemplateParameters, Align)); } -void CGDebugInfo::EmitGlobalVariable(const VarDecl *VD) { - assert(CGM.getCodeGenOpts().hasReducedDebugInfo()); - if (VD->hasAttr()) - return; - - const auto CacheIt = DeclCache.find(VD); - if (CacheIt != DeclCache.end()) - return; - - const auto InitVal = evaluateConstantInitializer(VD, CGM.getContext()); - if (!InitVal) - return; - - llvm::DIFile *Unit = nullptr; - llvm::DIScope *DContext = nullptr; - unsigned LineNo; - StringRef DeclName, LinkageName; - QualType T; - llvm::MDTuple *TemplateParameters = nullptr; - collectVarDeclProps(VD, Unit, LineNo, T, DeclName, LinkageName, - TemplateParameters, DContext); - - auto Align = getDeclAlignIfRequired(VD, CGM.getContext()); - llvm::DINodeArray Annotations = CollectBTFDeclTagAnnotations(VD); - llvm::DIExpression *InitExpr = createConstantValueExpression(VD, *InitVal); - - // Omit linkage name for variable definitions that represent constants. - // There hasn't been a need from consumers yet to have it attached. - DeclCache[VD].reset(DBuilder.createGlobalVariableExpression( - TheCU, DeclName, /* LinkageName */ {}, Unit, LineNo, - getOrCreateType(T, Unit), true, true, InitExpr, - getOrCreateStaticDataMemberDeclarationOrNull(VD), TemplateParameters, - Align, Annotations)); -} - void CGDebugInfo::EmitExternalVariable(llvm::GlobalVariable *Var, const VarDecl *D) { assert(CGM.getCodeGenOpts().hasReducedDebugInfo()); @@ -5867,20 +5810,6 @@ void CGDebugInfo::setDwoId(uint64_t Signature) { } void CGDebugInfo::finalize() { - // We can't use a for-each here because `EmitGlobalVariable` - // may push new decls into `StaticDataMemberDefinitionsToEmit`, - // which would invalidate any iterator. - for (size_t i = 0; i < StaticDataMemberDefinitionsToEmit.size(); ++i) { - auto const *VD = StaticDataMemberDefinitionsToEmit[i]; - - assert(VD && VD->isStaticDataMember()); - - if (DeclCache.contains(VD)) - continue; - - EmitGlobalVariable(VD); - } - // Creating types might create further types - invalidating the current // element and the size(), so don't cache/reference them. for (size_t i = 0; i != ObjCInterfaceCache.size(); ++i) { diff --git a/clang/lib/CodeGen/CGDebugInfo.h b/clang/lib/CodeGen/CGDebugInfo.h index 3e4c133b7f2b9f1917b8691311f6fb6d21b4d94e..7b60e94555d0608639789aacbb309843c1cf6fe4 100644 --- a/clang/lib/CodeGen/CGDebugInfo.h +++ b/clang/lib/CodeGen/CGDebugInfo.h @@ -161,9 +161,6 @@ class CGDebugInfo { llvm::DenseMap> StaticDataMemberCache; - /// Keeps track of static data members for which we should emit a definition. - std::vector StaticDataMemberDefinitionsToEmit; - using ParamDecl2StmtTy = llvm::DenseMap; using Param2DILocTy = llvm::DenseMap; @@ -529,9 +526,6 @@ public: /// Emit a constant global variable's debug info. void EmitGlobalVariable(const ValueDecl *VD, const APValue &Init); - /// Emit debug-info for a variable with a constant initializer. - void EmitGlobalVariable(const VarDecl *VD); - /// Emit information about an external variable. void EmitExternalVariable(llvm::GlobalVariable *GV, const VarDecl *Decl); diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 9d1f1a58f9e1c5e85e8b83b4db91649718ba804b..69cf7f76be9a7091742e3498c1a904ec838eafe5 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -3833,6 +3833,33 @@ static QualType getFixedSizeElementType(const ASTContext &ctx, return eltType; } +static bool hasBPFPreserveStaticOffset(const RecordDecl *D) { + return D && D->hasAttr(); +} + +static bool hasBPFPreserveStaticOffset(const Expr *E) { + if (!E) + return false; + QualType PointeeType = E->getType()->getPointeeType(); + if (PointeeType.isNull()) + return false; + if (const auto *BaseDecl = PointeeType->getAsRecordDecl()) + return hasBPFPreserveStaticOffset(BaseDecl); + return false; +} + +// Wraps Addr with a call to llvm.preserve.static.offset intrinsic. +static Address wrapWithBPFPreserveStaticOffset(CodeGenFunction &CGF, + Address &Addr) { + if (!CGF.getTarget().getTriple().isBPF()) + return Addr; + + llvm::Function *Fn = + CGF.CGM.getIntrinsic(llvm::Intrinsic::preserve_static_offset); + llvm::CallInst *Call = CGF.Builder.CreateCall(Fn, {Addr.getPointer()}); + return Address(Call, Addr.getElementType(), Addr.getAlignment()); +} + /// Given an array base, check whether its member access belongs to a record /// with preserve_access_index attribute or not. static bool IsPreserveAIArrayBase(CodeGenFunction &CGF, const Expr *ArrayBase) { @@ -3894,6 +3921,9 @@ static Address emitArraySubscriptGEP(CodeGenFunction &CGF, Address addr, CharUnits eltAlign = getArrayElementAlign(addr.getAlignment(), indices.back(), eltSize); + if (hasBPFPreserveStaticOffset(Base)) + addr = wrapWithBPFPreserveStaticOffset(CGF, addr); + llvm::Value *eltPtr; auto LastIndex = dyn_cast(indices.back()); if (!LastIndex || @@ -4522,6 +4552,8 @@ LValue CodeGenFunction::EmitLValueForField(LValue base, Address Addr = base.getAddress(*this); unsigned Idx = RL.getLLVMFieldNo(field); const RecordDecl *rec = field->getParent(); + if (hasBPFPreserveStaticOffset(rec)) + Addr = wrapWithBPFPreserveStaticOffset(*this, Addr); if (!UseVolatile) { if (!IsInPreservedAIRegion && (!getDebugInfo() || !rec->hasAttr())) { @@ -4594,6 +4626,8 @@ LValue CodeGenFunction::EmitLValueForField(LValue base, } Address addr = base.getAddress(*this); + if (hasBPFPreserveStaticOffset(rec)) + addr = wrapWithBPFPreserveStaticOffset(*this, addr); if (auto *ClassDef = dyn_cast(rec)) { if (CGM.getCodeGenOpts().StrictVTablePointers && ClassDef->isDynamicClass()) { diff --git a/clang/lib/CodeGen/CGExprComplex.cpp b/clang/lib/CodeGen/CGExprComplex.cpp index f3cbd1d0451ebe4f8d15b24306fb685d763430d2..e532794b71bdb4a9beed87128d409b47dd06263a 100644 --- a/clang/lib/CodeGen/CGExprComplex.cpp +++ b/clang/lib/CodeGen/CGExprComplex.cpp @@ -275,6 +275,10 @@ public: ComplexPairTy EmitBinSub(const BinOpInfo &Op); ComplexPairTy EmitBinMul(const BinOpInfo &Op); ComplexPairTy EmitBinDiv(const BinOpInfo &Op); + ComplexPairTy EmitAlgebraicDiv(llvm::Value *A, llvm::Value *B, llvm::Value *C, + llvm::Value *D); + ComplexPairTy EmitRangeReductionDiv(llvm::Value *A, llvm::Value *B, + llvm::Value *C, llvm::Value *D); ComplexPairTy EmitComplexBinOpLibCall(StringRef LibCallName, const BinOpInfo &Op); @@ -781,6 +785,10 @@ ComplexPairTy ComplexExprEmitter::EmitBinMul(const BinOpInfo &Op) { ResR = Builder.CreateFSub(AC, BD, "mul_r"); ResI = Builder.CreateFAdd(AD, BC, "mul_i"); + if (Op.FPFeatures.getComplexRange() == LangOptions::CX_Limited || + Op.FPFeatures.getComplexRange() == LangOptions::CX_Fortran) + return ComplexPairTy(ResR, ResI); + // Emit the test for the real part becoming NaN and create a branch to // handle it. We test for NaN by comparing the number to itself. Value *IsRNaN = Builder.CreateFCmpUNO(ResR, ResR, "isnan_cmp"); @@ -846,23 +854,139 @@ ComplexPairTy ComplexExprEmitter::EmitBinMul(const BinOpInfo &Op) { return ComplexPairTy(ResR, ResI); } +ComplexPairTy ComplexExprEmitter::EmitAlgebraicDiv(llvm::Value *LHSr, + llvm::Value *LHSi, + llvm::Value *RHSr, + llvm::Value *RHSi) { + // (a+ib) / (c+id) = ((ac+bd)/(cc+dd)) + i((bc-ad)/(cc+dd)) + llvm::Value *DSTr, *DSTi; + + llvm::Value *AC = Builder.CreateFMul(LHSr, RHSr); // a*c + llvm::Value *BD = Builder.CreateFMul(LHSi, RHSi); // b*d + llvm::Value *ACpBD = Builder.CreateFAdd(AC, BD); // ac+bd + + llvm::Value *CC = Builder.CreateFMul(RHSr, RHSr); // c*c + llvm::Value *DD = Builder.CreateFMul(RHSi, RHSi); // d*d + llvm::Value *CCpDD = Builder.CreateFAdd(CC, DD); // cc+dd + + llvm::Value *BC = Builder.CreateFMul(LHSi, RHSr); // b*c + llvm::Value *AD = Builder.CreateFMul(LHSr, RHSi); // a*d + llvm::Value *BCmAD = Builder.CreateFSub(BC, AD); // bc-ad + + DSTr = Builder.CreateFDiv(ACpBD, CCpDD); + DSTi = Builder.CreateFDiv(BCmAD, CCpDD); + return ComplexPairTy(DSTr, DSTi); +} + +// EmitFAbs - Emit a call to @llvm.fabs. +static llvm::Value *EmitllvmFAbs(CodeGenFunction &CGF, llvm::Value *Value) { + llvm::Function *Func = + CGF.CGM.getIntrinsic(llvm::Intrinsic::fabs, Value->getType()); + llvm::Value *Call = CGF.Builder.CreateCall(Func, Value); + return Call; +} + +// EmitRangeReductionDiv - Implements Smith's algorithm for complex division. +// SMITH, R. L. Algorithm 116: Complex division. Commun. ACM 5, 8 (1962). +ComplexPairTy ComplexExprEmitter::EmitRangeReductionDiv(llvm::Value *LHSr, + llvm::Value *LHSi, + llvm::Value *RHSr, + llvm::Value *RHSi) { + // (a + ib) / (c + id) = (e + if) + llvm::Value *FAbsRHSr = EmitllvmFAbs(CGF, RHSr); // |c| + llvm::Value *FAbsRHSi = EmitllvmFAbs(CGF, RHSi); // |d| + // |c| >= |d| + llvm::Value *IsR = Builder.CreateFCmpUGT(FAbsRHSr, FAbsRHSi, "abs_cmp"); + + llvm::BasicBlock *TrueBB = + CGF.createBasicBlock("abs_rhsr_greater_or_equal_abs_rhsi"); + llvm::BasicBlock *FalseBB = + CGF.createBasicBlock("abs_rhsr_less_than_abs_rhsi"); + llvm::BasicBlock *ContBB = CGF.createBasicBlock("complex_div"); + Builder.CreateCondBr(IsR, TrueBB, FalseBB); + + CGF.EmitBlock(TrueBB); + // abs(c) >= abs(d) + // r = d/c + // tmp = c + rd + // e = (a + br)/tmp + // f = (b - ar)/tmp + llvm::Value *DdC = Builder.CreateFDiv(RHSi, RHSr); // r=d/c + + llvm::Value *RD = Builder.CreateFMul(DdC, RHSi); // rd + llvm::Value *CpRD = Builder.CreateFAdd(RHSr, RD); // tmp=c+rd + + llvm::Value *T3 = Builder.CreateFMul(LHSi, DdC); // br + llvm::Value *T4 = Builder.CreateFAdd(LHSr, T3); // a+br + llvm::Value *DSTTr = Builder.CreateFDiv(T4, CpRD); // (a+br)/tmp + + llvm::Value *T5 = Builder.CreateFMul(LHSr, DdC); // ar + llvm::Value *T6 = Builder.CreateFSub(LHSi, T5); // b-ar + llvm::Value *DSTTi = Builder.CreateFDiv(T6, CpRD); // (b-ar)/tmp + Builder.CreateBr(ContBB); + + CGF.EmitBlock(FalseBB); + // abs(c) < abs(d) + // r = c/d + // tmp = d + rc + // e = (ar + b)/tmp + // f = (br - a)/tmp + llvm::Value *CdD = Builder.CreateFDiv(RHSr, RHSi); // r=c/d + + llvm::Value *RC = Builder.CreateFMul(CdD, RHSr); // rc + llvm::Value *DpRC = Builder.CreateFAdd(RHSi, RC); // tmp=d+rc + + llvm::Value *T7 = Builder.CreateFMul(LHSr, RC); // ar + llvm::Value *T8 = Builder.CreateFAdd(T7, LHSi); // ar+b + llvm::Value *DSTFr = Builder.CreateFDiv(T8, DpRC); // (ar+b)/tmp + + llvm::Value *T9 = Builder.CreateFMul(LHSi, CdD); // br + llvm::Value *T10 = Builder.CreateFSub(T9, LHSr); // br-a + llvm::Value *DSTFi = Builder.CreateFDiv(T10, DpRC); // (br-a)/tmp + Builder.CreateBr(ContBB); + + // Phi together the computation paths. + CGF.EmitBlock(ContBB); + llvm::PHINode *VALr = Builder.CreatePHI(DSTTr->getType(), 2); + VALr->addIncoming(DSTTr, TrueBB); + VALr->addIncoming(DSTFr, FalseBB); + llvm::PHINode *VALi = Builder.CreatePHI(DSTTi->getType(), 2); + VALi->addIncoming(DSTTi, TrueBB); + VALi->addIncoming(DSTFi, FalseBB); + return ComplexPairTy(VALr, VALi); +} + // See C11 Annex G.5.1 for the semantics of multiplicative operators on complex // typed values. ComplexPairTy ComplexExprEmitter::EmitBinDiv(const BinOpInfo &Op) { llvm::Value *LHSr = Op.LHS.first, *LHSi = Op.LHS.second; llvm::Value *RHSr = Op.RHS.first, *RHSi = Op.RHS.second; - llvm::Value *DSTr, *DSTi; if (LHSr->getType()->isFloatingPointTy()) { - // If we have a complex operand on the RHS and FastMath is not allowed, we - // delegate to a libcall to handle all of the complexities and minimize - // underflow/overflow cases. When FastMath is allowed we construct the - // divide inline using the same algorithm as for integer operands. - // - // FIXME: We would be able to avoid the libcall in many places if we - // supported imaginary types in addition to complex types. CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, Op.FPFeatures); - if (RHSi && !CGF.getLangOpts().FastMath) { + if (!RHSi) { + assert(LHSi && "Can have at most one non-complex operand!"); + + DSTr = Builder.CreateFDiv(LHSr, RHSr); + DSTi = Builder.CreateFDiv(LHSi, RHSr); + return ComplexPairTy(DSTr, DSTi); + } + llvm::Value *OrigLHSi = LHSi; + if (!LHSi) + LHSi = llvm::Constant::getNullValue(RHSi->getType()); + if (Op.FPFeatures.getComplexRange() == LangOptions::CX_Fortran) + return EmitRangeReductionDiv(LHSr, LHSi, RHSr, RHSi); + else if (Op.FPFeatures.getComplexRange() == LangOptions::CX_Limited) + return EmitAlgebraicDiv(LHSr, LHSi, RHSr, RHSi); + else if (!CGF.getLangOpts().FastMath) { + LHSi = OrigLHSi; + // If we have a complex operand on the RHS and FastMath is not allowed, we + // delegate to a libcall to handle all of the complexities and minimize + // underflow/overflow cases. When FastMath is allowed we construct the + // divide inline using the same algorithm as for integer operands. + // + // FIXME: We would be able to avoid the libcall in many places if we + // supported imaginary types in addition to complex types. BinOpInfo LibCallOp = Op; // If LHS was a real, supply a null imaginary part. if (!LHSi) @@ -884,30 +1008,8 @@ ComplexPairTy ComplexExprEmitter::EmitBinDiv(const BinOpInfo &Op) { case llvm::Type::FP128TyID: return EmitComplexBinOpLibCall("__divtc3", LibCallOp); } - } else if (RHSi) { - if (!LHSi) - LHSi = llvm::Constant::getNullValue(RHSi->getType()); - - // (a+ib) / (c+id) = ((ac+bd)/(cc+dd)) + i((bc-ad)/(cc+dd)) - llvm::Value *AC = Builder.CreateFMul(LHSr, RHSr); // a*c - llvm::Value *BD = Builder.CreateFMul(LHSi, RHSi); // b*d - llvm::Value *ACpBD = Builder.CreateFAdd(AC, BD); // ac+bd - - llvm::Value *CC = Builder.CreateFMul(RHSr, RHSr); // c*c - llvm::Value *DD = Builder.CreateFMul(RHSi, RHSi); // d*d - llvm::Value *CCpDD = Builder.CreateFAdd(CC, DD); // cc+dd - - llvm::Value *BC = Builder.CreateFMul(LHSi, RHSr); // b*c - llvm::Value *AD = Builder.CreateFMul(LHSr, RHSi); // a*d - llvm::Value *BCmAD = Builder.CreateFSub(BC, AD); // bc-ad - - DSTr = Builder.CreateFDiv(ACpBD, CCpDD); - DSTi = Builder.CreateFDiv(BCmAD, CCpDD); } else { - assert(LHSi && "Can have at most one non-complex operand!"); - - DSTr = Builder.CreateFDiv(LHSr, RHSr); - DSTi = Builder.CreateFDiv(LHSi, RHSr); + return EmitAlgebraicDiv(LHSr, LHSi, RHSr, RHSi); } } else { assert(Op.LHS.second && Op.RHS.second && diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 378437364767f693a072fe90a6957862efbc4743..41ad2ddac30d2d3b45758fde246a4fa83891011e 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -2571,7 +2571,7 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV, // For atomic bool increment, we just store true and return it for // preincrement, do an atomic swap with true for postincrement return Builder.CreateAtomicRMW( - llvm::AtomicRMWInst::Xchg, LV.getPointer(CGF), True, + llvm::AtomicRMWInst::Xchg, LV.getAddress(CGF), True, llvm::AtomicOrdering::SequentiallyConsistent); } // Special case for atomic increment / decrement on integers, emit @@ -2589,7 +2589,7 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV, llvm::Value *amt = CGF.EmitToMemory( llvm::ConstantInt::get(ConvertType(type), 1, true), type); llvm::Value *old = - Builder.CreateAtomicRMW(aop, LV.getPointer(CGF), amt, + Builder.CreateAtomicRMW(aop, LV.getAddress(CGF), amt, llvm::AtomicOrdering::SequentiallyConsistent); return isPre ? Builder.CreateBinOp(op, old, amt) : old; } @@ -3314,7 +3314,7 @@ LValue ScalarExprEmitter::EmitCompoundAssignLValue( E->getExprLoc()), LHSTy); Value *OldVal = Builder.CreateAtomicRMW( - AtomicOp, LHSLV.getPointer(CGF), Amt, + AtomicOp, LHSLV.getAddress(CGF), Amt, llvm::AtomicOrdering::SequentiallyConsistent); // Since operation is atomic, the result type is guaranteed to be the diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp index c239bc17ef267e86381233cebfbbee9eeb59864a..3e8a40e7540bef7060a4f5fe124250483e684c46 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.cpp +++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp @@ -184,7 +184,8 @@ void CGHLSLRuntime::finishCodeGen() { : llvm::hlsl::ResourceKind::TBuffer; std::string TyName = Buf.Name.str() + (Buf.IsCBuffer ? ".cb." : ".tb.") + "ty"; - addBufferResourceAnnotation(GV, TyName, RC, RK, Buf.Binding); + addBufferResourceAnnotation(GV, TyName, RC, RK, /*IsROV=*/false, + Buf.Binding); } } @@ -196,6 +197,7 @@ void CGHLSLRuntime::addBufferResourceAnnotation(llvm::GlobalVariable *GV, llvm::StringRef TyName, llvm::hlsl::ResourceClass RC, llvm::hlsl::ResourceKind RK, + bool IsROV, BufferResBinding &Binding) { llvm::Module &M = CGM.getModule(); @@ -219,7 +221,7 @@ void CGHLSLRuntime::addBufferResourceAnnotation(llvm::GlobalVariable *GV, "ResourceMD must have been set by the switch above."); llvm::hlsl::FrontendResource Res( - GV, TyName, RK, Binding.Reg.value_or(UINT_MAX), Binding.Space); + GV, TyName, RK, IsROV, Binding.Reg.value_or(UINT_MAX), Binding.Space); ResourceMD->addOperand(Res.getMetadata()); } @@ -236,10 +238,11 @@ void CGHLSLRuntime::annotateHLSLResource(const VarDecl *D, GlobalVariable *GV) { llvm::hlsl::ResourceClass RC = Attr->getResourceClass(); llvm::hlsl::ResourceKind RK = Attr->getResourceKind(); + bool IsROV = Attr->getIsROV(); QualType QT(Ty, 0); BufferResBinding Binding(D->getAttr()); - addBufferResourceAnnotation(GV, QT.getAsString(), RC, RK, Binding); + addBufferResourceAnnotation(GV, QT.getAsString(), RC, RK, IsROV, Binding); } CGHLSLRuntime::BufferResBinding::BufferResBinding( diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h index 67413fbd4a78e1a99801499f1f33692a1094d136..bb500cb5c979f27d4e85d5440ae68aa207e69f19 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.h +++ b/clang/lib/CodeGen/CGHLSLRuntime.h @@ -92,7 +92,7 @@ private: void addBufferResourceAnnotation(llvm::GlobalVariable *GV, llvm::StringRef TyName, llvm::hlsl::ResourceClass RC, - llvm::hlsl::ResourceKind RK, + llvm::hlsl::ResourceKind RK, bool IsROV, BufferResBinding &Binding); void addConstant(VarDecl *D, Buffer &CB); void addBufferDecls(const DeclContext *DC, Buffer &CB); diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp index 55648963df36ab97811fecb15502f5a3cc85f421..7f7e6f5306664446ccbfdbfbe40ec7de13f0a977 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp @@ -7389,7 +7389,14 @@ private: } else if (FieldIndex < PartialStruct.LowestElem.first) { PartialStruct.LowestElem = {FieldIndex, LowestElem}; } else if (FieldIndex > PartialStruct.HighestElem.first) { - PartialStruct.HighestElem = {FieldIndex, LowestElem}; + if (IsFinalArraySection) { + Address HB = + CGF.EmitOMPArraySectionExpr(OASE, /*IsLowerBound=*/false) + .getAddress(CGF); + PartialStruct.HighestElem = {FieldIndex, HB}; + } else { + PartialStruct.HighestElem = {FieldIndex, LowestElem}; + } } } diff --git a/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp b/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp index 293ccaa3413cdf372d72a02ff4a93f4c2a28b947..299ee1460b3db0ef895c681246a8cc7f8bd42fb2 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp @@ -3483,6 +3483,7 @@ void CGOpenMPRuntimeGPU::processRequiresDirective( case CudaArch::SM_87: case CudaArch::SM_89: case CudaArch::SM_90: + case CudaArch::SM_90a: case CudaArch::GFX600: case CudaArch::GFX601: case CudaArch::GFX602: diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index 90c7ed450e54b99cb2374a663f8b410cdf20f43a..ed426098ac691564edd4d2d23d7ffdee5e07c1b0 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -2558,9 +2558,9 @@ static void emitOMPSimdRegion(CodeGenFunction &CGF, const OMPLoopDirective &S, (void)CGF.EmitOMPLinearClauseInit(S); { CodeGenFunction::OMPPrivateScope LoopScope(CGF); + CGF.EmitOMPPrivateClause(S, LoopScope); CGF.EmitOMPPrivateLoopCounters(S, LoopScope); CGF.EmitOMPLinearClause(S, LoopScope); - CGF.EmitOMPPrivateClause(S, LoopScope); CGF.EmitOMPReductionClauseInit(S, LoopScope); CGOpenMPRuntime::LastprivateConditionalRAII LPCRegion( CGF, S, CGF.EmitLValue(S.getIterationVariable())); @@ -6206,7 +6206,7 @@ static std::pair emitOMPAtomicRMW(CodeGenFunction &CGF, LValue X, X.getAddress(CGF).getElementType()); } llvm::Value *Res = - CGF.Builder.CreateAtomicRMW(RMWOp, X.getPointer(CGF), UpdateVal, AO); + CGF.Builder.CreateAtomicRMW(RMWOp, X.getAddress(CGF), UpdateVal, AO); return std::make_pair(true, RValue::get(Res)); } diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index dea58a7ff4146a65ec9267308e2e13e83114ee29..b931a81bc00871b6d1de5fc0919e64467324b6cb 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -4178,8 +4178,29 @@ void CodeGenModule::emitMultiVersionFunctions() { } llvm::Constant *ResolverConstant = GetOrCreateMultiVersionResolver(GD); - if (auto *IFunc = dyn_cast(ResolverConstant)) + if (auto *IFunc = dyn_cast(ResolverConstant)) { ResolverConstant = IFunc->getResolver(); + // In Aarch64, default versions of multiversioned functions are mangled to + // their 'normal' assembly name. This deviates from other targets which + // append a '.default' string. As a result we need to continue appending + // .ifunc in Aarch64. + // FIXME: Should Aarch64 mangling for 'default' multiversion function and + // in turn ifunc function match that of other targets? + if (FD->isTargetClonesMultiVersion() && + !getTarget().getTriple().isAArch64()) { + const CGFunctionInfo &FI = getTypes().arrangeGlobalDeclaration(GD); + llvm::FunctionType *DeclTy = getTypes().GetFunctionType(FI); + std::string MangledName = getMangledNameImpl( + *this, GD, FD, /*OmitMultiVersionMangling=*/true); + // In prior versions of Clang, the mangling for ifuncs incorrectly + // included an .ifunc suffix. This alias is generated for backward + // compatibility. It is deprecated, and may be removed in the future. + auto *Alias = llvm::GlobalAlias::create( + DeclTy, 0, getMultiversionLinkage(*this, GD), + MangledName + ".ifunc", IFunc, &getModule()); + SetCommonAttributes(FD, Alias); + } + } llvm::Function *ResolverFunc = cast(ResolverConstant); ResolverFunc->setLinkage(getMultiversionLinkage(*this, GD)); @@ -4346,10 +4367,19 @@ llvm::Constant *CodeGenModule::GetOrCreateMultiVersionResolver(GlobalDecl GD) { // Holds the name of the resolver, in ifunc mode this is the ifunc (which has // a separate resolver). std::string ResolverName = MangledName; - if (getTarget().supportsIFunc()) - ResolverName += ".ifunc"; - else if (FD->isTargetMultiVersion()) + if (getTarget().supportsIFunc()) { + // In Aarch64, default versions of multiversioned functions are mangled to + // their 'normal' assembly name. This deviates from other targets which + // append a '.default' string. As a result we need to continue appending + // .ifunc in Aarch64. + // FIXME: Should Aarch64 mangling for 'default' multiversion function and + // in turn ifunc function match that of other targets? + if (!FD->isTargetClonesMultiVersion() || + getTarget().getTriple().isAArch64()) + ResolverName += ".ifunc"; + } else if (FD->isTargetMultiVersion()) { ResolverName += ".resolver"; + } // If the resolver has already been created, just return it. if (llvm::GlobalValue *ResolverGV = GetGlobalValue(ResolverName)) @@ -6409,7 +6439,7 @@ ConstantAddress CodeGenModule::GetAddrOfGlobalTemporary( VD, E->getManglingNumber(), Out); APValue *Value = nullptr; - if (E->getStorageDuration() == SD_Static && VD && VD->evaluateValue()) { + if (E->getStorageDuration() == SD_Static && VD->evaluateValue()) { // If the initializer of the extending declaration is a constant // initializer, we should have a cached constant initializer for this // temporary. Note that this might have a different value from the value @@ -6424,8 +6454,7 @@ ConstantAddress CodeGenModule::GetAddrOfGlobalTemporary( !EvalResult.hasSideEffects()) Value = &EvalResult.Val; - LangAS AddrSpace = - VD ? GetGlobalVarAddressSpace(VD) : MaterializedType.getAddressSpace(); + LangAS AddrSpace = GetGlobalVarAddressSpace(VD); std::optional emitter; llvm::Constant *InitialValue = nullptr; diff --git a/clang/lib/CodeGen/CodeGenTBAA.cpp b/clang/lib/CodeGen/CodeGenTBAA.cpp index 5906b14dd93cf088bf9c25443d70c9a531416a00..dc288bc3f6157ac7dd42068046abf0888a740f69 100644 --- a/clang/lib/CodeGen/CodeGenTBAA.cpp +++ b/clang/lib/CodeGen/CodeGenTBAA.cpp @@ -196,11 +196,14 @@ llvm::MDNode *CodeGenTBAA::getTypeInfoHelper(const Type *Ty) { // Enum types are distinct types. In C++ they have "underlying types", // however they aren't related for TBAA. if (const EnumType *ETy = dyn_cast(Ty)) { + if (!Features.CPlusPlus) + return getTypeInfo(ETy->getDecl()->getIntegerType()); + // In C++ mode, types have linkage, so we can rely on the ODR and // on their mangled names, if they're external. // TODO: Is there a way to get a program-wide unique name for a // decl with local linkage or no linkage? - if (!Features.CPlusPlus || !ETy->getDecl()->isExternallyVisible()) + if (!ETy->getDecl()->isExternallyVisible()) return getChar(); SmallString<256> OutName; diff --git a/clang/lib/CodeGen/Targets/AMDGPU.cpp b/clang/lib/CodeGen/Targets/AMDGPU.cpp index b654e3f12af8d4918e96784083b7b278c1691ca5..03ac6b78598fc8477e6756b4c64f5936fd0daedb 100644 --- a/clang/lib/CodeGen/Targets/AMDGPU.cpp +++ b/clang/lib/CodeGen/Targets/AMDGPU.cpp @@ -471,20 +471,25 @@ AMDGPUTargetCodeGenInfo::getLLVMSyncScopeID(const LangOptions &LangOpts, std::string Name; switch (Scope) { case SyncScope::HIPSingleThread: + case SyncScope::SingleScope: Name = "singlethread"; break; case SyncScope::HIPWavefront: case SyncScope::OpenCLSubGroup: + case SyncScope::WavefrontScope: Name = "wavefront"; break; case SyncScope::HIPWorkgroup: case SyncScope::OpenCLWorkGroup: + case SyncScope::WorkgroupScope: Name = "workgroup"; break; case SyncScope::HIPAgent: case SyncScope::OpenCLDevice: + case SyncScope::DeviceScope: Name = "agent"; break; + case SyncScope::SystemScope: case SyncScope::HIPSystem: case SyncScope::OpenCLAllSVMDevices: Name = ""; diff --git a/clang/lib/CrossTU/CrossTranslationUnit.cpp b/clang/lib/CrossTU/CrossTranslationUnit.cpp index 540c22d078654c01e454d46a576823c74753b859..94c10e50d7d06489084633a9ccdb11fc3d793e1e 100644 --- a/clang/lib/CrossTU/CrossTranslationUnit.cpp +++ b/clang/lib/CrossTU/CrossTranslationUnit.cpp @@ -551,7 +551,7 @@ CrossTranslationUnitContext::ASTLoader::load(StringRef Identifier) { // Normalize by removing relative path components. llvm::sys::path::remove_dots(Path, /*remove_dot_dot*/ true, PathStyle); - if (Path.endswith(".ast")) + if (Path.ends_with(".ast")) return loadFromDump(Path); else return loadFromSource(Path); diff --git a/clang/lib/DirectoryWatcher/linux/DirectoryWatcher-linux.cpp b/clang/lib/DirectoryWatcher/linux/DirectoryWatcher-linux.cpp index 9b3d2571f29f628d85200ae43c9838164641dc0e..beca9586988b526876c0787ae9d0e62345268c4f 100644 --- a/clang/lib/DirectoryWatcher/linux/DirectoryWatcher-linux.cpp +++ b/clang/lib/DirectoryWatcher/linux/DirectoryWatcher-linux.cpp @@ -14,7 +14,6 @@ #include "llvm/Support/AlignOf.h" #include "llvm/Support/Errno.h" #include "llvm/Support/Error.h" -#include "llvm/Support/MathExtras.h" #include "llvm/Support/Path.h" #include #include @@ -25,6 +24,7 @@ #include #include +#include #include #include #include diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index 6f5ff8141032677d426d5e63d343c56fe4b9da4c..f392f6794f857e62df637602027a56e99ad2fb9e 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -1522,7 +1522,7 @@ bool Driver::getCrashDiagnosticFile(StringRef ReproCrashFilename, // (or /Library/Logs/DiagnosticReports for root) and has the filename pattern // clang-__.crash. path::home_directory(CrashDiagDir); - if (CrashDiagDir.startswith("/var/root")) + if (CrashDiagDir.starts_with("/var/root")) CrashDiagDir = "/"; path::append(CrashDiagDir, "Library/Logs/DiagnosticReports"); int PID = @@ -1940,12 +1940,6 @@ int Driver::ExecuteCompilation( void Driver::PrintHelp(bool ShowHidden) const { llvm::opt::Visibility VisibilityMask = getOptionVisibilityMask(); - // TODO: We're overriding the mask for flang here to keep this NFC for the - // option refactoring, but what we really need to do is annotate the flags - // that Flang uses. - if (IsFlangMode()) - VisibilityMask = llvm::opt::Visibility(options::FlangOption); - std::string Usage = llvm::formatv("{0} [options] file...", Name).str(); getOpts().printHelp(llvm::outs(), Usage.c_str(), DriverTitle.c_str(), ShowHidden, /*ShowAllAliases=*/false, diff --git a/clang/lib/Driver/Multilib.cpp b/clang/lib/Driver/Multilib.cpp index 7681c1a3ce6756f6cfc00cc13ed56b796a830ac5..9c091bbfdabab122cec9bb3c1035ece1988b0fc4 100644 --- a/clang/lib/Driver/Multilib.cpp +++ b/clang/lib/Driver/Multilib.cpp @@ -95,7 +95,7 @@ MultilibSet &MultilibSet::FilterOut(FilterCallback F) { void MultilibSet::push_back(const Multilib &M) { Multilibs.push_back(M); } bool MultilibSet::select(const Multilib::flags_list &Flags, - llvm::SmallVector &Selected) const { + llvm::SmallVectorImpl &Selected) const { llvm::StringSet<> FlagSet(expandFlags(Flags)); Selected.clear(); diff --git a/clang/lib/Driver/ToolChains/Arch/AArch64.cpp b/clang/lib/Driver/ToolChains/Arch/AArch64.cpp index 1f77c987051749ca5caba5bc77821b405e308000..097258b16924442abf7b067343eea81d9c8cb0ec 100644 --- a/clang/lib/Driver/ToolChains/Arch/AArch64.cpp +++ b/clang/lib/Driver/ToolChains/Arch/AArch64.cpp @@ -57,9 +57,8 @@ std::string aarch64::getAArch64TargetCPU(const ArgList &Args, if (Triple.isArm64e()) return "apple-a12"; - // Make sure we pick the appropriate Apple CPU if -arch is used or when - // targetting a Darwin OS. - if (Args.getLastArg(options::OPT_arch) || Triple.isOSDarwin()) + // Make sure we pick the appropriate Apple CPU when targetting a Darwin OS. + if (Triple.isOSDarwin()) return Triple.getArch() == llvm::Triple::aarch64_32 ? "apple-s4" : "apple-a7"; @@ -274,7 +273,7 @@ void aarch64::getAArch64TargetFeatures(const Driver &D, success = getAArch64ArchFeaturesFromMarch(D, A->getValue(), Args, Features); else if ((A = Args.getLastArg(options::OPT_mcpu_EQ))) success = getAArch64ArchFeaturesFromMcpu(D, A->getValue(), Args, Features); - else if (Args.hasArg(options::OPT_arch) || isCPUDeterminedByTriple(Triple)) + else if (isCPUDeterminedByTriple(Triple)) success = getAArch64ArchFeaturesFromMcpu( D, getAArch64TargetCPU(Args, Triple, A), Args, Features); else @@ -287,8 +286,7 @@ void aarch64::getAArch64TargetFeatures(const Driver &D, else if (success && (A = Args.getLastArg(options::OPT_mcpu_EQ))) success = getAArch64MicroArchFeaturesFromMcpu(D, A->getValue(), Args, Features); - else if (success && - (Args.hasArg(options::OPT_arch) || isCPUDeterminedByTriple(Triple))) + else if (success && isCPUDeterminedByTriple(Triple)) success = getAArch64MicroArchFeaturesFromMcpu( D, getAArch64TargetCPU(Args, Triple, A), Args, Features); diff --git a/clang/lib/Driver/ToolChains/Arch/RISCV.cpp b/clang/lib/Driver/ToolChains/Arch/RISCV.cpp index 5d990ba78e5cc880f72bd31d9b250b1cc0a9eefa..0b696111e7d712382b68c520f041b10babdb5a58 100644 --- a/clang/lib/Driver/ToolChains/Arch/RISCV.cpp +++ b/clang/lib/Driver/ToolChains/Arch/RISCV.cpp @@ -171,13 +171,8 @@ void riscv::getRISCVTargetFeatures(const Driver &D, const llvm::Triple &Triple, Features.push_back("-save-restore"); // -mno-unaligned-access is default, unless -munaligned-access is specified. - if (const Arg *A = Args.getLastArg(options::OPT_munaligned_access, - options::OPT_mno_unaligned_access)) { - if (A->getOption().matches(options::OPT_munaligned_access)) - Features.push_back("+fast-unaligned-access"); - else - Features.push_back("-fast-unaligned-access"); - } + AddTargetFeature(Args, Features, options::OPT_munaligned_access, + options::OPT_mno_unaligned_access, "fast-unaligned-access"); // Now add any that the user explicitly requested on the command line, // which may override the defaults. diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index f02f7c841b91f0ba56dd41e377429397404fb9d3..f95f3227aba7d03bb4956b62f39569ce6ee49768 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -1294,6 +1294,9 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA, CmdArgs.push_back("-source-date-epoch"); CmdArgs.push_back(Args.MakeArgString(Epoch)); } + + Args.addOptInFlag(CmdArgs, options::OPT_fdefine_target_os_macros, + options::OPT_fno_define_target_os_macros); } // FIXME: Move to target hook. @@ -2657,6 +2660,35 @@ static void CollectArgsForIntegratedAssembler(Compilation &C, } } +static StringRef EnumComplexRangeToStr(LangOptions::ComplexRangeKind Range) { + StringRef RangeStr = ""; + switch (Range) { + case LangOptions::ComplexRangeKind::CX_Limited: + return "-fcx-limited-range"; + break; + case LangOptions::ComplexRangeKind::CX_Fortran: + return "-fcx-fortran-rules"; + break; + default: + return RangeStr; + break; + } +} + +static void EmitComplexRangeDiag(const Driver &D, + LangOptions::ComplexRangeKind Range1, + LangOptions::ComplexRangeKind Range2) { + if (Range1 != LangOptions::ComplexRangeKind::CX_Full) + D.Diag(clang::diag::warn_drv_overriding_option) + << EnumComplexRangeToStr(Range1) << EnumComplexRangeToStr(Range2); +} + +static std::string RenderComplexRangeOption(std::string Range) { + std::string ComplexRangeStr = "-complex-range="; + ComplexRangeStr += Range; + return ComplexRangeStr; +} + static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D, bool OFastEnabled, const ArgList &Args, ArgStringList &CmdArgs, @@ -2703,6 +2735,7 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D, bool StrictFPModel = false; StringRef Float16ExcessPrecision = ""; StringRef BFloat16ExcessPrecision = ""; + LangOptions::ComplexRangeKind Range = LangOptions::ComplexRangeKind::CX_Full; if (const Arg *A = Args.getLastArg(options::OPT_flimited_precision_EQ)) { CmdArgs.push_back("-mlimit-float-precision"); @@ -2715,6 +2748,28 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D, switch (optID) { default: break; + case options::OPT_fcx_limited_range: { + EmitComplexRangeDiag(D, Range, LangOptions::ComplexRangeKind::CX_Limited); + Range = LangOptions::ComplexRangeKind::CX_Limited; + std::string ComplexRangeStr = RenderComplexRangeOption("limited"); + if (!ComplexRangeStr.empty()) + CmdArgs.push_back(Args.MakeArgString(ComplexRangeStr)); + break; + } + case options::OPT_fno_cx_limited_range: + Range = LangOptions::ComplexRangeKind::CX_Full; + break; + case options::OPT_fcx_fortran_rules: { + EmitComplexRangeDiag(D, Range, LangOptions::ComplexRangeKind::CX_Fortran); + Range = LangOptions::ComplexRangeKind::CX_Fortran; + std::string ComplexRangeStr = RenderComplexRangeOption("fortran"); + if (!ComplexRangeStr.empty()) + CmdArgs.push_back(Args.MakeArgString(ComplexRangeStr)); + break; + } + case options::OPT_fno_cx_fortran_rules: + Range = LangOptions::ComplexRangeKind::CX_Full; + break; case options::OPT_ffp_model_EQ: { // If -ffp-model= is seen, reset to fno-fast-math HonorINFs = true; @@ -2769,7 +2824,7 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D, D.Diag(diag::err_drv_unsupported_option_argument) << A->getSpelling() << Val; break; - } + } } switch (optID) { @@ -2968,7 +3023,7 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D, if (!OFastEnabled) continue; [[fallthrough]]; - case options::OPT_ffast_math: + case options::OPT_ffast_math: { HonorINFs = false; HonorNaNs = false; MathErrno = false; @@ -2982,7 +3037,13 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D, // If fast-math is set then set the fp-contract mode to fast. FPContract = "fast"; SeenUnsafeMathModeOption = true; + // ffast-math enables fortran rules for complex multiplication and + // division. + std::string ComplexRangeStr = RenderComplexRangeOption("limited"); + if (!ComplexRangeStr.empty()) + CmdArgs.push_back(Args.MakeArgString(ComplexRangeStr)); break; + } case options::OPT_fno_fast_math: HonorINFs = true; HonorNaNs = true; @@ -3136,6 +3197,15 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D, if (Args.hasFlag(options::OPT_fno_strict_float_cast_overflow, options::OPT_fstrict_float_cast_overflow, false)) CmdArgs.push_back("-fno-strict-float-cast-overflow"); + + if (const Arg *A = Args.getLastArg(options::OPT_fcx_limited_range)) + CmdArgs.push_back("-fcx-limited-range"); + if (const Arg *A = Args.getLastArg(options::OPT_fcx_fortran_rules)) + CmdArgs.push_back("-fcx-fortran-rules"); + if (const Arg *A = Args.getLastArg(options::OPT_fno_cx_limited_range)) + CmdArgs.push_back("-fno-cx-limited-range"); + if (const Arg *A = Args.getLastArg(options::OPT_fno_cx_fortran_rules)) + CmdArgs.push_back("-fno-cx-fortran-rules"); } static void RenderAnalyzerOptions(const ArgList &Args, ArgStringList &CmdArgs, diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp index 0ae8e2dce32e94a8703ea73cfae44f95f4a16a68..31e7d68161ff1b224dfa4b49433d82242b02794d 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -1120,55 +1120,61 @@ void tools::addFortranRuntimeLibs(const ToolChain &TC, const ArgList &Args, llvm::opt::ArgStringList &CmdArgs) { // These are handled earlier on Windows by telling the frontend driver to add // the correct libraries to link against as dependents in the object file. - if (!TC.getTriple().isKnownWindowsMSVCEnvironment()) { - // The --whole-archive option needs to be part of the link line to - // make sure that the main() function from Fortran_main.a is pulled - // in by the linker. Determine if --whole-archive is active when - // flang will try to link Fortran_main.a. If it is, don't add the - // --whole-archive flag to the link line. If it's not, add a proper - // --whole-archive/--no-whole-archive bracket to the link line. - bool WholeArchiveActive = false; - for (auto *Arg : Args.filtered(options::OPT_Wl_COMMA)) - if (Arg) - for (StringRef ArgValue : Arg->getValues()) { - if (ArgValue == "--whole-archive") - WholeArchiveActive = true; - if (ArgValue == "--no-whole-archive") - WholeArchiveActive = false; - } - if (!WholeArchiveActive) - CmdArgs.push_back("--whole-archive"); - CmdArgs.push_back("-lFortran_main"); - if (!WholeArchiveActive) - CmdArgs.push_back("--no-whole-archive"); + // if -fno-fortran-main has been passed, skip linking Fortran_main.a + bool LinkFortranMain = !Args.hasArg(options::OPT_no_fortran_main); + if (!TC.getTriple().isKnownWindowsMSVCEnvironment()) { + if (LinkFortranMain) { + // The --whole-archive option needs to be part of the link line to + // make sure that the main() function from Fortran_main.a is pulled + // in by the linker. Determine if --whole-archive is active when + // flang will try to link Fortran_main.a. If it is, don't add the + // --whole-archive flag to the link line. If it's not, add a proper + // --whole-archive/--no-whole-archive bracket to the link line. + bool WholeArchiveActive = false; + for (auto *Arg : Args.filtered(options::OPT_Wl_COMMA)) + if (Arg) + for (StringRef ArgValue : Arg->getValues()) { + if (ArgValue == "--whole-archive") + WholeArchiveActive = true; + if (ArgValue == "--no-whole-archive") + WholeArchiveActive = false; + } + if (!WholeArchiveActive) + CmdArgs.push_back("--whole-archive"); + CmdArgs.push_back("-lFortran_main"); + if (!WholeArchiveActive) + CmdArgs.push_back("--no-whole-archive"); + } // Perform regular linkage of the remaining runtime libraries. CmdArgs.push_back("-lFortranRuntime"); CmdArgs.push_back("-lFortranDecimal"); } else { - unsigned RTOptionID = options::OPT__SLASH_MT; - if (auto *rtl = Args.getLastArg(options::OPT_fms_runtime_lib_EQ)) { - RTOptionID = llvm::StringSwitch(rtl->getValue()) - .Case("static", options::OPT__SLASH_MT) - .Case("static_dbg", options::OPT__SLASH_MTd) - .Case("dll", options::OPT__SLASH_MD) - .Case("dll_dbg", options::OPT__SLASH_MDd) - .Default(options::OPT__SLASH_MT); - } - switch (RTOptionID) { - case options::OPT__SLASH_MT: - CmdArgs.push_back("/WHOLEARCHIVE:Fortran_main.static.lib"); - break; - case options::OPT__SLASH_MTd: - CmdArgs.push_back("/WHOLEARCHIVE:Fortran_main.static_dbg.lib"); - break; - case options::OPT__SLASH_MD: - CmdArgs.push_back("/WHOLEARCHIVE:Fortran_main.dynamic.lib"); - break; - case options::OPT__SLASH_MDd: - CmdArgs.push_back("/WHOLEARCHIVE:Fortran_main.dynamic_dbg.lib"); - break; + if (LinkFortranMain) { + unsigned RTOptionID = options::OPT__SLASH_MT; + if (auto *rtl = Args.getLastArg(options::OPT_fms_runtime_lib_EQ)) { + RTOptionID = llvm::StringSwitch(rtl->getValue()) + .Case("static", options::OPT__SLASH_MT) + .Case("static_dbg", options::OPT__SLASH_MTd) + .Case("dll", options::OPT__SLASH_MD) + .Case("dll_dbg", options::OPT__SLASH_MDd) + .Default(options::OPT__SLASH_MT); + } + switch (RTOptionID) { + case options::OPT__SLASH_MT: + CmdArgs.push_back("/WHOLEARCHIVE:Fortran_main.static.lib"); + break; + case options::OPT__SLASH_MTd: + CmdArgs.push_back("/WHOLEARCHIVE:Fortran_main.static_dbg.lib"); + break; + case options::OPT__SLASH_MD: + CmdArgs.push_back("/WHOLEARCHIVE:Fortran_main.dynamic.lib"); + break; + case options::OPT__SLASH_MDd: + CmdArgs.push_back("/WHOLEARCHIVE:Fortran_main.dynamic_dbg.lib"); + break; + } } } } @@ -2583,9 +2589,7 @@ void tools::addMachineOutlinerArgs(const Driver &D, // We only support -moutline in AArch64 and ARM targets right now. If // we're not compiling for these, emit a warning and ignore the flag. // Otherwise, add the proper mllvm flags. - if (!(Triple.isARM() || Triple.isThumb() || - Triple.getArch() == llvm::Triple::aarch64 || - Triple.getArch() == llvm::Triple::aarch64_32)) { + if (!(Triple.isARM() || Triple.isThumb() || Triple.isAArch64())) { D.Diag(diag::warn_drv_moutline_unsupported_opt) << Triple.getArchName(); } else { addArg(Twine("-enable-machine-outliner")); diff --git a/clang/lib/Driver/ToolChains/Cuda.cpp b/clang/lib/Driver/ToolChains/Cuda.cpp index e95ff98e6c940f1becedc9b40c74d8c249495a84..ef1e77974c1eaaf79f707bfc22c565024f3b5862 100644 --- a/clang/lib/Driver/ToolChains/Cuda.cpp +++ b/clang/lib/Driver/ToolChains/Cuda.cpp @@ -78,6 +78,10 @@ CudaVersion getCudaVersion(uint32_t raw_version) { return CudaVersion::CUDA_120; if (raw_version < 12020) return CudaVersion::CUDA_121; + if (raw_version < 12030) + return CudaVersion::CUDA_122; + if (raw_version < 12040) + return CudaVersion::CUDA_123; return CudaVersion::NEW; } @@ -671,6 +675,8 @@ void NVPTX::getNVPTXTargetFeatures(const Driver &D, const llvm::Triple &Triple, case CudaVersion::CUDA_##CUDA_VER: \ PtxFeature = "+ptx" #PTX_VER; \ break; + CASE_CUDA_VERSION(123, 83); + CASE_CUDA_VERSION(122, 82); CASE_CUDA_VERSION(121, 81); CASE_CUDA_VERSION(120, 80); CASE_CUDA_VERSION(118, 78); diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp index f09bc27d7d2c0e6d76aa776e98bb5b3d8ee15c1d..692b3a3f285d744afc868a622ea7dc0aa1559de6 100644 --- a/clang/lib/Driver/ToolChains/Darwin.cpp +++ b/clang/lib/Driver/ToolChains/Darwin.cpp @@ -1281,7 +1281,7 @@ void MachO::AddLinkRuntimeLib(const ArgList &Args, ArgStringList &CmdArgs, // rpaths. This is currently true from this place, but we need to be // careful if this function is ever called before user's rpaths are emitted. if (Opts & RLO_AddRPath) { - assert(DarwinLibName.endswith(".dylib") && "must be a dynamic library"); + assert(DarwinLibName.ends_with(".dylib") && "must be a dynamic library"); // Add @executable_path to rpath to support having the dylib copied with // the executable. diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp index 9db19e30a9f1f7fcb182721947e3cdef1d089bc8..502b9f17a06c52ff06434f206489f817f81dfcc4 100644 --- a/clang/lib/Driver/ToolChains/Flang.cpp +++ b/clang/lib/Driver/ToolChains/Flang.cpp @@ -143,33 +143,11 @@ void Flang::addCodegenOptions(const ArgList &Args, if (shouldLoopVersion(Args)) CmdArgs.push_back("-fversion-loops-for-stride"); - Arg *aliasAnalysis = Args.getLastArg(options::OPT_falias_analysis, - options::OPT_fno_alias_analysis); - // only pass on the argument if it does not match that implied by the - // optimization level: so if optimization is requested, only forward - // -fno-alias-analysis. If optimization is not requested, only forward - // -falias-analysis. - Arg *optLevel = - Args.getLastArg(options::OPT_Ofast, options::OPT_O, options::OPT_O4); - if (aliasAnalysis) { - bool faliasAnalysis = - aliasAnalysis->getOption().matches(options::OPT_falias_analysis); - if (optLevel && !faliasAnalysis) { - CmdArgs.push_back("-fno-alias-analysis"); - } else { - if (faliasAnalysis) - // requested alias analysis but no optimization enabled - CmdArgs.push_back("-falias-analysis"); - } - } - Args.addAllArgs(CmdArgs, {options::OPT_flang_experimental_hlfir, options::OPT_flang_deprecated_no_hlfir, options::OPT_flang_experimental_polymorphism, options::OPT_fno_ppc_native_vec_elem_order, - options::OPT_fppc_native_vec_elem_order, - options::OPT_falias_analysis, - options::OPT_fno_alias_analysis}); + options::OPT_fppc_native_vec_elem_order}); } void Flang::addPicOptions(const ArgList &Args, ArgStringList &CmdArgs) const { @@ -253,6 +231,8 @@ static void processVSRuntimeLibrary(const ToolChain &TC, const ArgList &Args, ArgStringList &CmdArgs) { assert(TC.getTriple().isKnownWindowsMSVCEnvironment() && "can only add VS runtime library on Windows!"); + // if -fno-fortran-main has been passed, skip linking Fortran_main.a + bool LinkFortranMain = !Args.hasArg(options::OPT_no_fortran_main); if (TC.getTriple().isKnownWindowsMSVCEnvironment()) { CmdArgs.push_back(Args.MakeArgString( "--dependent-lib=" + TC.getCompilerRTBasename(Args, "builtins"))); @@ -270,7 +250,8 @@ static void processVSRuntimeLibrary(const ToolChain &TC, const ArgList &Args, case options::OPT__SLASH_MT: CmdArgs.push_back("-D_MT"); CmdArgs.push_back("--dependent-lib=libcmt"); - CmdArgs.push_back("--dependent-lib=Fortran_main.static.lib"); + if (LinkFortranMain) + CmdArgs.push_back("--dependent-lib=Fortran_main.static.lib"); CmdArgs.push_back("--dependent-lib=FortranRuntime.static.lib"); CmdArgs.push_back("--dependent-lib=FortranDecimal.static.lib"); break; @@ -278,7 +259,8 @@ static void processVSRuntimeLibrary(const ToolChain &TC, const ArgList &Args, CmdArgs.push_back("-D_MT"); CmdArgs.push_back("-D_DEBUG"); CmdArgs.push_back("--dependent-lib=libcmtd"); - CmdArgs.push_back("--dependent-lib=Fortran_main.static_dbg.lib"); + if (LinkFortranMain) + CmdArgs.push_back("--dependent-lib=Fortran_main.static_dbg.lib"); CmdArgs.push_back("--dependent-lib=FortranRuntime.static_dbg.lib"); CmdArgs.push_back("--dependent-lib=FortranDecimal.static_dbg.lib"); break; @@ -286,7 +268,8 @@ static void processVSRuntimeLibrary(const ToolChain &TC, const ArgList &Args, CmdArgs.push_back("-D_MT"); CmdArgs.push_back("-D_DLL"); CmdArgs.push_back("--dependent-lib=msvcrt"); - CmdArgs.push_back("--dependent-lib=Fortran_main.dynamic.lib"); + if (LinkFortranMain) + CmdArgs.push_back("--dependent-lib=Fortran_main.dynamic.lib"); CmdArgs.push_back("--dependent-lib=FortranRuntime.dynamic.lib"); CmdArgs.push_back("--dependent-lib=FortranDecimal.dynamic.lib"); break; @@ -295,7 +278,8 @@ static void processVSRuntimeLibrary(const ToolChain &TC, const ArgList &Args, CmdArgs.push_back("-D_DEBUG"); CmdArgs.push_back("-D_DLL"); CmdArgs.push_back("--dependent-lib=msvcrtd"); - CmdArgs.push_back("--dependent-lib=Fortran_main.dynamic_dbg.lib"); + if (LinkFortranMain) + CmdArgs.push_back("--dependent-lib=Fortran_main.dynamic_dbg.lib"); CmdArgs.push_back("--dependent-lib=FortranRuntime.dynamic_dbg.lib"); CmdArgs.push_back("--dependent-lib=FortranDecimal.dynamic_dbg.lib"); break; diff --git a/clang/lib/Driver/ToolChains/MSVC.cpp b/clang/lib/Driver/ToolChains/MSVC.cpp index 8a4a174c90ea8557336cc3258d617628828b6787..6d925555b7bb4b2d462ef91ab5eb0f0974ab1a0c 100644 --- a/clang/lib/Driver/ToolChains/MSVC.cpp +++ b/clang/lib/Driver/ToolChains/MSVC.cpp @@ -787,11 +787,11 @@ VersionTuple MSVCToolChain::computeMSVCVersion(const Driver *D, if (MSVT.empty() && Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions, IsWindowsMSVC)) { - // -fms-compatibility-version=19.20 is default, aka 2019, 16.x + // -fms-compatibility-version=19.33 is default, aka 2022, 17.3 // NOTE: when changing this value, also update // clang/docs/CommandGuide/clang.rst and clang/docs/UsersManual.rst // accordingly. - MSVT = VersionTuple(19, 20); + MSVT = VersionTuple(19, 33); } return MSVT; } diff --git a/clang/lib/Driver/ToolChains/WebAssembly.cpp b/clang/lib/Driver/ToolChains/WebAssembly.cpp index f04018179a5dab724aeb603568f4f2a4b283b021..f131b6cf3baff9d7ccfc2782d3ddfe6ea9b17b57 100644 --- a/clang/lib/Driver/ToolChains/WebAssembly.cpp +++ b/clang/lib/Driver/ToolChains/WebAssembly.cpp @@ -143,7 +143,7 @@ void wasm::Linker::ConstructJob(Compilation &C, const JobAction &JA, // When optimizing, if wasm-opt is available, run it. std::string WasmOptPath; - if (Arg *A = Args.getLastArg(options::OPT_O_Group)) { + if (Args.getLastArg(options::OPT_O_Group)) { WasmOptPath = ToolChain.GetProgramPath("wasm-opt"); if (WasmOptPath == "wasm-opt") { WasmOptPath = {}; diff --git a/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp b/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp index 931933b2bd1ac0e98c2bebe3bd15f306971292df..d9675b0c94de3962fa185b87f9819bb2d844b268 100644 --- a/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp +++ b/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp @@ -199,9 +199,10 @@ StringRef getLanguageName(Language Lang) { return "objective-c"; case Language::CXX: return "c++"; + case Language::ObjCXX: + return "objective-c++"; // Unsupported language currently - case Language::ObjCXX: case Language::OpenCL: case Language::OpenCLCXX: case Language::CUDA: diff --git a/clang/lib/Format/ContinuationIndenter.cpp b/clang/lib/Format/ContinuationIndenter.cpp index cb7dc5f3dd9babcbfdbe15c3278331fbe1d0596f..9e4e939503dfe4a0b5dd501e14353cdb4133c664 100644 --- a/clang/lib/Format/ContinuationIndenter.cpp +++ b/clang/lib/Format/ContinuationIndenter.cpp @@ -1259,7 +1259,7 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) { } if (Style.AlignAfterOpenBracket == FormatStyle::BAS_BlockIndent && (Current.is(tok::r_paren) || - (Current.is(tok::r_brace) && + (Current.is(tok::r_brace) && Current.MatchingParen && Current.MatchingParen->is(BK_BracedInit))) && State.Stack.size() > 1) { return State.Stack[State.Stack.size() - 2].LastSpace; diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index b09487435adb2da7a8f3908006b798d55d47dfc5..8feee7457fc31b76a09f9c9ebd9a9104db281404 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -3955,10 +3955,7 @@ llvm::Expected getStyle(StringRef StyleName, StringRef FileName, StringRef FallbackStyleName, StringRef Code, llvm::vfs::FileSystem *FS, bool AllowUnknownOptions) { - if (!FS) - FS = llvm::vfs::getRealFileSystem().get(); FormatStyle Style = getLLVMStyle(guessLanguage(FileName, Code)); - FormatStyle FallbackStyle = getNoStyle(); if (!getPredefinedStyle(FallbackStyleName, Style.Language, &FallbackStyle)) return make_string_error("Invalid fallback style: " + FallbackStyleName); @@ -3974,14 +3971,18 @@ llvm::Expected getStyle(StringRef StyleName, StringRef FileName, AllowUnknownOptions)) { return make_string_error("Error parsing -style: " + ec.message()); } - if (Style.InheritsParentConfig) { - ChildFormatTextToApply.emplace_back( - llvm::MemoryBuffer::getMemBuffer(StyleName, Source, false)); - } else { + + if (!Style.InheritsParentConfig) return Style; - } + + ChildFormatTextToApply.emplace_back( + llvm::MemoryBuffer::getMemBuffer(StyleName, Source, false)); } + if (!FS) + FS = llvm::vfs::getRealFileSystem().get(); + assert(FS); + // User provided clang-format file using -style=file:path/to/format/file. if (!Style.InheritsParentConfig && StyleName.starts_with_insensitive("file:")) { @@ -4015,18 +4016,12 @@ llvm::Expected getStyle(StringRef StyleName, StringRef FileName, return Style; } - // Reset possible inheritance - Style.InheritsParentConfig = false; - - // Look for .clang-format/_clang-format file in the file's parent directories. - SmallString<128> UnsuitableConfigFiles; SmallString<128> Path(FileName); if (std::error_code EC = FS->makeAbsolute(Path)) return make_string_error(EC.message()); - llvm::SmallVector FilesToLookFor; - FilesToLookFor.push_back(".clang-format"); - FilesToLookFor.push_back("_clang-format"); + // Reset possible inheritance + Style.InheritsParentConfig = false; auto dropDiagnosticHandler = [](const llvm::SMDiagnostic &, void *) {}; @@ -4040,9 +4035,14 @@ llvm::Expected getStyle(StringRef StyleName, StringRef FileName, } }; + // Look for .clang-format/_clang-format file in the file's parent directories. + llvm::SmallVector FilesToLookFor; + FilesToLookFor.push_back(".clang-format"); + FilesToLookFor.push_back("_clang-format"); + + SmallString<128> UnsuitableConfigFiles; for (StringRef Directory = Path; !Directory.empty(); Directory = llvm::sys::path::parent_path(Directory)) { - auto Status = FS->status(Directory); if (!Status || Status->getType() != llvm::sys::fs::file_type::directory_file) { @@ -4055,50 +4055,51 @@ llvm::Expected getStyle(StringRef StyleName, StringRef FileName, llvm::sys::path::append(ConfigFile, F); LLVM_DEBUG(llvm::dbgs() << "Trying " << ConfigFile << "...\n"); - Status = FS->status(ConfigFile.str()); - - if (Status && - (Status->getType() == llvm::sys::fs::file_type::regular_file)) { - llvm::ErrorOr> Text = - loadAndParseConfigFile(ConfigFile, FS, &Style, AllowUnknownOptions); - if (auto EC = Text.getError()) { - if (EC == ParseError::Unsuitable) { - if (!UnsuitableConfigFiles.empty()) - UnsuitableConfigFiles.append(", "); - UnsuitableConfigFiles.append(ConfigFile); - continue; - } + Status = FS->status(ConfigFile); + if (!Status || + Status->getType() != llvm::sys::fs::file_type::regular_file) { + continue; + } + + llvm::ErrorOr> Text = + loadAndParseConfigFile(ConfigFile, FS, &Style, AllowUnknownOptions); + if (auto EC = Text.getError()) { + if (EC != ParseError::Unsuitable) { return make_string_error("Error reading " + ConfigFile + ": " + EC.message()); } - LLVM_DEBUG(llvm::dbgs() - << "Using configuration file " << ConfigFile << "\n"); + if (!UnsuitableConfigFiles.empty()) + UnsuitableConfigFiles.append(", "); + UnsuitableConfigFiles.append(ConfigFile); + continue; + } - if (!Style.InheritsParentConfig) { - if (ChildFormatTextToApply.empty()) - return Style; + LLVM_DEBUG(llvm::dbgs() + << "Using configuration file " << ConfigFile << "\n"); + if (!Style.InheritsParentConfig) { + if (!ChildFormatTextToApply.empty()) { LLVM_DEBUG(llvm::dbgs() << "Applying child configurations\n"); applyChildFormatTexts(&Style); - - return Style; } + return Style; + } - LLVM_DEBUG(llvm::dbgs() << "Inherits parent configuration\n"); + LLVM_DEBUG(llvm::dbgs() << "Inherits parent configuration\n"); - // Reset inheritance of style - Style.InheritsParentConfig = false; + // Reset inheritance of style + Style.InheritsParentConfig = false; - ChildFormatTextToApply.emplace_back(std::move(*Text)); + ChildFormatTextToApply.emplace_back(std::move(*Text)); - // Breaking out of the inner loop, since we don't want to parse - // .clang-format AND _clang-format, if both exist. Then we continue the - // inner loop (parent directories) in search for the parent - // configuration. - break; - } + // Breaking out of the inner loop, since we don't want to parse + // .clang-format AND _clang-format, if both exist. Then we continue the + // outer loop (parent directories) in search for the parent + // configuration. + break; } } + if (!UnsuitableConfigFiles.empty()) { return make_string_error("Configuration file(s) do(es) not support " + getLanguageName(Style.Language) + ": " + diff --git a/clang/lib/Format/ObjCPropertyAttributeOrderFixer.cpp b/clang/lib/Format/ObjCPropertyAttributeOrderFixer.cpp index 20108306f1039f047d35c337e30f8259f28e21ff..c91d6251425eab508c3c196c66ba77774f9fabdb 100644 --- a/clang/lib/Format/ObjCPropertyAttributeOrderFixer.cpp +++ b/clang/lib/Format/ObjCPropertyAttributeOrderFixer.cpp @@ -15,8 +15,6 @@ #include "ObjCPropertyAttributeOrderFixer.h" -#include "llvm/ADT/Sequence.h" - #include namespace clang { @@ -25,26 +23,20 @@ namespace format { ObjCPropertyAttributeOrderFixer::ObjCPropertyAttributeOrderFixer( const Environment &Env, const FormatStyle &Style) : TokenAnalyzer(Env, Style) { - // Create an "order priority" map to use to sort properties. - unsigned index = 0; + unsigned Index = 0; for (const auto &Property : Style.ObjCPropertyAttributeOrder) - SortOrderMap[Property] = index++; + SortOrderMap[Property] = Index++; } struct ObjCPropertyEntry { - StringRef Attribute; // eg, "readwrite" - StringRef Value; // eg, the "foo" of the attribute "getter=foo" + StringRef Attribute; // eg, `readwrite` + StringRef Value; // eg, the `foo` of the attribute `getter=foo` }; -static bool isObjCPropertyAttribute(const FormatToken *Tok) { - // Most attributes look like identifiers, but `class` is a keyword. - return Tok->isOneOf(tok::identifier, tok::kw_class); -} - void ObjCPropertyAttributeOrderFixer::sortPropertyAttributes( const SourceManager &SourceMgr, tooling::Replacements &Fixes, - const FormatToken *BeginTok, const FormatToken *EndTok) const { + const FormatToken *BeginTok, const FormatToken *EndTok) { assert(BeginTok); assert(EndTok); assert(EndTok->Previous); @@ -53,8 +45,16 @@ void ObjCPropertyAttributeOrderFixer::sortPropertyAttributes( if (BeginTok == EndTok || BeginTok->Next == EndTok) return; + // Use a set to sort attributes and remove duplicates. + std::set Ordinals; + + // Create a "remapping index" on how to reorder the attributes. + SmallVector Indices; + // Collect the attributes. - SmallVector PropertyAttributes; + SmallVector PropertyAttributes; + bool HasDuplicates = false; + int Index = 0; for (auto Tok = BeginTok; Tok != EndTok; Tok = Tok->Next) { assert(Tok); if (Tok->is(tok::comma)) { @@ -62,13 +62,14 @@ void ObjCPropertyAttributeOrderFixer::sortPropertyAttributes( continue; } - if (!isObjCPropertyAttribute(Tok)) { + // Most attributes look like identifiers, but `class` is a keyword. + if (!Tok->isOneOf(tok::identifier, tok::kw_class)) { // If we hit any other kind of token, just bail. return; } - // Memoize the attribute. (Note that 'class' is a legal attribute!) - PropertyAttributes.push_back({Tok->TokenText, StringRef{}}); + const StringRef Attribute{Tok->TokenText}; + StringRef Value; // Also handle `getter=getFoo` attributes. // (Note: no check needed against `EndTok`, since its type is not @@ -82,49 +83,66 @@ void ObjCPropertyAttributeOrderFixer::sortPropertyAttributes( return; } Tok = Tok->Next; - PropertyAttributes.back().Value = Tok->TokenText; + Value = Tok->TokenText; + } + + auto It = SortOrderMap.find(Attribute); + if (It == SortOrderMap.end()) + It = SortOrderMap.insert({Attribute, SortOrderMap.size()}).first; + + // Sort the indices based on the priority stored in `SortOrderMap`. + const auto Ordinal = It->second; + if (!Ordinals.insert(Ordinal).second) { + HasDuplicates = true; + continue; } + + if (Ordinal >= Indices.size()) + Indices.resize(Ordinal + 1); + Indices[Ordinal] = Index++; + + // Memoize the attribute. + PropertyAttributes.push_back({Attribute, Value}); } - // There's nothing to do unless there's more than one attribute. - if (PropertyAttributes.size() < 2) - return; + if (!HasDuplicates) { + // There's nothing to do unless there's more than one attribute. + if (PropertyAttributes.size() < 2) + return; - // Create a "remapping index" on how to reorder the attributes. - SmallVector Indices = - llvm::to_vector<8>(llvm::seq(0, PropertyAttributes.size())); - - // Sort the indices based on the priority stored in 'SortOrderMap'; use Max - // for missing values. - const auto SortOrderMax = Style.ObjCPropertyAttributeOrder.size(); - auto SortIndex = [&](const StringRef &Needle) -> unsigned { - auto I = SortOrderMap.find(Needle); - return (I == SortOrderMap.end()) ? SortOrderMax : I->getValue(); - }; - llvm::stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) { - return SortIndex(PropertyAttributes[LHSI].Attribute) < - SortIndex(PropertyAttributes[RHSI].Attribute); - }); - - // If the property order is already correct, then no fix-up is needed. - if (llvm::is_sorted(Indices)) - return; + int PrevIndex = -1; + bool IsSorted = true; + for (const auto Ordinal : Ordinals) { + const auto Index = Indices[Ordinal]; + if (Index < PrevIndex) { + IsSorted = false; + break; + } + assert(Index > PrevIndex); + PrevIndex = Index; + } + + // If the property order is already correct, then no fix-up is needed. + if (IsSorted) + return; + } // Generate the replacement text. std::string NewText; - const auto AppendAttribute = [&](const ObjCPropertyEntry &PropertyEntry) { + bool IsFirst = true; + for (const auto Ordinal : Ordinals) { + if (IsFirst) + IsFirst = false; + else + NewText += ", "; + + const auto &PropertyEntry = PropertyAttributes[Indices[Ordinal]]; NewText += PropertyEntry.Attribute; - if (!PropertyEntry.Value.empty()) { - NewText += "="; - NewText += PropertyEntry.Value; + if (const auto Value = PropertyEntry.Value; !Value.empty()) { + NewText += '='; + NewText += Value; } - }; - - AppendAttribute(PropertyAttributes[Indices[0]]); - for (unsigned Index : llvm::drop_begin(Indices)) { - NewText += ", "; - AppendAttribute(PropertyAttributes[Index]); } auto Range = CharSourceRange::getCharRange( @@ -139,7 +157,7 @@ void ObjCPropertyAttributeOrderFixer::sortPropertyAttributes( void ObjCPropertyAttributeOrderFixer::analyzeObjCPropertyDecl( const SourceManager &SourceMgr, const AdditionalKeywords &Keywords, - tooling::Replacements &Fixes, const FormatToken *Tok) const { + tooling::Replacements &Fixes, const FormatToken *Tok) { assert(Tok); // Expect `property` to be the very next token or else just bail early. diff --git a/clang/lib/Format/ObjCPropertyAttributeOrderFixer.h b/clang/lib/Format/ObjCPropertyAttributeOrderFixer.h index 99f0dd338f6088d99b0675f6b19ac7c974e56b8f..d9ce85d144afb2b683731c12ae768d198b5ebead 100644 --- a/clang/lib/Format/ObjCPropertyAttributeOrderFixer.h +++ b/clang/lib/Format/ObjCPropertyAttributeOrderFixer.h @@ -28,12 +28,12 @@ class ObjCPropertyAttributeOrderFixer : public TokenAnalyzer { void analyzeObjCPropertyDecl(const SourceManager &SourceMgr, const AdditionalKeywords &Keywords, tooling::Replacements &Fixes, - const FormatToken *Tok) const; + const FormatToken *Tok); void sortPropertyAttributes(const SourceManager &SourceMgr, tooling::Replacements &Fixes, const FormatToken *BeginTok, - const FormatToken *EndTok) const; + const FormatToken *EndTok); std::pair analyze(TokenAnnotator &Annotator, diff --git a/clang/lib/Format/TokenAnnotator.h b/clang/lib/Format/TokenAnnotator.h index 58e2cf79f488fa42cc245d0eec03050abab164a4..05a6daa87d8034045bb23a6493839604d10913c5 100644 --- a/clang/lib/Format/TokenAnnotator.h +++ b/clang/lib/Format/TokenAnnotator.h @@ -156,6 +156,11 @@ public: return First->is(tok::comment) ? First->getNextNonComment() : First; } + FormatToken *getLastNonComment() const { + assert(Last); + return Last->is(tok::comment) ? Last->getPreviousNonComment() : Last; + } + FormatToken *First; FormatToken *Last; diff --git a/clang/lib/Format/UnwrappedLineFormatter.cpp b/clang/lib/Format/UnwrappedLineFormatter.cpp index 40730cd53529ed356fc5be78005f88e069bbe08d..56077499c39d539ab69a94786a202d89af3e264c 100644 --- a/clang/lib/Format/UnwrappedLineFormatter.cpp +++ b/clang/lib/Format/UnwrappedLineFormatter.cpp @@ -346,14 +346,10 @@ private: return false; // Check if the found line starts a record. - const FormatToken *LastNonComment = Line->Last; + const auto *LastNonComment = Line->getLastNonComment(); + // There must be another token (usually `{`), because we chose a + // non-PPDirective and non-comment line that has a smaller level. assert(LastNonComment); - if (LastNonComment->is(tok::comment)) { - LastNonComment = LastNonComment->getPreviousNonComment(); - // There must be another token (usually `{`), because we chose a - // non-PPDirective and non-comment line that has a smaller level. - assert(LastNonComment); - } return isRecordLBrace(*LastNonComment); } } @@ -363,12 +359,9 @@ private: bool MergeShortFunctions = ShouldMergeShortFunctions(); - const FormatToken *FirstNonComment = TheLine->First; - if (FirstNonComment->is(tok::comment)) { - FirstNonComment = FirstNonComment->getNextNonComment(); - if (!FirstNonComment) - return 0; - } + const auto *FirstNonComment = TheLine->getFirstNonComment(); + if (!FirstNonComment) + return 0; // FIXME: There are probably cases where we should use FirstNonComment // instead of TheLine->First. @@ -418,9 +411,16 @@ private: } } + const auto *LastNonComment = TheLine->getLastNonComment(); + assert(LastNonComment); + // FIXME: There are probably cases where we should use LastNonComment + // instead of TheLine->Last. + // Try to merge a function block with left brace unwrapped. - if (TheLine->Last->is(TT_FunctionLBrace) && TheLine->First != TheLine->Last) + if (LastNonComment->is(TT_FunctionLBrace) && + TheLine->First != LastNonComment) { return MergeShortFunctions ? tryMergeSimpleBlock(I, E, Limit) : 0; + } // Try to merge a control statement block with left brace unwrapped. if (TheLine->Last->is(tok::l_brace) && FirstNonComment != TheLine->Last && FirstNonComment->isOneOf(tok::kw_if, tok::kw_while, tok::kw_for, @@ -796,7 +796,8 @@ private: } } - if (Line.Last->is(tok::l_brace)) { + if (const auto *LastNonComment = Line.getLastNonComment(); + LastNonComment && LastNonComment->is(tok::l_brace)) { if (IsSplitBlock && Line.First == Line.Last && I > AnnotatedLines.begin() && (I[-1]->endsWith(tok::kw_else) || IsCtrlStmt(*I[-1]))) { @@ -812,7 +813,8 @@ private: if (ShouldMerge()) { // We merge empty blocks even if the line exceeds the column limit. - Tok->SpacesRequiredBefore = Style.SpaceInEmptyBlock ? 1 : 0; + Tok->SpacesRequiredBefore = + (Style.SpaceInEmptyBlock || Line.Last->is(tok::comment)) ? 1 : 0; Tok->CanBreakBefore = true; return 1; } else if (Limit != 0 && !Line.startsWithNamespace() && diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp index e5f8c0746a99dd457bd4727d83f82531474fd70c..56bbef9697b650073778b1db61fdbb2c49ec8b38 100644 --- a/clang/lib/Frontend/CompilerInstance.cpp +++ b/clang/lib/Frontend/CompilerInstance.cpp @@ -2260,7 +2260,7 @@ GlobalModuleIndex *CompilerInstance::loadGlobalModuleIndex( for (ModuleMap::module_iterator I = MMap.module_begin(), E = MMap.module_end(); I != E; ++I) { Module *TheModule = I->second; - const FileEntry *Entry = TheModule->getASTFile(); + OptionalFileEntryRef Entry = TheModule->getASTFile(); if (!Entry) { SmallVector, 2> Path; Path.push_back(std::make_pair( diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index be0d4963a20921d390904368abd01393c67909c6..b33bdad2ad81bad041c9ca791066ac347706d1e7 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -4365,6 +4365,9 @@ static void GeneratePreprocessorArgs(const PreprocessorOptions &Opts, if (Opts.SourceDateEpoch) GenerateArg(Consumer, OPT_source_date_epoch, Twine(*Opts.SourceDateEpoch)); + if (Opts.DefineTargetOSMacros) + GenerateArg(Consumer, OPT_fdefine_target_os_macros); + // Don't handle LexEditorPlaceholders. It is implied by the action that is // generated elsewhere. } @@ -4463,6 +4466,10 @@ static bool ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args, if (isStrictlyPreprocessorAction(Action)) Opts.LexEditorPlaceholders = false; + Opts.DefineTargetOSMacros = + Args.hasFlag(OPT_fdefine_target_os_macros, + OPT_fno_define_target_os_macros, Opts.DefineTargetOSMacros); + return Diags.getNumErrors() == NumErrorsBefore; } @@ -4787,6 +4794,18 @@ std::string CompilerInvocation::getModuleHash() const { if (getCodeGenOpts().DebugTypeExtRefs) HBuilder.addRange(getCodeGenOpts().DebugPrefixMap); + // Extend the signature with the affecting debug options. + if (getHeaderSearchOpts().ModuleFormat == "obj") { +#define DEBUGOPT(Name, Bits, Default) HBuilder.add(CodeGenOpts->Name); +#define VALUE_DEBUGOPT(Name, Bits, Default) HBuilder.add(CodeGenOpts->Name); +#define ENUM_DEBUGOPT(Name, Type, Bits, Default) \ + HBuilder.add(static_cast(CodeGenOpts->get##Name())); +#define BENIGN_DEBUGOPT(Name, Bits, Default) +#define BENIGN_VALUE_DEBUGOPT(Name, Bits, Default) +#define BENIGN_ENUM_DEBUGOPT(Name, Type, Bits, Default) +#include "clang/Basic/DebugOptions.def" + } + // Extend the signature with the enabled sanitizers, if at least one is // enabled. Sanitizers which cannot affect AST generation aren't hashed. SanitizerSet SanHash = getLangOpts().Sanitize; @@ -4833,6 +4852,7 @@ std::vector CompilerInvocationBase::getCC1CommandLine() const { void CompilerInvocation::resetNonModularOptions() { getLangOpts().resetNonModularOptions(); getPreprocessorOpts().resetNonModularOptions(); + getCodeGenOpts().resetNonModularOptions(getHeaderSearchOpts().ModuleFormat); } void CompilerInvocation::clearImplicitModuleBuildOptions() { diff --git a/clang/lib/Frontend/FrontendActions.cpp b/clang/lib/Frontend/FrontendActions.cpp index 2afcf1cf9f68c819d6ddc59da5bbcc5c70063827..c1d6e71455365c980b7e8cef3160698c50e40595 100644 --- a/clang/lib/Frontend/FrontendActions.cpp +++ b/clang/lib/Frontend/FrontendActions.cpp @@ -258,6 +258,16 @@ bool GenerateModuleInterfaceAction::BeginSourceFileAction( return GenerateModuleAction::BeginSourceFileAction(CI); } +std::unique_ptr +GenerateModuleInterfaceAction::CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) { + CI.getHeaderSearchOpts().ModulesSkipDiagnosticOptions = true; + CI.getHeaderSearchOpts().ModulesSkipHeaderSearchPaths = true; + CI.getHeaderSearchOpts().ModulesSkipPragmaDiagnosticMappings = true; + + return GenerateModuleAction::CreateASTConsumer(CI, InFile); +} + std::unique_ptr GenerateModuleInterfaceAction::CreateOutputFile(CompilerInstance &CI, StringRef InFile) { diff --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp index 17948dcebd7e55a2d7412889ef1f20c91717e135..d83128adb511ef4f999cfebf529bf6ac998d74c6 100644 --- a/clang/lib/Frontend/InitPreprocessor.cpp +++ b/clang/lib/Frontend/InitPreprocessor.cpp @@ -809,6 +809,13 @@ static void InitializePredefinedMacros(const TargetInfo &TI, Builder.defineMacro("__ATOMIC_ACQ_REL", "4"); Builder.defineMacro("__ATOMIC_SEQ_CST", "5"); + // Define macros for the clang atomic scopes. + Builder.defineMacro("__MEMORY_SCOPE_SYSTEM", "0"); + Builder.defineMacro("__MEMORY_SCOPE_DEVICE", "1"); + Builder.defineMacro("__MEMORY_SCOPE_WRKGRP", "2"); + Builder.defineMacro("__MEMORY_SCOPE_WVFRNT", "3"); + Builder.defineMacro("__MEMORY_SCOPE_SINGLE", "4"); + // Define macros for the OpenCL memory scope. // The values should match AtomicScopeOpenCLModel::ID enum. static_assert( @@ -1344,6 +1351,15 @@ static void InitializePredefinedMacros(const TargetInfo &TI, if (TI.getTriple().isOSBinFormatELF()) Builder.defineMacro("__ELF__"); + // Target OS macro definitions. + if (PPOpts.DefineTargetOSMacros) { + const llvm::Triple &Triple = TI.getTriple(); +#define TARGET_OS(Name, Predicate) \ + Builder.defineMacro(#Name, (Predicate) ? "1" : "0"); +#include "clang/Basic/TargetOSMacros.def" +#undef TARGET_OS + } + // Get other target #defines. TI.getTargetDefines(LangOpts, Builder); } diff --git a/clang/lib/Headers/bmiintrin.h b/clang/lib/Headers/bmiintrin.h index ffb94bea639af6993956c11d4485e64df8759bd8..bc7c8a03c5e2a0de64a2a8bfe7e9a5b563ad7453 100644 --- a/clang/lib/Headers/bmiintrin.h +++ b/clang/lib/Headers/bmiintrin.h @@ -19,7 +19,7 @@ to use it as a potentially faster version of BSF. */ #define __RELAXED_FN_ATTRS __attribute__((__always_inline__, __nodebug__)) -#define _tzcnt_u16(a) (__tzcnt_u16((a))) +#define _tzcnt_u16 __tzcnt_u16 /// Counts the number of trailing zero bits in the operand. /// @@ -71,7 +71,7 @@ _mm_tzcnt_32(unsigned int __X) return (int)__builtin_ia32_tzcnt_u32(__X); } -#define _tzcnt_u32(a) (__tzcnt_u32((a))) +#define _tzcnt_u32 __tzcnt_u32 #ifdef __x86_64__ @@ -109,7 +109,7 @@ _mm_tzcnt_64(unsigned long long __X) return (long long)__builtin_ia32_tzcnt_u64(__X); } -#define _tzcnt_u64(a) (__tzcnt_u64((a))) +#define _tzcnt_u64 __tzcnt_u64 #endif /* __x86_64__ */ @@ -121,14 +121,14 @@ _mm_tzcnt_64(unsigned long long __X) /* Define the default attributes for the functions in this file. */ #define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("bmi"))) -#define _andn_u32(a, b) (__andn_u32((a), (b))) +#define _andn_u32 __andn_u32 /* _bextr_u32 != __bextr_u32 */ -#define _blsi_u32(a) (__blsi_u32((a))) +#define _blsi_u32 __blsi_u32 -#define _blsmsk_u32(a) (__blsmsk_u32((a))) +#define _blsmsk_u32 __blsmsk_u32 -#define _blsr_u32(a) (__blsr_u32((a))) +#define _blsr_u32 __blsr_u32 /// Performs a bitwise AND of the second operand with the one's /// complement of the first operand. @@ -272,14 +272,14 @@ __blsr_u32(unsigned int __X) #ifdef __x86_64__ -#define _andn_u64(a, b) (__andn_u64((a), (b))) +#define _andn_u64 __andn_u64 /* _bextr_u64 != __bextr_u64 */ -#define _blsi_u64(a) (__blsi_u64((a))) +#define _blsi_u64 __blsi_u64 -#define _blsmsk_u64(a) (__blsmsk_u64((a))) +#define _blsmsk_u64 __blsmsk_u64 -#define _blsr_u64(a) (__blsr_u64((a))) +#define _blsr_u64 __blsr_u64 /// Performs a bitwise AND of the second operand with the one's /// complement of the first operand. diff --git a/clang/lib/IndexSerialization/SerializablePathCollection.cpp b/clang/lib/IndexSerialization/SerializablePathCollection.cpp index 34663738088e8fa4fb40c793faa47cbf4779ff67..bd5f861bf482e511168ca428bdf7046aacb4751b 100644 --- a/clang/lib/IndexSerialization/SerializablePathCollection.cpp +++ b/clang/lib/IndexSerialization/SerializablePathCollection.cpp @@ -45,8 +45,8 @@ SerializablePathCollection::SerializablePathCollection( SysRootPath(Paths.addDirPath(SysRoot)), OutputFilePath(Paths.addDirPath(OutputFile)) {} -size_t SerializablePathCollection::tryStoreFilePath(const FileEntry &FE) { - auto FileIt = UniqueFiles.find(&FE); +size_t SerializablePathCollection::tryStoreFilePath(FileEntryRef FE) { + auto FileIt = UniqueFiles.find(FE); if (FileIt != UniqueFiles.end()) return FileIt->second; @@ -54,7 +54,7 @@ size_t SerializablePathCollection::tryStoreFilePath(const FileEntry &FE) { const auto FileIdx = Paths.addFilePath(Dir.Root, Dir.Path, sys::path::filename(FE.getName())); - UniqueFiles.try_emplace(&FE, FileIdx); + UniqueFiles.try_emplace(FE, FileIdx); return FileIdx; } diff --git a/clang/lib/Lex/HeaderSearch.cpp b/clang/lib/Lex/HeaderSearch.cpp index cf1c0cc5284f316db41324f8c2c934ec98c99029..c03cf19688d961adb9a02e33b4390b6cbf2b4748 100644 --- a/clang/lib/Lex/HeaderSearch.cpp +++ b/clang/lib/Lex/HeaderSearch.cpp @@ -105,7 +105,7 @@ void HeaderSearch::PrintStats() { void HeaderSearch::SetSearchPaths( std::vector dirs, unsigned int angledDirIdx, - unsigned int systemDirIdx, bool noCurDirSearch, + unsigned int systemDirIdx, llvm::DenseMap searchDirToHSEntry) { assert(angledDirIdx <= systemDirIdx && systemDirIdx <= dirs.size() && "Directory indices are unordered"); @@ -113,7 +113,6 @@ void HeaderSearch::SetSearchPaths( SearchDirsUsage.assign(SearchDirs.size(), false); AngledDirIdx = angledDirIdx; SystemDirIdx = systemDirIdx; - NoCurDirSearch = noCurDirSearch; SearchDirToHSEntry = std::move(searchDirToHSEntry); //LookupFileCache.clear(); indexInitialHeaderMaps(); @@ -904,12 +903,12 @@ OptionalFileEntryRef HeaderSearch::LookupFile( ModuleMap::KnownHeader MSSuggestedModule; OptionalFileEntryRef MSFE; - // Unless disabled, check to see if the file is in the #includer's - // directory. This cannot be based on CurDir, because each includer could be - // a #include of a subdirectory (#include "foo/bar.h") and a subsequent - // include of "baz.h" should resolve to "whatever/foo/baz.h". - // This search is not done for <> headers. - if (!Includers.empty() && !isAngled && !NoCurDirSearch) { + // Check to see if the file is in the #includer's directory. This cannot be + // based on CurDir, because each includer could be a #include of a + // subdirectory (#include "foo/bar.h") and a subsequent include of "baz.h" + // should resolve to "whatever/foo/baz.h". This search is not done for <> + // headers. + if (!Includers.empty() && !isAngled) { SmallString<1024> TmpDir; bool First = true; for (const auto &IncluderAndDir : Includers) { diff --git a/clang/lib/Lex/InitHeaderSearch.cpp b/clang/lib/Lex/InitHeaderSearch.cpp index 1f4c7a6d67b7f79bc2bb7ee22d2bcd4de80c99e0..5b1b7c859c85d9346858ee7472f6cfd3d9838f8e 100644 --- a/clang/lib/Lex/InitHeaderSearch.cpp +++ b/clang/lib/Lex/InitHeaderSearch.cpp @@ -513,9 +513,8 @@ void InitHeaderSearch::Realize(const LangOptions &Lang) { unsigned NonSystemRemoved = RemoveDuplicates(SearchList, NumQuoted, Verbose); NumAngled -= NonSystemRemoved; - bool DontSearchCurDir = false; // TODO: set to true if -I- is set? Headers.SetSearchPaths(extractLookups(SearchList), NumQuoted, NumAngled, - DontSearchCurDir, mapToUserEntries(SearchList)); + mapToUserEntries(SearchList)); Headers.SetSystemHeaderPrefixes(SystemHeaderPrefixes); diff --git a/clang/lib/Lex/ModuleMap.cpp b/clang/lib/Lex/ModuleMap.cpp index 1d67e275cb4775a15dce3a9543a142d88d914573..d35c282543c564d6ac94f8db51d50d38f5a4f7db 100644 --- a/clang/lib/Lex/ModuleMap.cpp +++ b/clang/lib/Lex/ModuleMap.cpp @@ -1067,9 +1067,7 @@ Module *ModuleMap::inferFrameworkModule(DirectoryEntryRef FrameworkDir, if (!canInfer) return nullptr; } else { - OptionalFileEntryRefDegradesToFileEntryPtr ModuleMapRef = - getModuleMapFileForUniquing(Parent); - ModuleMapFile = ModuleMapRef; + ModuleMapFile = getModuleMapFileForUniquing(Parent); } // Look for an umbrella header. @@ -1866,7 +1864,7 @@ void ModuleMapParser::diagnosePrivateModules(SourceLocation ExplicitLoc, continue; SmallString<128> FullName(ActiveModule->getFullModuleName()); - if (!FullName.startswith(M->Name) && !FullName.endswith("Private")) + if (!FullName.starts_with(M->Name) && !FullName.ends_with("Private")) continue; SmallString<128> FixedPrivModDecl; SmallString<128> Canonical(M->Name); diff --git a/clang/lib/Lex/PPDirectives.cpp b/clang/lib/Lex/PPDirectives.cpp index 956e2276f25b710174fdb1c34b51c0948cc0a9a0..14003480d7fa2e91f38a363a7932879fec2f2d9e 100644 --- a/clang/lib/Lex/PPDirectives.cpp +++ b/clang/lib/Lex/PPDirectives.cpp @@ -1934,7 +1934,8 @@ Preprocessor::getIncludeNextStart(const Token &IncludeNextTok) const { // Start looking up in the directory *after* the one in which the current // file would be found, if any. assert(CurPPLexer && "#include_next directive in macro?"); - LookupFromFile = CurPPLexer->getFileEntry(); + if (auto FE = CurPPLexer->getFileEntry()) + LookupFromFile = *FE; Lookup = nullptr; } else if (!Lookup) { // The current file was not found by walking the include path. Either it diff --git a/clang/lib/Lex/Pragma.cpp b/clang/lib/Lex/Pragma.cpp index 35ab42cb6b5ef852e3a1c34dba0a5115fbcd64b8..499813f8ab7df0e6f81f8b84e2d8ea5b6cd5399b 100644 --- a/clang/lib/Lex/Pragma.cpp +++ b/clang/lib/Lex/Pragma.cpp @@ -548,7 +548,7 @@ void Preprocessor::HandlePragmaDependency(Token &DependencyTok) { return; } - const FileEntry *CurFile = getCurrentFileLexer()->getFileEntry(); + OptionalFileEntryRef CurFile = getCurrentFileLexer()->getFileEntry(); // If this file is older than the file it depends on, emit a diagnostic. if (CurFile && CurFile->getModificationTime() < File->getModificationTime()) { diff --git a/clang/lib/Lex/PreprocessorLexer.cpp b/clang/lib/Lex/PreprocessorLexer.cpp index 23c80d375214c69b6b7343b96888835e811fe8b4..7551ba235fe9b85b331c913c752e2d4dacb418b8 100644 --- a/clang/lib/Lex/PreprocessorLexer.cpp +++ b/clang/lib/Lex/PreprocessorLexer.cpp @@ -47,7 +47,6 @@ void PreprocessorLexer::LexIncludeFilename(Token &FilenameTok) { /// getFileEntry - Return the FileEntry corresponding to this FileID. Like /// getFileID(), this only works for lexers with attached preprocessors. -OptionalFileEntryRefDegradesToFileEntryPtr -PreprocessorLexer::getFileEntry() const { +OptionalFileEntryRef PreprocessorLexer::getFileEntry() const { return PP->getSourceManager().getFileEntryRefForID(getFileID()); } diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index 8b86db1bb8fc5d55914c788974ef1979d2ea1e75..2fc364fc811b3245f9a37fac80920ad81872e3f2 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -1548,7 +1548,7 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( if (!Stmt.isInvalid() && !TrailingReturnType.isInvalid() && !D.isInvalidType()) - return Actions.ActOnLambdaExpr(LambdaBeginLoc, Stmt.get(), getCurScope()); + return Actions.ActOnLambdaExpr(LambdaBeginLoc, Stmt.get()); Actions.ActOnLambdaError(LambdaBeginLoc, getCurScope()); return ExprError(); diff --git a/clang/lib/Parse/ParseOpenACC.cpp b/clang/lib/Parse/ParseOpenACC.cpp index 4021d50318561fd4bf3d9ab3116c1ee3577abfc8..f7f096762e91a64b25eca104d1c352bbff9f4480 100644 --- a/clang/lib/Parse/ParseOpenACC.cpp +++ b/clang/lib/Parse/ParseOpenACC.cpp @@ -36,15 +36,19 @@ enum class OpenACCDirectiveKindEx { // identifies the first token), and doesn't fully handle 'enter data', 'exit // data', nor any of the 'atomic' variants, just the first token of each. So // this should only be used by `ParseOpenACCDirectiveKind`. -OpenACCDirectiveKindEx getOpenACCDirectiveKind(StringRef Name) { +OpenACCDirectiveKindEx getOpenACCDirectiveKind(Token Tok) { + if (!Tok.is(tok::identifier)) + return OpenACCDirectiveKindEx::Invalid; OpenACCDirectiveKind DirKind = - llvm::StringSwitch(Name) + llvm::StringSwitch( + Tok.getIdentifierInfo()->getName()) .Case("parallel", OpenACCDirectiveKind::Parallel) .Case("serial", OpenACCDirectiveKind::Serial) .Case("kernels", OpenACCDirectiveKind::Kernels) .Case("data", OpenACCDirectiveKind::Data) .Case("host_data", OpenACCDirectiveKind::HostData) .Case("loop", OpenACCDirectiveKind::Loop) + .Case("cache", OpenACCDirectiveKind::Cache) .Case("atomic", OpenACCDirectiveKind::Atomic) .Case("routine", OpenACCDirectiveKind::Routine) .Case("declare", OpenACCDirectiveKind::Declare) @@ -52,12 +56,14 @@ OpenACCDirectiveKindEx getOpenACCDirectiveKind(StringRef Name) { .Case("shutdown", OpenACCDirectiveKind::Shutdown) .Case("set", OpenACCDirectiveKind::Shutdown) .Case("update", OpenACCDirectiveKind::Update) + .Case("wait", OpenACCDirectiveKind::Wait) .Default(OpenACCDirectiveKind::Invalid); if (DirKind != OpenACCDirectiveKind::Invalid) return static_cast(DirKind); - return llvm::StringSwitch(Name) + return llvm::StringSwitch( + Tok.getIdentifierInfo()->getName()) .Case("enter", OpenACCDirectiveKindEx::Enter) .Case("exit", OpenACCDirectiveKindEx::Exit) .Default(OpenACCDirectiveKindEx::Invalid); @@ -65,8 +71,11 @@ OpenACCDirectiveKindEx getOpenACCDirectiveKind(StringRef Name) { // Since 'atomic' is effectively a compound directive, this will decode the // second part of the directive. -OpenACCAtomicKind getOpenACCAtomicKind(StringRef Name) { - return llvm::StringSwitch(Name) +OpenACCAtomicKind getOpenACCAtomicKind(Token Tok) { + if (!Tok.is(tok::identifier)) + return OpenACCAtomicKind::Invalid; + return llvm::StringSwitch( + Tok.getIdentifierInfo()->getName()) .Case("read", OpenACCAtomicKind::Read) .Case("write", OpenACCAtomicKind::Write) .Case("update", OpenACCAtomicKind::Update) @@ -74,20 +83,46 @@ OpenACCAtomicKind getOpenACCAtomicKind(StringRef Name) { .Default(OpenACCAtomicKind::Invalid); } -bool isOpenACCDirectiveKind(OpenACCDirectiveKind Kind, StringRef Tok) { +enum class OpenACCSpecialTokenKind { + ReadOnly, + DevNum, + Queues, +}; + +bool isOpenACCSpecialToken(OpenACCSpecialTokenKind Kind, Token Tok) { + if (!Tok.is(tok::identifier)) + return false; + + switch (Kind) { + case OpenACCSpecialTokenKind::ReadOnly: + return Tok.getIdentifierInfo()->isStr("readonly"); + case OpenACCSpecialTokenKind::DevNum: + return Tok.getIdentifierInfo()->isStr("devnum"); + case OpenACCSpecialTokenKind::Queues: + return Tok.getIdentifierInfo()->isStr("queues"); + } + llvm_unreachable("Unknown 'Kind' Passed"); +} + +bool isOpenACCDirectiveKind(OpenACCDirectiveKind Kind, Token Tok) { + if (!Tok.is(tok::identifier)) + return false; + switch (Kind) { case OpenACCDirectiveKind::Parallel: - return Tok == "parallel"; + return Tok.getIdentifierInfo()->isStr("parallel"); case OpenACCDirectiveKind::Serial: - return Tok == "serial"; + return Tok.getIdentifierInfo()->isStr("serial"); case OpenACCDirectiveKind::Kernels: - return Tok == "kernels"; + return Tok.getIdentifierInfo()->isStr("kernels"); case OpenACCDirectiveKind::Data: - return Tok == "data"; + return Tok.getIdentifierInfo()->isStr("data"); case OpenACCDirectiveKind::HostData: - return Tok == "host_data"; + return Tok.getIdentifierInfo()->isStr("host_data"); case OpenACCDirectiveKind::Loop: - return Tok == "loop"; + return Tok.getIdentifierInfo()->isStr("loop"); + case OpenACCDirectiveKind::Cache: + return Tok.getIdentifierInfo()->isStr("cache"); case OpenACCDirectiveKind::ParallelLoop: case OpenACCDirectiveKind::SerialLoop: @@ -97,19 +132,21 @@ bool isOpenACCDirectiveKind(OpenACCDirectiveKind Kind, StringRef Tok) { return false; case OpenACCDirectiveKind::Atomic: - return Tok == "atomic"; + return Tok.getIdentifierInfo()->isStr("atomic"); case OpenACCDirectiveKind::Routine: - return Tok == "routine"; + return Tok.getIdentifierInfo()->isStr("routine"); case OpenACCDirectiveKind::Declare: - return Tok == "declare"; + return Tok.getIdentifierInfo()->isStr("declare"); case OpenACCDirectiveKind::Init: - return Tok == "init"; + return Tok.getIdentifierInfo()->isStr("init"); case OpenACCDirectiveKind::Shutdown: - return Tok == "shutdown"; + return Tok.getIdentifierInfo()->isStr("shutdown"); case OpenACCDirectiveKind::Set: - return Tok == "set"; + return Tok.getIdentifierInfo()->isStr("set"); case OpenACCDirectiveKind::Update: - return Tok == "update"; + return Tok.getIdentifierInfo()->isStr("update"); + case OpenACCDirectiveKind::Wait: + return Tok.getIdentifierInfo()->isStr("wait"); case OpenACCDirectiveKind::Invalid: return false; } @@ -118,20 +155,22 @@ bool isOpenACCDirectiveKind(OpenACCDirectiveKind Kind, StringRef Tok) { OpenACCDirectiveKind ParseOpenACCEnterExitDataDirective(Parser &P, Token FirstTok, - StringRef FirstTokSpelling, OpenACCDirectiveKindEx ExtDirKind) { Token SecondTok = P.getCurToken(); if (SecondTok.isAnnotation()) { - P.Diag(FirstTok, diag::err_acc_invalid_directive) << 0 << FirstTokSpelling; + P.Diag(FirstTok, diag::err_acc_invalid_directive) + << 0 << FirstTok.getIdentifierInfo(); return OpenACCDirectiveKind::Invalid; } - std::string SecondTokSpelling = P.getPreprocessor().getSpelling(SecondTok); - - if (!isOpenACCDirectiveKind(OpenACCDirectiveKind::Data, SecondTokSpelling)) { - P.Diag(FirstTok, diag::err_acc_invalid_directive) - << 1 << FirstTokSpelling << SecondTokSpelling; + if (!isOpenACCDirectiveKind(OpenACCDirectiveKind::Data, SecondTok)) { + if (!SecondTok.is(tok::identifier)) + P.Diag(SecondTok, diag::err_expected) << tok::identifier; + else + P.Diag(FirstTok, diag::err_acc_invalid_directive) + << 1 << FirstTok.getIdentifierInfo()->getName() + << SecondTok.getIdentifierInfo()->getName(); return OpenACCDirectiveKind::Invalid; } @@ -149,9 +188,7 @@ OpenACCAtomicKind ParseOpenACCAtomicKind(Parser &P) { if (AtomicClauseToken.isAnnotation()) return OpenACCAtomicKind::Update; - std::string AtomicClauseSpelling = - P.getPreprocessor().getSpelling(AtomicClauseToken); - OpenACCAtomicKind AtomicKind = getOpenACCAtomicKind(AtomicClauseSpelling); + OpenACCAtomicKind AtomicKind = getOpenACCAtomicKind(AtomicClauseToken); // If we don't know what this is, treat it as 'nothing', and treat the rest of // this as a clause list, which, despite being invalid, is likely what the @@ -169,15 +206,14 @@ OpenACCDirectiveKind ParseOpenACCDirectiveKind(Parser &P) { // Just #pragma acc can get us immediately to the end, make sure we don't // introspect on the spelling before then. - if (FirstTok.isAnnotation()) { + if (FirstTok.isNot(tok::identifier)) { P.Diag(FirstTok, diag::err_acc_missing_directive); return OpenACCDirectiveKind::Invalid; } P.ConsumeToken(); - std::string FirstTokSpelling = P.getPreprocessor().getSpelling(FirstTok); - OpenACCDirectiveKindEx ExDirKind = getOpenACCDirectiveKind(FirstTokSpelling); + OpenACCDirectiveKindEx ExDirKind = getOpenACCDirectiveKind(FirstTok); // OpenACCDirectiveKindEx is meant to be an extended list // over OpenACCDirectiveKind, so any value below Invalid is one of the @@ -187,14 +223,14 @@ OpenACCDirectiveKind ParseOpenACCDirectiveKind(Parser &P) { // immediately cast it and use it as that. if (ExDirKind >= OpenACCDirectiveKindEx::Invalid) { switch (ExDirKind) { - case OpenACCDirectiveKindEx::Invalid: + case OpenACCDirectiveKindEx::Invalid: { P.Diag(FirstTok, diag::err_acc_invalid_directive) - << 0 << FirstTokSpelling; + << 0 << FirstTok.getIdentifierInfo(); return OpenACCDirectiveKind::Invalid; + } case OpenACCDirectiveKindEx::Enter: case OpenACCDirectiveKindEx::Exit: - return ParseOpenACCEnterExitDataDirective(P, FirstTok, FirstTokSpelling, - ExDirKind); + return ParseOpenACCEnterExitDataDirective(P, FirstTok, ExDirKind); } } @@ -205,8 +241,7 @@ OpenACCDirectiveKind ParseOpenACCDirectiveKind(Parser &P) { // clause. Token SecondTok = P.getCurToken(); if (!SecondTok.isAnnotation() && - isOpenACCDirectiveKind(OpenACCDirectiveKind::Loop, - P.getPreprocessor().getSpelling(SecondTok))) { + isOpenACCDirectiveKind(OpenACCDirectiveKind::Loop, SecondTok)) { switch (DirKind) { default: // Nothing to do except in the below cases, as they should be diagnosed as @@ -237,10 +272,68 @@ void ParseOpenACCClauseList(Parser &P) { } // namespace -// Routine has an optional paren-wrapped name of a function in the local scope. -// We parse the name, emitting any diagnostics -ExprResult Parser::ParseOpenACCRoutineName() { +/// OpenACC 3.3, section 2.16: +/// In this section and throughout the specification, the term wait-argument +/// means: +/// [ devnum : int-expr : ] [ queues : ] async-argument-list +bool Parser::ParseOpenACCWaitArgument() { + // [devnum : int-expr : ] + if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::DevNum, Tok) && + NextToken().is(tok::colon)) { + // Consume devnum. + ConsumeToken(); + // Consume colon. + ConsumeToken(); + + ExprResult IntExpr = + getActions().CorrectDelayedTyposInExpr(ParseAssignmentExpression()); + if (IntExpr.isInvalid()) + return true; + + if (ExpectAndConsume(tok::colon)) + return true; + } + + // [ queues : ] + if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::Queues, Tok) && + NextToken().is(tok::colon)) { + // Consume queues. + ConsumeToken(); + // Consume colon. + ConsumeToken(); + } + + // OpenACC 3.3, section 2.16: + // the term 'async-argument' means a nonnegative scalar integer expression, or + // one of the special values 'acc_async_noval' or 'acc_async_sync', as defined + // in the C header file and the Fortran opacc module. + // + // We are parsing this simply as list of assignment expressions (to avoid + // comma being troublesome), and will ensure it is an integral type. The + // 'special' types are defined as macros, so we can't really check those + // (other than perhaps as values at one point?), but the standard does say it + // is implementation-defined to use any other negative value. + // + // + bool FirstArg = true; + while (!getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) { + if (!FirstArg) { + if (ExpectAndConsume(tok::comma)) + return true; + } + FirstArg = false; + + ExprResult CurArg = + getActions().CorrectDelayedTyposInExpr(ParseAssignmentExpression()); + if (CurArg.isInvalid()) + return true; + } + + return false; +} + +ExprResult Parser::ParseOpenACCIDExpression() { ExprResult Res; if (getLangOpts().CPlusPlus) { Res = ParseCXXIdExpression(/*isAddressOfOperand=*/false); @@ -248,8 +341,10 @@ ExprResult Parser::ParseOpenACCRoutineName() { // There isn't anything quite the same as ParseCXXIdExpression for C, so we // need to get the identifier, then call into Sema ourselves. - if (expectIdentifier()) + if (Tok.isNot(tok::identifier)) { + Diag(Tok, diag::err_expected) << tok::identifier; return ExprError(); + } Token FuncName = getCurToken(); UnqualifiedId Name; @@ -268,6 +363,85 @@ ExprResult Parser::ParseOpenACCRoutineName() { return getActions().CorrectDelayedTyposInExpr(Res); } +/// OpenACC 3.3, section 2.10: +/// A 'var' in a cache directive must be a single array element or a simple +/// subarray. In C and C++, a simple subarray is an array name followed by an +/// extended array range specification in brackets, with a start and length such +/// as: +/// +/// arr[lower:length] +/// +bool Parser::ParseOpenACCCacheVar() { + ExprResult ArrayName = ParseOpenACCIDExpression(); + if (ArrayName.isInvalid()) + return true; + + // If the expression is invalid, just continue parsing the brackets, there + // is likely other useful diagnostics we can emit inside of those. + + BalancedDelimiterTracker SquareBrackets(*this, tok::l_square, + tok::annot_pragma_openacc_end); + + // Square brackets are required, so error here, and try to recover by moving + // until the next comma, or the close paren/end of pragma. + if (SquareBrackets.expectAndConsume()) { + SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openacc_end, + Parser::StopBeforeMatch); + return true; + } + + ExprResult Lower = getActions().CorrectDelayedTyposInExpr(ParseExpression()); + if (Lower.isInvalid()) + return true; + + // The 'length' expression is optional, as this could be a single array + // element. If there is no colon, we can treat it as that. + if (getCurToken().is(tok::colon)) { + ConsumeToken(); + ExprResult Length = + getActions().CorrectDelayedTyposInExpr(ParseExpression()); + if (Length.isInvalid()) + return true; + } + + // Diagnose the square bracket being in the wrong place and continue. + return SquareBrackets.consumeClose(); +} + +/// OpenACC 3.3, section 2.10: +/// In C and C++, the syntax of the cache directive is: +/// +/// #pragma acc cache ([readonly:]var-list) new-line +void Parser::ParseOpenACCCacheVarList() { + // If this is the end of the line, just return 'false' and count on the close + // paren diagnostic to catch the issue. + if (getCurToken().isAnnotation()) + return; + + // The VarList is an optional `readonly:` followed by a list of a variable + // specifications. First, see if we have `readonly:`, else we back-out and + // treat it like the beginning of a reference to a potentially-existing + // `readonly` variable. + if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::ReadOnly, Tok) && + NextToken().is(tok::colon)) { + // Consume both tokens. + ConsumeToken(); + ConsumeToken(); + // FIXME: Record that this is a 'readonly' so that we can use that during + // Sema/AST generation. + } + + bool FirstArray = true; + while (!getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) { + if (!FirstArray) + ExpectAndConsume(tok::comma); + FirstArray = false; + if (ParseOpenACCCacheVar()) + SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end, tok::comma, + StopBeforeMatch); + } +} + void Parser::ParseOpenACCDirective() { OpenACCDirectiveKind DirKind = ParseOpenACCDirectiveKind(*this); @@ -289,7 +463,9 @@ void Parser::ParseOpenACCDirective() { T.skipToEnd(); break; case OpenACCDirectiveKind::Routine: { - ExprResult RoutineName = ParseOpenACCRoutineName(); + // Routine has an optional paren-wrapped name of a function in the local + // scope. We parse the name, emitting any diagnostics + ExprResult RoutineName = ParseOpenACCIDExpression(); // If the routine name is invalid, just skip until the closing paren to // recover more gracefully. if (RoutineName.isInvalid()) @@ -298,7 +474,25 @@ void Parser::ParseOpenACCDirective() { T.consumeClose(); break; } + case OpenACCDirectiveKind::Cache: + ParseOpenACCCacheVarList(); + // The ParseOpenACCCacheVarList function manages to recover from failures, + // so we can always consume the close. + T.consumeClose(); + break; + case OpenACCDirectiveKind::Wait: + // OpenACC has an optional paren-wrapped 'wait-argument'. + if (ParseOpenACCWaitArgument()) + T.skipToEnd(); + else + T.consumeClose(); + break; } + } else if (DirKind == OpenACCDirectiveKind::Cache) { + // Cache's paren var-list is required, so error here if it isn't provided. + // We know that the consumeOpen above left the first non-paren here, so + // diagnose, then continue as if it was completely omitted. + Diag(Tok, diag::err_expected) << tok::l_paren; } // Parses the list of clauses, if present. diff --git a/clang/lib/Parse/ParsePragma.cpp b/clang/lib/Parse/ParsePragma.cpp index efdf7c90f977fbff32c7edae42e87dd04e3ef225..730ac1a0fee5cc9f151759cac31706869983760c 100644 --- a/clang/lib/Parse/ParsePragma.cpp +++ b/clang/lib/Parse/ParsePragma.cpp @@ -137,7 +137,20 @@ struct PragmaSTDC_CX_LIMITED_RANGEHandler : public PragmaHandler { void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, Token &Tok) override { tok::OnOffSwitch OOS; - PP.LexOnOffSwitch(OOS); + if (PP.LexOnOffSwitch(OOS)) + return; + + MutableArrayRef Toks( + PP.getPreprocessorAllocator().Allocate(1), 1); + + Toks[0].startToken(); + Toks[0].setKind(tok::annot_pragma_cx_limited_range); + Toks[0].setLocation(Tok.getLocation()); + Toks[0].setAnnotationEndLoc(Tok.getLocation()); + Toks[0].setAnnotationValue( + reinterpret_cast(static_cast(OOS))); + PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true, + /*IsReinject=*/false); } }; @@ -888,6 +901,31 @@ void Parser::HandlePragmaFEnvRound() { Actions.ActOnPragmaFEnvRound(PragmaLoc, RM); } +void Parser::HandlePragmaCXLimitedRange() { + assert(Tok.is(tok::annot_pragma_cx_limited_range)); + tok::OnOffSwitch OOS = static_cast( + reinterpret_cast(Tok.getAnnotationValue())); + + LangOptions::ComplexRangeKind Range; + switch (OOS) { + case tok::OOS_ON: + Range = LangOptions::CX_Limited; + break; + case tok::OOS_OFF: + Range = LangOptions::CX_Full; + break; + case tok::OOS_DEFAULT: + // According to ISO C99 standard chapter 7.3.4, the default value + // for the pragma is ``off'. -fcx-limited-range and -fcx-fortran-rules + // control the default value of these pragmas. + Range = getLangOpts().getComplexRange(); + break; + } + + SourceLocation PragmaLoc = ConsumeAnnotationToken(); + Actions.ActOnPragmaCXLimitedRange(PragmaLoc, Range); +} + StmtResult Parser::HandlePragmaCaptured() { assert(Tok.is(tok::annot_pragma_captured)); diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp index 918afdc2baea389e3d7972c6baa40f160d4168a3..d0ff33bd1379ab727bdf712ad2ebee58f64f9149 100644 --- a/clang/lib/Parse/ParseStmt.cpp +++ b/clang/lib/Parse/ParseStmt.cpp @@ -444,6 +444,14 @@ Retry: ConsumeAnnotationToken(); return StmtError(); + case tok::annot_pragma_cx_limited_range: + ProhibitAttributes(CXX11Attrs); + ProhibitAttributes(GNUAttrs); + Diag(Tok, diag::err_pragma_file_or_compound_scope) + << "STDC CX_LIMITED_RANGE"; + ConsumeAnnotationToken(); + return StmtError(); + case tok::annot_pragma_float_control: ProhibitAttributes(CXX11Attrs); ProhibitAttributes(GNUAttrs); @@ -1066,6 +1074,9 @@ void Parser::ParseCompoundStatementLeadingPragmas() { case tok::annot_pragma_fenv_round: HandlePragmaFEnvRound(); break; + case tok::annot_pragma_cx_limited_range: + HandlePragmaCXLimitedRange(); + break; case tok::annot_pragma_float_control: HandlePragmaFloatControl(); break; diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index 1baeb2aeb021faa89826ef88616568c40ac11678..ec67faf7dcaf863985a2b595e517d3007ff3fa68 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/lib/Parse/Parser.cpp @@ -844,6 +844,9 @@ Parser::ParseExternalDeclaration(ParsedAttributes &Attrs, case tok::annot_pragma_fenv_round: HandlePragmaFEnvRound(); return nullptr; + case tok::annot_pragma_cx_limited_range: + HandlePragmaCXLimitedRange(); + return nullptr; case tok::annot_pragma_float_control: HandlePragmaFloatControl(); return nullptr; diff --git a/clang/lib/Rewrite/Rewriter.cpp b/clang/lib/Rewrite/Rewriter.cpp index ef2858990dd954e222b1473a557d513fdc05a475..0896221dd0bdeb5672b89ea2d450f6faa78b8d3c 100644 --- a/clang/lib/Rewrite/Rewriter.cpp +++ b/clang/lib/Rewrite/Rewriter.cpp @@ -412,12 +412,13 @@ bool Rewriter::overwriteChangedFiles() { unsigned OverwriteFailure = Diag.getCustomDiagID( DiagnosticsEngine::Error, "unable to overwrite file %0: %1"); for (buffer_iterator I = buffer_begin(), E = buffer_end(); I != E; ++I) { - const FileEntry *Entry = getSourceMgr().getFileEntryForID(I->first); - if (auto Error = - llvm::writeToOutput(Entry->getName(), [&](llvm::raw_ostream &OS) { - I->second.write(OS); - return llvm::Error::success(); - })) { + OptionalFileEntryRef Entry = getSourceMgr().getFileEntryRefForID(I->first); + llvm::SmallString<128> Path(Entry->getName()); + getSourceMgr().getFileManager().makeAbsolutePath(Path); + if (auto Error = llvm::writeToOutput(Path, [&](llvm::raw_ostream &OS) { + I->second.write(OS); + return llvm::Error::success(); + })) { Diag.Report(OverwriteFailure) << Entry->getName() << llvm::toString(std::move(Error)); AllWritten = false; diff --git a/clang/lib/Sema/HLSLExternalSemaSource.cpp b/clang/lib/Sema/HLSLExternalSemaSource.cpp index 8de144486c91df6297c0ecee79bb9af0a66339e1..1a1febf7a3524118d9179d14575e3c870a5a20c3 100644 --- a/clang/lib/Sema/HLSLExternalSemaSource.cpp +++ b/clang/lib/Sema/HLSLExternalSemaSource.cpp @@ -116,11 +116,11 @@ struct BuiltinTypeDeclBuilder { } BuiltinTypeDeclBuilder &annotateResourceClass(ResourceClass RC, - ResourceKind RK) { + ResourceKind RK, bool IsROV) { if (Record->isCompleteDefinition()) return *this; - Record->addAttr( - HLSLResourceAttr::CreateImplicit(Record->getASTContext(), RC, RK)); + Record->addAttr(HLSLResourceAttr::CreateImplicit(Record->getASTContext(), + RC, RK, IsROV)); return *this; } @@ -306,6 +306,7 @@ struct BuiltinTypeDeclBuilder { } TemplateParameterListBuilder addTemplateArgumentList(); + BuiltinTypeDeclBuilder &addSimpleTemplateParams(ArrayRef Names); }; struct TemplateParameterListBuilder { @@ -360,11 +361,19 @@ struct TemplateParameterListBuilder { return Builder; } }; +} // namespace TemplateParameterListBuilder BuiltinTypeDeclBuilder::addTemplateArgumentList() { return TemplateParameterListBuilder(*this); } -} // namespace + +BuiltinTypeDeclBuilder & +BuiltinTypeDeclBuilder::addSimpleTemplateParams(ArrayRef Names) { + TemplateParameterListBuilder Builder = this->addTemplateArgumentList(); + for (StringRef Name : Names) + Builder.addTypeParameter(Name); + return Builder.finalizeTemplateArgs(); +} HLSLExternalSemaSource::~HLSLExternalSemaSource() {} @@ -390,7 +399,7 @@ void HLSLExternalSemaSource::InitializeSema(Sema &S) { // Force external decls in the HLSL namespace to load from the PCH. (void)HLSLNamespace->getCanonicalDecl()->decls_begin(); defineTrivialHLSLTypes(); - forwardDeclareHLSLTypes(); + defineHLSLTypesWithForwardDeclarations(); // This adds a `using namespace hlsl` directive. In DXC, we don't put HLSL's // built in types inside a namespace, but we are planning to change that in @@ -467,18 +476,43 @@ void HLSLExternalSemaSource::defineTrivialHLSLTypes() { .Record; } -void HLSLExternalSemaSource::forwardDeclareHLSLTypes() { +/// Set up common members and attributes for buffer types +static BuiltinTypeDeclBuilder setupBufferType(CXXRecordDecl *Decl, Sema &S, + ResourceClass RC, ResourceKind RK, + bool IsROV) { + return BuiltinTypeDeclBuilder(Decl) + .addHandleMember() + .addDefaultHandleConstructor(S, RC) + .annotateResourceClass(RC, RK, IsROV); +} + +void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() { CXXRecordDecl *Decl; Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "RWBuffer") - .addTemplateArgumentList() - .addTypeParameter("element_type", SemaPtr->getASTContext().FloatTy) - .finalizeTemplateArgs() + .addSimpleTemplateParams({"element_type"}) .Record; - if (!Decl->isCompleteDefinition()) - Completions.insert( - std::make_pair(Decl->getCanonicalDecl(), - std::bind(&HLSLExternalSemaSource::completeBufferType, - this, std::placeholders::_1))); + onCompletion(Decl, [this](CXXRecordDecl *Decl) { + setupBufferType(Decl, *SemaPtr, ResourceClass::UAV, + ResourceKind::TypedBuffer, /*IsROV=*/false) + .addArraySubscriptOperators() + .completeDefinition(); + }); + + Decl = + BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "RasterizerOrderedBuffer") + .addSimpleTemplateParams({"element_type"}) + .Record; + onCompletion(Decl, [this](CXXRecordDecl *Decl) { + setupBufferType(Decl, *SemaPtr, ResourceClass::UAV, + ResourceKind::TypedBuffer, /*IsROV=*/true) + .addArraySubscriptOperators() + .completeDefinition(); + }); +} + +void HLSLExternalSemaSource::onCompletion(CXXRecordDecl *Record, + CompletionFunction Fn) { + Completions.insert(std::make_pair(Record->getCanonicalDecl(), Fn)); } void HLSLExternalSemaSource::CompleteType(TagDecl *Tag) { @@ -496,12 +530,3 @@ void HLSLExternalSemaSource::CompleteType(TagDecl *Tag) { return; It->second(Record); } - -void HLSLExternalSemaSource::completeBufferType(CXXRecordDecl *Record) { - BuiltinTypeDeclBuilder(Record) - .addHandleMember() - .addDefaultHandleConstructor(*SemaPtr, ResourceClass::UAV) - .addArraySubscriptOperators() - .annotateResourceClass(ResourceClass::UAV, ResourceKind::TypedBuffer) - .completeDefinition(); -} diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index 9771aaa2f3b0371530354c878488982a414e9523..cafbecebc8a119a60589e8c357b7fd206f5a52fb 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -870,6 +870,7 @@ static void checkUndefinedButUsed(Sema &S) { // Collect all the still-undefined entities with internal linkage. SmallVector, 16> Undefined; S.getUndefinedButUsed(Undefined); + S.UndefinedButUsed.clear(); if (Undefined.empty()) return; for (const auto &Undef : Undefined) { @@ -923,8 +924,6 @@ static void checkUndefinedButUsed(Sema &S) { if (UseLoc.isValid()) S.Diag(UseLoc, diag::note_used_here); } - - S.UndefinedButUsed.clear(); } void Sema::LoadExternalWeakUndeclaredIdentifiers() { @@ -2077,15 +2076,15 @@ void Sema::checkTypeSupport(QualType Ty, SourceLocation Loc, ValueDecl *D) { targetDiag(D->getLocation(), diag::note_defined_here, FD) << D; } - if (TI.hasRISCVVTypes() && Ty->isRVVType()) + if (TI.hasRISCVVTypes() && Ty->isRVVSizelessBuiltinType()) checkRVVTypeSupport(Ty, Loc, D); // Don't allow SVE types in functions without a SVE target. if (Ty->isSVESizelessBuiltinType() && FD && FD->hasBody()) { llvm::StringMap CallerFeatureMap; Context.getFunctionFeatureMap(CallerFeatureMap, FD); - if (!Builtin::evaluateRequiredTargetFeatures( - "sve", CallerFeatureMap)) + if (!Builtin::evaluateRequiredTargetFeatures("sve", CallerFeatureMap) && + !Builtin::evaluateRequiredTargetFeatures("sme", CallerFeatureMap)) Diag(D->getLocation(), diag::err_sve_vector_in_non_sve_target) << Ty; } }; diff --git a/clang/lib/Sema/SemaAttr.cpp b/clang/lib/Sema/SemaAttr.cpp index 79271c872627310ec92d1cda432f45897c07cb4b..0dcf42e489971344d516153c872a36c1df03e188 100644 --- a/clang/lib/Sema/SemaAttr.cpp +++ b/clang/lib/Sema/SemaAttr.cpp @@ -1352,6 +1352,14 @@ void Sema::ActOnPragmaFEnvAccess(SourceLocation Loc, bool IsEnabled) { CurFPFeatures = NewFPFeatures.applyOverrides(getLangOpts()); } +void Sema::ActOnPragmaCXLimitedRange(SourceLocation Loc, + LangOptions::ComplexRangeKind Range) { + FPOptionsOverride NewFPFeatures = CurFPFeatureOverrides(); + NewFPFeatures.setComplexRangeOverride(Range); + FpPragmaStack.Act(Loc, PSK_Set, StringRef(), NewFPFeatures); + CurFPFeatures = NewFPFeatures.applyOverrides(getLangOpts()); +} + void Sema::ActOnPragmaFPExceptions(SourceLocation Loc, LangOptions::FPExceptionModeKind FPE) { setExceptionMode(Loc, FPE); diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 77c8334f3ca25d305ca5fd772b2b033749abe276..cdb6e9584e9554104e3b4921f15d4752440661fe 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -712,8 +712,13 @@ static ExprResult SemaBuiltinDumpStruct(Sema &S, CallExpr *TheCall) { << 1 << TheCall->getDirectCallee() << PtrArgType; return ExprError(); } - const RecordDecl *RD = PtrArgType->getPointeeType()->getAsRecordDecl(); - + QualType Pointee = PtrArgType->getPointeeType(); + const RecordDecl *RD = Pointee->getAsRecordDecl(); + // Try to instantiate the class template as appropriate; otherwise, access to + // its data() may lead to a crash. + if (S.RequireCompleteType(PtrArgResult.get()->getBeginLoc(), Pointee, + diag::err_incomplete_type)) + return ExprError(); // Second argument is a callable, but we can't fully validate it until we try // calling it. QualType FnArgType = TheCall->getArg(1)->getType(); @@ -2995,58 +3000,15 @@ static QualType getNeonEltType(NeonTypeFlags Flags, ASTContext &Context, enum ArmStreamingType { ArmNonStreaming, ArmStreaming, ArmStreamingCompatible }; -static ArmStreamingType getArmStreamingFnType(const FunctionDecl *FD) { - if (FD->hasAttr()) - return ArmStreaming; - if (const auto *T = FD->getType()->getAs()) { - if (T->getAArch64SMEAttributes() & FunctionType::SME_PStateSMEnabledMask) - return ArmStreaming; - if (T->getAArch64SMEAttributes() & FunctionType::SME_PStateSMCompatibleMask) - return ArmStreamingCompatible; - } - return ArmNonStreaming; -} - -static void checkArmStreamingBuiltin(Sema &S, CallExpr *TheCall, - const FunctionDecl *FD, - ArmStreamingType BuiltinType) { - ArmStreamingType FnType = getArmStreamingFnType(FD); - - if (FnType == ArmStreaming && BuiltinType == ArmNonStreaming) { - S.Diag(TheCall->getBeginLoc(), diag::warn_attribute_arm_sm_incompat_builtin) - << TheCall->getSourceRange() << "streaming"; - } - - if (FnType == ArmStreamingCompatible && - BuiltinType != ArmStreamingCompatible) { - S.Diag(TheCall->getBeginLoc(), diag::warn_attribute_arm_sm_incompat_builtin) - << TheCall->getSourceRange() << "streaming compatible"; - return; - } -} - -bool Sema::CheckSVEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { - // Range check SVE intrinsics that take immediate values. - SmallVector, 3> ImmChecks; - - switch (BuiltinID) { - default: - return false; -#define GET_SVE_IMMEDIATE_CHECK -#include "clang/Basic/arm_sve_sema_rangechecks.inc" -#undef GET_SVE_IMMEDIATE_CHECK -#define GET_SME_IMMEDIATE_CHECK -#include "clang/Basic/arm_sme_sema_rangechecks.inc" -#undef GET_SME_IMMEDIATE_CHECK - } - +bool Sema::ParseSVEImmChecks( + CallExpr *TheCall, SmallVector, 3> &ImmChecks) { // Perform all the immediate checks for this builtin call. bool HasError = false; for (auto &I : ImmChecks) { int ArgNum, CheckTy, ElementSizeInBits; std::tie(ArgNum, CheckTy, ElementSizeInBits) = I; - typedef bool(*OptionSetCheckFnTy)(int64_t Value); + typedef bool (*OptionSetCheckFnTy)(int64_t Value); // Function that checks whether the operand (ArgNum) is an immediate // that is one of the predefined values. @@ -3178,6 +3140,54 @@ bool Sema::CheckSVEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { return HasError; } +static ArmStreamingType getArmStreamingFnType(const FunctionDecl *FD) { + if (FD->hasAttr()) + return ArmStreaming; + if (const auto *T = FD->getType()->getAs()) { + if (T->getAArch64SMEAttributes() & FunctionType::SME_PStateSMEnabledMask) + return ArmStreaming; + if (T->getAArch64SMEAttributes() & FunctionType::SME_PStateSMCompatibleMask) + return ArmStreamingCompatible; + } + return ArmNonStreaming; +} + +static void checkArmStreamingBuiltin(Sema &S, CallExpr *TheCall, + const FunctionDecl *FD, + ArmStreamingType BuiltinType) { + ArmStreamingType FnType = getArmStreamingFnType(FD); + + if (FnType == ArmStreaming && BuiltinType == ArmNonStreaming) { + S.Diag(TheCall->getBeginLoc(), diag::warn_attribute_arm_sm_incompat_builtin) + << TheCall->getSourceRange() << "streaming"; + } + + if (FnType == ArmStreamingCompatible && + BuiltinType != ArmStreamingCompatible) { + S.Diag(TheCall->getBeginLoc(), diag::warn_attribute_arm_sm_incompat_builtin) + << TheCall->getSourceRange() << "streaming compatible"; + return; + } +} + +bool Sema::CheckSVEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { + // Range check SVE intrinsics that take immediate values. + SmallVector, 3> ImmChecks; + + switch (BuiltinID) { + default: + return false; +#define GET_SVE_IMMEDIATE_CHECK +#include "clang/Basic/arm_sve_sema_rangechecks.inc" +#undef GET_SVE_IMMEDIATE_CHECK +#define GET_SME_IMMEDIATE_CHECK +#include "clang/Basic/arm_sme_sema_rangechecks.inc" +#undef GET_SME_IMMEDIATE_CHECK + } + + return ParseSVEImmChecks(TheCall, ImmChecks); +} + bool Sema::CheckNeonBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall) { if (const FunctionDecl *FD = getCurFunctionDecl()) { @@ -5072,12 +5082,10 @@ static bool CheckInvalidVLENandLMUL(const TargetInfo &TI, CallExpr *TheCall, assert((EGW == 128 || EGW == 256) && "EGW can only be 128 or 256 bits"); // LMUL * VLEN >= EGW - unsigned ElemSize = Type->isRVVType(32, false) ? 32 : 64; - unsigned MinElemCount = Type->isRVVType(1) ? 1 - : Type->isRVVType(2) ? 2 - : Type->isRVVType(4) ? 4 - : Type->isRVVType(8) ? 8 - : 16; + ASTContext::BuiltinVectorTypeInfo Info = + S.Context.getBuiltinVectorTypeInfo(Type->castAs()); + unsigned ElemSize = S.Context.getTypeSize(Info.ElementType); + unsigned MinElemCount = Info.EC.getKnownMinValue(); unsigned EGS = EGW / ElemSize; // If EGS is less than or equal to the minimum number of elements, then the @@ -5205,15 +5213,13 @@ bool Sema::CheckRISCVBuiltinFunctionCall(const TargetInfo &TI, case RISCVVector::BI__builtin_rvv_vsmul_vx_tum: case RISCVVector::BI__builtin_rvv_vsmul_vv_tumu: case RISCVVector::BI__builtin_rvv_vsmul_vx_tumu: { - bool RequireV = false; - for (unsigned ArgNum = 0; ArgNum < TheCall->getNumArgs(); ++ArgNum) - RequireV |= TheCall->getArg(ArgNum)->getType()->isRVVType( - /* Bitwidth */ 64, /* IsFloat */ false); + ASTContext::BuiltinVectorTypeInfo Info = Context.getBuiltinVectorTypeInfo( + TheCall->getType()->castAs()); - if (RequireV && !TI.hasFeature("v")) + if (Context.getTypeSize(Info.ElementType) == 64 && !TI.hasFeature("v")) return Diag(TheCall->getBeginLoc(), diag::err_riscv_builtin_requires_extension) - << /* IsExtension */ false << TheCall->getSourceRange() << "v"; + << /* IsExtension */ true << TheCall->getSourceRange() << "v"; break; } @@ -5973,7 +5979,7 @@ bool Sema::CheckRISCVBuiltinFunctionCall(const TargetInfo &TI, ValType = ValType.getUnqualifiedType(); if (!ValType->isIntegerType() && !ValType->isAnyPointerType() && !ValType->isBlockPointerType() && !ValType->isFloatingType() && - !ValType->isVectorType() && !ValType->isRVVType()) { + !ValType->isVectorType() && !ValType->isRVVSizelessBuiltinType()) { Diag(DRE->getBeginLoc(), diag::err_nontemporal_builtin_must_be_pointer_intfltptr_or_vector) << PointerArg->getType() << PointerArg->getSourceRange(); @@ -7643,6 +7649,8 @@ static bool isValidOrderingForOp(int64_t Ordering, AtomicExpr::AtomicOp Op) { case AtomicExpr::AO__hip_atomic_load: case AtomicExpr::AO__atomic_load_n: case AtomicExpr::AO__atomic_load: + case AtomicExpr::AO__scoped_atomic_load_n: + case AtomicExpr::AO__scoped_atomic_load: return OrderingCABI != llvm::AtomicOrderingCABI::release && OrderingCABI != llvm::AtomicOrderingCABI::acq_rel; @@ -7651,6 +7659,8 @@ static bool isValidOrderingForOp(int64_t Ordering, AtomicExpr::AtomicOp Op) { case AtomicExpr::AO__hip_atomic_store: case AtomicExpr::AO__atomic_store: case AtomicExpr::AO__atomic_store_n: + case AtomicExpr::AO__scoped_atomic_store: + case AtomicExpr::AO__scoped_atomic_store_n: return OrderingCABI != llvm::AtomicOrderingCABI::consume && OrderingCABI != llvm::AtomicOrderingCABI::acquire && OrderingCABI != llvm::AtomicOrderingCABI::acq_rel; @@ -7727,13 +7737,19 @@ ExprResult Sema::BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange, Op <= AtomicExpr::AO__opencl_atomic_fetch_max; bool IsHIP = Op >= AtomicExpr::AO__hip_atomic_load && Op <= AtomicExpr::AO__hip_atomic_fetch_max; + bool IsScoped = Op >= AtomicExpr::AO__scoped_atomic_load && + Op <= AtomicExpr::AO__scoped_atomic_fetch_max; bool IsC11 = (Op >= AtomicExpr::AO__c11_atomic_init && Op <= AtomicExpr::AO__c11_atomic_fetch_min) || IsOpenCL; bool IsN = Op == AtomicExpr::AO__atomic_load_n || Op == AtomicExpr::AO__atomic_store_n || Op == AtomicExpr::AO__atomic_exchange_n || - Op == AtomicExpr::AO__atomic_compare_exchange_n; + Op == AtomicExpr::AO__atomic_compare_exchange_n || + Op == AtomicExpr::AO__scoped_atomic_load_n || + Op == AtomicExpr::AO__scoped_atomic_store_n || + Op == AtomicExpr::AO__scoped_atomic_exchange_n || + Op == AtomicExpr::AO__scoped_atomic_compare_exchange_n; // Bit mask for extra allowed value types other than integers for atomic // arithmetic operations. Add/sub allow pointer and floating point. Min/max // allow floating point. @@ -7754,10 +7770,12 @@ ExprResult Sema::BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange, case AtomicExpr::AO__opencl_atomic_load: case AtomicExpr::AO__hip_atomic_load: case AtomicExpr::AO__atomic_load_n: + case AtomicExpr::AO__scoped_atomic_load_n: Form = Load; break; case AtomicExpr::AO__atomic_load: + case AtomicExpr::AO__scoped_atomic_load: Form = LoadCopy; break; @@ -7766,12 +7784,18 @@ ExprResult Sema::BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange, case AtomicExpr::AO__hip_atomic_store: case AtomicExpr::AO__atomic_store: case AtomicExpr::AO__atomic_store_n: + case AtomicExpr::AO__scoped_atomic_store: + case AtomicExpr::AO__scoped_atomic_store_n: Form = Copy; break; case AtomicExpr::AO__atomic_fetch_add: case AtomicExpr::AO__atomic_fetch_sub: case AtomicExpr::AO__atomic_add_fetch: case AtomicExpr::AO__atomic_sub_fetch: + case AtomicExpr::AO__scoped_atomic_fetch_add: + case AtomicExpr::AO__scoped_atomic_fetch_sub: + case AtomicExpr::AO__scoped_atomic_add_fetch: + case AtomicExpr::AO__scoped_atomic_sub_fetch: case AtomicExpr::AO__c11_atomic_fetch_add: case AtomicExpr::AO__c11_atomic_fetch_sub: case AtomicExpr::AO__opencl_atomic_fetch_add: @@ -7785,6 +7809,10 @@ ExprResult Sema::BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange, case AtomicExpr::AO__atomic_fetch_min: case AtomicExpr::AO__atomic_max_fetch: case AtomicExpr::AO__atomic_min_fetch: + case AtomicExpr::AO__scoped_atomic_fetch_max: + case AtomicExpr::AO__scoped_atomic_fetch_min: + case AtomicExpr::AO__scoped_atomic_max_fetch: + case AtomicExpr::AO__scoped_atomic_min_fetch: case AtomicExpr::AO__c11_atomic_fetch_max: case AtomicExpr::AO__c11_atomic_fetch_min: case AtomicExpr::AO__opencl_atomic_fetch_max: @@ -7812,6 +7840,14 @@ ExprResult Sema::BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange, case AtomicExpr::AO__atomic_or_fetch: case AtomicExpr::AO__atomic_xor_fetch: case AtomicExpr::AO__atomic_nand_fetch: + case AtomicExpr::AO__scoped_atomic_fetch_and: + case AtomicExpr::AO__scoped_atomic_fetch_or: + case AtomicExpr::AO__scoped_atomic_fetch_xor: + case AtomicExpr::AO__scoped_atomic_fetch_nand: + case AtomicExpr::AO__scoped_atomic_and_fetch: + case AtomicExpr::AO__scoped_atomic_or_fetch: + case AtomicExpr::AO__scoped_atomic_xor_fetch: + case AtomicExpr::AO__scoped_atomic_nand_fetch: Form = Arithmetic; break; @@ -7819,10 +7855,12 @@ ExprResult Sema::BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange, case AtomicExpr::AO__hip_atomic_exchange: case AtomicExpr::AO__opencl_atomic_exchange: case AtomicExpr::AO__atomic_exchange_n: + case AtomicExpr::AO__scoped_atomic_exchange_n: Form = Xchg; break; case AtomicExpr::AO__atomic_exchange: + case AtomicExpr::AO__scoped_atomic_exchange: Form = GNUXchg; break; @@ -7837,12 +7875,15 @@ ExprResult Sema::BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange, case AtomicExpr::AO__atomic_compare_exchange: case AtomicExpr::AO__atomic_compare_exchange_n: + case AtomicExpr::AO__scoped_atomic_compare_exchange: + case AtomicExpr::AO__scoped_atomic_compare_exchange_n: Form = GNUCmpXchg; break; } unsigned AdjustedNumArgs = NumArgs[Form]; - if ((IsOpenCL || IsHIP) && Op != AtomicExpr::AO__opencl_atomic_init) + if ((IsOpenCL || IsHIP || IsScoped) && + Op != AtomicExpr::AO__opencl_atomic_init) ++AdjustedNumArgs; // Check we have the right number of arguments. if (Args.size() < AdjustedNumArgs) { diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp index 6169144ef1c2d4863a1294f9516f32695e1b9a22..143968b4ab0442fe017705f21dccbef066c164ab 100644 --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/lib/Sema/SemaCodeComplete.cpp @@ -10112,7 +10112,7 @@ void Sema::CodeCompleteIncludedFile(llvm::StringRef Dir, bool Angled) { const StringRef &Dirname = llvm::sys::path::filename(Dir); const bool isQt = Dirname.startswith("Qt") || Dirname == "ActiveQt"; const bool ExtensionlessHeaders = - IsSystem || isQt || Dir.endswith(".framework/Headers"); + IsSystem || isQt || Dir.ends_with(".framework/Headers"); std::error_code EC; unsigned Count = 0; for (auto It = FS.dir_begin(Dir, EC); diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index f12424d33b7da2d1c68880903fac404549127174..19d972ed8ab2d830ec9b099d3a820ff00561bc03 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -5971,7 +5971,7 @@ Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) { diag::err_deduction_guide_name_not_class_template) << (int)getTemplateNameKindForDiagnostics(TN) << TN; if (Template) - Diag(Template->getLocation(), diag::note_template_decl_here); + NoteTemplateLocation(*Template); return DeclarationNameInfo(); } @@ -8914,7 +8914,7 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) { } } - if (T->isRVVType()) + if (T->isRVVSizelessBuiltinType()) checkRVVTypeSupport(T, NewVD->getLocation(), cast(CurContext)); } @@ -16221,7 +16221,9 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, ActivePolicy = &WP; } - if (!IsInstantiation && FD && FD->isConstexpr() && !FD->isInvalidDecl() && + if (!IsInstantiation && FD && + (FD->isConstexpr() || FD->hasAttr()) && + !FD->isInvalidDecl() && !CheckConstexprFunctionDefinition(FD, CheckConstexprKind::Diagnose)) FD->setInvalidDecl(); diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 87c78d742d0ff4d36c1427d26d84becae186a8b2..59e456fd9f729837de00d86e5511db839d960c6d 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -7372,6 +7372,28 @@ static void handleDeclspecThreadAttr(Sema &S, Decl *D, const ParsedAttr &AL) { D->addAttr(::new (S.Context) ThreadAttr(S.Context, AL)); } +static void handleMSConstexprAttr(Sema &S, Decl *D, const ParsedAttr &AL) { + if (!S.getLangOpts().isCompatibleWithMSVC(LangOptions::MSVC2022_3)) { + S.Diag(AL.getLoc(), diag::warn_unknown_attribute_ignored) + << AL << AL.getRange(); + return; + } + auto *FD = cast(D); + if (FD->isConstexprSpecified() || FD->isConsteval()) { + S.Diag(AL.getLoc(), diag::err_ms_constexpr_cannot_be_applied) + << FD->isConsteval() << FD; + return; + } + if (auto *MD = dyn_cast(FD)) { + if (!S.getLangOpts().CPlusPlus20 && MD->isVirtual()) { + S.Diag(AL.getLoc(), diag::err_ms_constexpr_cannot_be_applied) + << /*virtual*/ 2 << MD; + return; + } + } + D->addAttr(::new (S.Context) MSConstexprAttr(S.Context, AL)); +} + static void handleAbiTagAttr(Sema &S, Decl *D, const ParsedAttr &AL) { SmallVector Tags; for (unsigned I = 0, E = AL.getNumArgs(); I != E; ++I) { @@ -9036,6 +9058,9 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL, case ParsedAttr::AT_BPFPreserveAccessIndex: handleBPFPreserveAccessIndexAttr(S, D, AL); break; + case ParsedAttr::AT_BPFPreserveStaticOffset: + handleSimpleAttribute(S, D, AL); + break; case ParsedAttr::AT_BTFDeclTag: handleBTFDeclTagAttr(S, D, AL); break; @@ -9474,6 +9499,9 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL, case ParsedAttr::AT_Thread: handleDeclspecThreadAttr(S, D, AL); break; + case ParsedAttr::AT_MSConstexpr: + handleMSConstexprAttr(S, D, AL); + break; // HLSL attributes: case ParsedAttr::AT_HLSLNumThreads: diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 8fedf41d8424ad9f925c4e9ea9a9d7cac78ff3ad..36e53c684ac4dc3b012764202dfcd4c3e914ea54 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -11462,7 +11462,7 @@ bool Sema::CheckDeductionGuideDeclarator(Declarator &D, QualType &R, GuidedTemplateDecl->getDeclContext()->getRedeclContext())) { Diag(D.getIdentifierLoc(), diag::err_deduction_guide_wrong_scope) << GuidedTemplateDecl; - Diag(GuidedTemplateDecl->getLocation(), diag::note_template_decl_here); + NoteTemplateLocation(*GuidedTemplateDecl); } auto &DS = D.getMutableDeclSpec(); @@ -17879,6 +17879,8 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, LookupResult Previous(*this, NameInfo, LookupOrdinaryName, ForExternalRedeclaration); + bool isTemplateId = D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId; + // There are five cases here. // - There's no scope specifier and we're in a local class. Only look // for functions declared in the immediately-enclosing block scope. @@ -17916,14 +17918,6 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, } adjustContextForLocalExternDecl(DC); - // C++ [class.friend]p6: - // A function can be defined in a friend declaration of a class if and - // only if the class is a non-local class (9.8), the function name is - // unqualified, and the function has namespace scope. - if (D.isFunctionDefinition()) { - Diag(NameInfo.getBeginLoc(), diag::err_friend_def_in_local_class); - } - // - There's no scope specifier, in which case we just go to the // appropriate scope and look for a function or function template // there as appropriate. @@ -17934,8 +17928,6 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, // elaborated-type-specifier, the lookup to determine whether // the entity has been previously declared shall not consider // any scopes outside the innermost enclosing namespace. - bool isTemplateId = - D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId; // Find the appropriate context according to the above. DC = CurContext; @@ -17988,39 +17980,12 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, diag::warn_cxx98_compat_friend_is_member : diag::err_friend_is_member); - if (D.isFunctionDefinition()) { - // C++ [class.friend]p6: - // A function can be defined in a friend declaration of a class if and - // only if the class is a non-local class (9.8), the function name is - // unqualified, and the function has namespace scope. - // - // FIXME: We should only do this if the scope specifier names the - // innermost enclosing namespace; otherwise the fixit changes the - // meaning of the code. - SemaDiagnosticBuilder DB - = Diag(SS.getRange().getBegin(), diag::err_qualified_friend_def); - - DB << SS.getScopeRep(); - if (DC->isFileContext()) - DB << FixItHint::CreateRemoval(SS.getRange()); - SS.clear(); - } - // - There's a scope specifier that does not match any template // parameter lists, in which case we use some arbitrary context, // create a method or method template, and wait for instantiation. // - There's a scope specifier that does match some template // parameter lists, which we don't handle right now. } else { - if (D.isFunctionDefinition()) { - // C++ [class.friend]p6: - // A function can be defined in a friend declaration of a class if and - // only if the class is a non-local class (9.8), the function name is - // unqualified, and the function has namespace scope. - Diag(SS.getRange().getBegin(), diag::err_qualified_friend_def) - << SS.getScopeRep(); - } - DC = CurContext; assert(isa(DC) && "friend declaration not in class?"); } @@ -18105,6 +18070,38 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, else FD = cast(ND); + // C++ [class.friend]p6: + // A function may be defined in a friend declaration of a class if and + // only if the class is a non-local class, and the function name is + // unqualified. + if (D.isFunctionDefinition()) { + // Qualified friend function definition. + if (SS.isNotEmpty()) { + // FIXME: We should only do this if the scope specifier names the + // innermost enclosing namespace; otherwise the fixit changes the + // meaning of the code. + SemaDiagnosticBuilder DB = + Diag(SS.getRange().getBegin(), diag::err_qualified_friend_def); + + DB << SS.getScopeRep(); + if (DC->isFileContext()) + DB << FixItHint::CreateRemoval(SS.getRange()); + + // Friend function defined in a local class. + } else if (FunctionContainingLocalClass) { + Diag(NameInfo.getBeginLoc(), diag::err_friend_def_in_local_class); + + // Per [basic.pre]p4, a template-id is not a name. Therefore, if we have + // a template-id, the function name is not unqualified because these is + // no name. While the wording requires some reading in-between the + // lines, GCC, MSVC, and EDG all consider a friend function + // specialization definitions // to be de facto explicit specialization + // and diagnose them as such. + } else if (isTemplateId) { + Diag(NameInfo.getBeginLoc(), diag::err_friend_specialization_def); + } + } + // C++11 [dcl.fct.default]p4: If a friend declaration specifies a // default argument expression, that declaration shall be a definition // and shall be the only declaration of the function or function diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 50ee0a5acb5586a8c13904831b00eaf70e3ecb3d..5ca6b232df66a560b97751c73f3c6ff87cb978d5 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -4085,16 +4085,13 @@ static bool hasCopyOrMoveCtorParam(ASTContext &Ctx, return Ctx.hasSameUnqualifiedType(ParmT, ClassT); } -static OverloadingResult -ResolveConstructorOverload(Sema &S, SourceLocation DeclLoc, - MultiExprArg Args, - OverloadCandidateSet &CandidateSet, - QualType DestType, - DeclContext::lookup_result Ctors, - OverloadCandidateSet::iterator &Best, - bool CopyInitializing, bool AllowExplicit, - bool OnlyListConstructors, bool IsListInit, - bool SecondStepOfCopyInit = false) { +static OverloadingResult ResolveConstructorOverload( + Sema &S, SourceLocation DeclLoc, MultiExprArg Args, + OverloadCandidateSet &CandidateSet, QualType DestType, + DeclContext::lookup_result Ctors, OverloadCandidateSet::iterator &Best, + bool CopyInitializing, bool AllowExplicit, bool OnlyListConstructors, + bool IsListInit, bool RequireActualConstructor, + bool SecondStepOfCopyInit = false) { CandidateSet.clear(OverloadCandidateSet::CSK_InitByConstructor); CandidateSet.setDestAS(DestType.getQualifiers().getAddressSpace()); @@ -4157,7 +4154,7 @@ ResolveConstructorOverload(Sema &S, SourceLocation DeclLoc, // Note: SecondStepOfCopyInit is only ever true in this case when // evaluating whether to produce a C++98 compatibility warning. if (S.getLangOpts().CPlusPlus17 && Args.size() == 1 && - !SecondStepOfCopyInit) { + !RequireActualConstructor && !SecondStepOfCopyInit) { Expr *Initializer = Args[0]; auto *SourceRD = Initializer->getType()->getAsCXXRecordDecl(); if (SourceRD && S.isCompleteType(DeclLoc, Initializer->getType())) { @@ -4225,6 +4222,12 @@ static void TryConstructorInitialization(Sema &S, return; } + bool RequireActualConstructor = + !(Entity.getKind() != InitializedEntity::EK_Base && + Entity.getKind() != InitializedEntity::EK_Delegating && + Entity.getKind() != + InitializedEntity::EK_LambdaToBlockConversionBlockElement); + // C++17 [dcl.init]p17: // - If the initializer expression is a prvalue and the cv-unqualified // version of the source type is the same class as the class of the @@ -4234,11 +4237,7 @@ static void TryConstructorInitialization(Sema &S, // class or delegating to another constructor from a mem-initializer. // ObjC++: Lambda captured by the block in the lambda to block conversion // should avoid copy elision. - if (S.getLangOpts().CPlusPlus17 && - Entity.getKind() != InitializedEntity::EK_Base && - Entity.getKind() != InitializedEntity::EK_Delegating && - Entity.getKind() != - InitializedEntity::EK_LambdaToBlockConversionBlockElement && + if (S.getLangOpts().CPlusPlus17 && !RequireActualConstructor && UnwrappedArgs.size() == 1 && UnwrappedArgs[0]->isPRValue() && S.Context.hasSameUnqualifiedType(UnwrappedArgs[0]->getType(), DestType)) { // Convert qualifications if necessary. @@ -4286,11 +4285,10 @@ static void TryConstructorInitialization(Sema &S, // If the initializer list has no elements and T has a default constructor, // the first phase is omitted. if (!(UnwrappedArgs.empty() && S.LookupDefaultConstructor(DestRecordDecl))) - Result = ResolveConstructorOverload(S, Kind.getLocation(), Args, - CandidateSet, DestType, Ctors, Best, - CopyInitialization, AllowExplicit, - /*OnlyListConstructors=*/true, - IsListInit); + Result = ResolveConstructorOverload( + S, Kind.getLocation(), Args, CandidateSet, DestType, Ctors, Best, + CopyInitialization, AllowExplicit, + /*OnlyListConstructors=*/true, IsListInit, RequireActualConstructor); } // C++11 [over.match.list]p1: @@ -4300,11 +4298,10 @@ static void TryConstructorInitialization(Sema &S, // elements of the initializer list. if (Result == OR_No_Viable_Function) { AsInitializerList = false; - Result = ResolveConstructorOverload(S, Kind.getLocation(), UnwrappedArgs, - CandidateSet, DestType, Ctors, Best, - CopyInitialization, AllowExplicit, - /*OnlyListConstructors=*/false, - IsListInit); + Result = ResolveConstructorOverload( + S, Kind.getLocation(), UnwrappedArgs, CandidateSet, DestType, Ctors, + Best, CopyInitialization, AllowExplicit, + /*OnlyListConstructors=*/false, IsListInit, RequireActualConstructor); } if (Result) { Sequence.SetOverloadFailure( @@ -6778,6 +6775,7 @@ static ExprResult CopyObject(Sema &S, S, Loc, CurInitExpr, CandidateSet, T, Ctors, Best, /*CopyInitializing=*/false, /*AllowExplicit=*/true, /*OnlyListConstructors=*/false, /*IsListInit=*/false, + /*RequireActualConstructor=*/false, /*SecondStepOfCopyInit=*/true)) { case OR_Success: break; @@ -6920,6 +6918,7 @@ static void CheckCXX98CompatAccessibleCopy(Sema &S, S, Loc, CurInitExpr, CandidateSet, CurInitExpr->getType(), Ctors, Best, /*CopyInitializing=*/false, /*AllowExplicit=*/true, /*OnlyListConstructors=*/false, /*IsListInit=*/false, + /*RequireActualConstructor=*/false, /*SecondStepOfCopyInit=*/true); PartialDiagnostic Diag = S.PDiag(diag::warn_cxx98_compat_temp_copy) @@ -10573,7 +10572,7 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer( diag::err_deduced_non_class_template_specialization_type) << (int)getTemplateNameKindForDiagnostics(TemplateName) << TemplateName; if (auto *TD = TemplateName.getAsTemplateDecl()) - Diag(TD->getLocation(), diag::note_template_decl_here); + NoteTemplateLocation(*TD); return QualType(); } diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp index ca09b0481bcac762fc4b8d43bf40468e30096c75..e7b6443c984c912f5bfaf5c7e51daf621d1fd9b5 100644 --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/lib/Sema/SemaLambda.cpp @@ -1444,7 +1444,7 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, for (const auto &Capture : Intro.Captures) { if (Capture.Id == TP->getIdentifier()) { Diag(Capture.Loc, diag::err_template_param_shadow) << Capture.Id; - Diag(TP->getLocation(), diag::note_template_param_here); + NoteTemplateParameterLocation(*TP); } } } @@ -1885,8 +1885,7 @@ ExprResult Sema::BuildCaptureInit(const Capture &Cap, return InitSeq.Perform(*this, Entity, InitKind, InitExpr); } -ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body, - Scope *CurScope) { +ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body) { LambdaScopeInfo LSI = *cast(FunctionScopes.back()); ActOnFinishFunctionBody(LSI.CallOperator, Body); return BuildLambdaExpr(StartLoc, Body->getEndLoc(), &LSI); diff --git a/clang/lib/Sema/SemaRISCVVectorLookup.cpp b/clang/lib/Sema/SemaRISCVVectorLookup.cpp index 9a5aecf669a07dfb2d57d193c24bde5071435333..0d411fca0f9c8275489fb476c1850714f49d5b44 100644 --- a/clang/lib/Sema/SemaRISCVVectorLookup.cpp +++ b/clang/lib/Sema/SemaRISCVVectorLookup.cpp @@ -34,12 +34,6 @@ namespace { // Function definition of a RVV intrinsic. struct RVVIntrinsicDef { - /// Full function name with suffix, e.g. vadd_vv_i32m1. - std::string Name; - - /// Overloaded function name, e.g. vadd. - std::string OverloadName; - /// Mapping to which clang built-in function, e.g. __builtin_rvv_vadd. std::string BuiltinName; @@ -393,7 +387,7 @@ void RISCVIntrinsicManagerImpl::InitRVVIntrinsic( // Put into IntrinsicList. size_t Index = IntrinsicList.size(); - IntrinsicList.push_back({Name, OverloadedName, BuiltinName, Signature}); + IntrinsicList.push_back({BuiltinName, Signature}); // Creating mapping to Intrinsics. Intrinsics.insert({Name, Index}); diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index 2b45aa5dff7be7cf8032d4ecf9e7de0ceddd015f..63348d27a8c94a1b4a24cb6fe4c4a4607a1655f9 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -1327,6 +1327,9 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, } } + if (!TheDefaultStmt) + Diag(SwitchLoc, diag::warn_switch_default); + if (!HasDependentValue) { // If we don't have a default statement, check whether the // condition is constant. diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp index eae1eaa2f9563d536c8d255f935fbf8ef803988a..725d8efe3828d659dbbeb58b91571a1453db50c3 100644 --- a/clang/lib/Sema/SemaStmtAttr.cpp +++ b/clang/lib/Sema/SemaStmtAttr.cpp @@ -397,6 +397,16 @@ static void CheckForDuplicateCodeAlignAttrs(Sema &S, } } +static Attr *handleMSConstexprAttr(Sema &S, Stmt *St, const ParsedAttr &A, + SourceRange Range) { + if (!S.getLangOpts().isCompatibleWithMSVC(LangOptions::MSVC2022_3)) { + S.Diag(A.getLoc(), diag::warn_unknown_attribute_ignored) + << A << A.getRange(); + return nullptr; + } + return ::new (S.Context) MSConstexprAttr(S.Context, A); +} + #define WANT_STMT_MERGE_LOGIC #include "clang/Sema/AttrParsedAttrImpl.inc" #undef WANT_STMT_MERGE_LOGIC @@ -600,6 +610,8 @@ static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const ParsedAttr &A, return handleUnlikely(S, St, A, Range); case ParsedAttr::AT_CodeAlign: return handleCodeAlignAttr(S, St, A); + case ParsedAttr::AT_MSConstexpr: + return handleMSConstexprAttr(S, St, A, Range); default: // N.B., ClangAttrEmitter.cpp emits a diagnostic helper that ensures a // declaration attribute is not written on a statement, but this code is diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 09bbf14d39af5ad09f68859261d6a58d944c3745..f10abeaba0d4517ed5df60d4fbaae7919b7d829a 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -820,7 +820,6 @@ bool Sema::DiagnoseUninstantiableTemplate(SourceLocation PointOfInstantiation, if (!Complain || (PatternDef && PatternDef->isInvalidDecl())) return true; - std::optional Note; QualType InstantiationTy; if (TagDecl *TD = dyn_cast(Instantiation)) InstantiationTy = Context.getTypeDeclType(TD); @@ -838,25 +837,25 @@ bool Sema::DiagnoseUninstantiableTemplate(SourceLocation PointOfInstantiation, diag::err_explicit_instantiation_undefined_member) << /*member function*/ 1 << Instantiation->getDeclName() << Instantiation->getDeclContext(); - Note = diag::note_explicit_instantiation_here; + Diag(Pattern->getLocation(), diag::note_explicit_instantiation_here); } else { assert(isa(Instantiation) && "Must be a TagDecl!"); Diag(PointOfInstantiation, diag::err_implicit_instantiate_member_undefined) << InstantiationTy; - Note = diag::note_member_declared_at; + Diag(Pattern->getLocation(), diag::note_member_declared_at); } } else { if (isa(Instantiation)) { Diag(PointOfInstantiation, diag::err_explicit_instantiation_undefined_func_template) << Pattern; - Note = diag::note_explicit_instantiation_here; + Diag(Pattern->getLocation(), diag::note_explicit_instantiation_here); } else if (isa(Instantiation)) { Diag(PointOfInstantiation, diag::err_template_instantiate_undefined) << (TSK != TSK_ImplicitInstantiation) << InstantiationTy; - Note = diag::note_template_decl_here; + NoteTemplateLocation(*Pattern); } else { assert(isa(Instantiation) && "Must be a VarDecl!"); if (isa(Instantiation)) { @@ -869,11 +868,9 @@ bool Sema::DiagnoseUninstantiableTemplate(SourceLocation PointOfInstantiation, diag::err_explicit_instantiation_undefined_member) << /*static data member*/ 2 << Instantiation->getDeclName() << Instantiation->getDeclContext(); - Note = diag::note_explicit_instantiation_here; + Diag(Pattern->getLocation(), diag::note_explicit_instantiation_here); } } - if (Note) // Diagnostics were emitted. - Diag(Pattern->getLocation(), *Note); // In general, Instantiation isn't marked invalid to get more than one // error for multiple undefined instantiations. But the code that does @@ -898,8 +895,9 @@ void Sema::DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl) { // Make this a warning when MSVC compatibility is requested. unsigned DiagId = getLangOpts().MSVCCompat ? diag::ext_template_param_shadow : diag::err_template_param_shadow; - Diag(Loc, DiagId) << cast(PrevDecl)->getDeclName(); - Diag(PrevDecl->getLocation(), diag::note_template_param_here); + const auto *ND = cast(PrevDecl); + Diag(Loc, DiagId) << ND->getDeclName(); + NoteTemplateParameterLocation(*ND); } /// AdjustDeclIfTemplate - If the given decl happens to be a template, reset @@ -1714,6 +1712,8 @@ class ConstraintRefersToContainingTemplateChecker // Friend, likely because it was referred to without its template arguments. void CheckIfContainingRecord(const CXXRecordDecl *CheckingRD) { CheckingRD = CheckingRD->getMostRecentDecl(); + if (!CheckingRD->isTemplated()) + return; for (const DeclContext *DC = Friend->getLexicalDeclContext(); DC && !DC->isFileContext(); DC = DC->getParent()) @@ -4488,7 +4488,7 @@ static void checkMoreSpecializedThanPrimary(Sema &S, PartialSpecDecl *Partial) { << SFINAEArgString; } - S.Diag(Template->getLocation(), diag::note_template_decl_here); + S.NoteTemplateLocation(*Template); SmallVector PartialAC, TemplateAC; Template->getAssociatedConstraints(TemplateAC); Partial->getAssociatedConstraints(PartialAC); @@ -4966,8 +4966,7 @@ void Sema::diagnoseMissingTemplateArguments(TemplateName Name, Diag(Loc, diag::err_template_missing_args) << (int)getTemplateNameKindForDiagnostics(Name) << Name; if (TemplateDecl *TD = Name.getAsTemplateDecl()) { - Diag(TD->getLocation(), diag::note_template_decl_here) - << TD->getTemplateParameters()->getSourceRange(); + NoteTemplateLocation(*TD, TD->getTemplateParameters()->getSourceRange()); } } @@ -5319,7 +5318,7 @@ bool Sema::CheckTemplateTypeArgument( ? diag::ext_ms_template_type_arg_missing_typename : diag::err_template_arg_must_be_type_suggest) << FixItHint::CreateInsertion(Loc, "typename "); - Diag(Param->getLocation(), diag::note_template_param_here); + NoteTemplateParameterLocation(*Param); // Recover by synthesizing a type using the location information that we // already have. @@ -5348,7 +5347,7 @@ bool Sema::CheckTemplateTypeArgument( // is not a type. SourceRange SR = AL.getSourceRange(); Diag(SR.getBegin(), diag::err_template_arg_must_be_type) << SR; - Diag(Param->getLocation(), diag::note_template_param_here); + NoteTemplateParameterLocation(*Param); return true; } @@ -5794,8 +5793,8 @@ bool Sema::CheckTemplateArgument( // therefore cannot be a non-type template argument. Diag(Arg.getLocation(), diag::err_template_arg_must_be_expr) << Arg.getSourceRange(); + NoteTemplateParameterLocation(*Param); - Diag(Param->getLocation(), diag::note_template_param_here); return true; case TemplateArgument::Type: { @@ -5815,7 +5814,7 @@ bool Sema::CheckTemplateArgument( Diag(SR.getBegin(), diag::err_template_arg_nontype_ambig) << SR << T; else Diag(SR.getBegin(), diag::err_template_arg_must_be_expr) << SR; - Diag(Param->getLocation(), diag::note_template_param_here); + NoteTemplateParameterLocation(*Param); return true; } @@ -5936,8 +5935,7 @@ static bool diagnoseMissingArgument(Sema &S, SourceLocation Loc, << /*not enough args*/0 << (int)S.getTemplateNameKindForDiagnostics(TemplateName(TD)) << TD; - S.Diag(TD->getLocation(), diag::note_template_decl_here) - << Params->getSourceRange(); + S.NoteTemplateLocation(*TD, Params->getSourceRange()); return true; } @@ -6003,8 +6001,7 @@ bool Sema::CheckTemplateArgumentList( << /*not enough args*/0 << (int)getTemplateNameKindForDiagnostics(TemplateName(Template)) << Template; - Diag(Template->getLocation(), diag::note_template_decl_here) - << Params->getSourceRange(); + NoteTemplateLocation(*Template, Params->getSourceRange()); return true; } } @@ -6036,7 +6033,7 @@ bool Sema::CheckTemplateArgumentList( diag::err_template_expansion_into_fixed_list) << (isa(Template) ? 1 : 0) << NewArgs[ArgIdx].getSourceRange(); - Diag((*Param)->getLocation(), diag::note_template_param_here); + NoteTemplateParameterLocation(**Param); return true; } @@ -6232,8 +6229,7 @@ bool Sema::CheckTemplateArgumentList( << (int)getTemplateNameKindForDiagnostics(TemplateName(Template)) << Template << SourceRange(NewArgs[ArgIdx].getLocation(), NewArgs.getRAngleLoc()); - Diag(Template->getLocation(), diag::note_template_decl_here) - << Params->getSourceRange(); + NoteTemplateLocation(*Template, Params->getSourceRange()); return true; } @@ -6645,7 +6641,7 @@ isNullPointerValueTemplateArgument(Sema &S, NonTypeTemplateParmDecl *Param, for (unsigned I = 0, N = Notes.size(); I != N; ++I) S.Diag(Notes[I].first, Notes[I].second); - S.Diag(Param->getLocation(), diag::note_template_param_here); + S.NoteTemplateParameterLocation(*Param); return NPV_Error; } @@ -6671,7 +6667,7 @@ isNullPointerValueTemplateArgument(Sema &S, NonTypeTemplateParmDecl *Param, // then recover as if the types were correct. S.Diag(Arg->getExprLoc(), diag::err_template_arg_wrongtype_null_constant) << Arg->getType() << ParamType << Arg->getSourceRange(); - S.Diag(Param->getLocation(), diag::note_template_param_here); + S.NoteTemplateParameterLocation(*Param); return NPV_NullPointer; } @@ -6681,7 +6677,7 @@ isNullPointerValueTemplateArgument(Sema &S, NonTypeTemplateParmDecl *Param, // message with the information we have here. S.Diag(Arg->getExprLoc(), diag::err_template_arg_invalid) << EvalResult.Val.getAsString(S.Context, ParamType); - S.Diag(Param->getLocation(), diag::note_template_param_here); + S.NoteTemplateParameterLocation(*Param); return NPV_Error; } @@ -6693,7 +6689,7 @@ isNullPointerValueTemplateArgument(Sema &S, NonTypeTemplateParmDecl *Param, << ParamType << FixItHint::CreateInsertion(Arg->getBeginLoc(), Code) << FixItHint::CreateInsertion(S.getLocForEndOfToken(Arg->getEndLoc()), ")"); - S.Diag(Param->getLocation(), diag::note_template_param_here); + S.NoteTemplateParameterLocation(*Param); return NPV_NullPointer; } @@ -6734,7 +6730,7 @@ static bool CheckTemplateArgumentIsCompatibleWithParameter( S.Diag(Arg->getBeginLoc(), diag::err_template_arg_ref_bind_ignores_quals) << ParamType << Arg->getType() << Arg->getSourceRange(); - S.Diag(Param->getLocation(), diag::note_template_param_here); + S.NoteTemplateParameterLocation(*Param); return true; } } @@ -6752,7 +6748,7 @@ static bool CheckTemplateArgumentIsCompatibleWithParameter( else S.Diag(Arg->getBeginLoc(), diag::err_template_arg_not_convertible) << ArgIn->getType() << ParamType << Arg->getSourceRange(); - S.Diag(Param->getLocation(), diag::note_template_param_here); + S.NoteTemplateParameterLocation(*Param); return true; } } @@ -6895,7 +6891,7 @@ static bool CheckTemplateArgumentAddressOfObjectOrFunction( if (!Entity) { S.Diag(Arg->getBeginLoc(), diag::err_template_arg_not_decl_ref) << Arg->getSourceRange(); - S.Diag(Param->getLocation(), diag::note_template_param_here); + S.NoteTemplateParameterLocation(*Param); return true; } @@ -6903,7 +6899,7 @@ static bool CheckTemplateArgumentAddressOfObjectOrFunction( if (isa(Entity) || isa(Entity)) { S.Diag(Arg->getBeginLoc(), diag::err_template_arg_field) << Entity << Arg->getSourceRange(); - S.Diag(Param->getLocation(), diag::note_template_param_here); + S.NoteTemplateParameterLocation(*Param); return true; } @@ -6912,7 +6908,7 @@ static bool CheckTemplateArgumentAddressOfObjectOrFunction( if (!Method->isStatic()) { S.Diag(Arg->getBeginLoc(), diag::err_template_arg_method) << Method << Arg->getSourceRange(); - S.Diag(Param->getLocation(), diag::note_template_param_here); + S.NoteTemplateParameterLocation(*Param); return true; } } @@ -6952,7 +6948,7 @@ static bool CheckTemplateArgumentAddressOfObjectOrFunction( if (Var->getType()->isReferenceType()) { S.Diag(Arg->getBeginLoc(), diag::err_template_arg_reference_var) << Var->getType() << Arg->getSourceRange(); - S.Diag(Param->getLocation(), diag::note_template_param_here); + S.NoteTemplateParameterLocation(*Param); return true; } @@ -6973,14 +6969,14 @@ static bool CheckTemplateArgumentAddressOfObjectOrFunction( ParamType.getNonReferenceType())) { S.Diag(AddrOpLoc, diag::err_template_arg_address_of_non_pointer) << ParamType; - S.Diag(Param->getLocation(), diag::note_template_param_here); + S.NoteTemplateParameterLocation(*Param); return true; } S.Diag(AddrOpLoc, diag::err_template_arg_address_of_non_pointer) << ParamType << FixItHint::CreateRemoval(AddrOpLoc); - S.Diag(Param->getLocation(), diag::note_template_param_here); + S.NoteTemplateParameterLocation(*Param); ArgType = Entity->getType(); } @@ -7002,14 +6998,14 @@ static bool CheckTemplateArgumentAddressOfObjectOrFunction( if (!S.Context.hasSameUnqualifiedType(ArgType, ParamType)) { S.Diag(Arg->getBeginLoc(), diag::err_template_arg_not_address_of) << ParamType; - S.Diag(Param->getLocation(), diag::note_template_param_here); + S.NoteTemplateParameterLocation(*Param); return true; } S.Diag(Arg->getBeginLoc(), diag::err_template_arg_not_address_of) << ParamType << FixItHint::CreateInsertion(Arg->getBeginLoc(), "&"); - S.Diag(Param->getLocation(), diag::note_template_param_here); + S.NoteTemplateParameterLocation(*Param); } } @@ -7125,7 +7121,7 @@ CheckTemplateArgumentPointerToMember(Sema &S, NonTypeTemplateParmDecl *Param, // We can't perform this conversion. S.Diag(ResultArg->getBeginLoc(), diag::err_template_arg_not_convertible) << ResultArg->getType() << ParamType << ResultArg->getSourceRange(); - S.Diag(Param->getLocation(), diag::note_template_param_here); + S.NoteTemplateParameterLocation(*Param); return true; } @@ -7237,7 +7233,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, diag::err_non_type_template_parm_type_deduction_failure) << Param->getDeclName() << Param->getType() << Arg->getType() << Arg->getSourceRange(); - Diag(Param->getLocation(), diag::note_template_param_here); + NoteTemplateParameterLocation(*Param); return ExprError(); } } @@ -7247,7 +7243,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, // where the parameter type is deduced. ParamType = CheckNonTypeTemplateParameterType(ParamType, Arg->getExprLoc()); if (ParamType.isNull()) { - Diag(Param->getLocation(), diag::note_template_param_here); + NoteTemplateParameterLocation(*Param); return ExprError(); } } @@ -7283,7 +7279,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, Diag(StartLoc, diag::err_deduced_non_type_template_arg_type_mismatch) << Arg->getType() << ParamType.getUnqualifiedType(); - Diag(Param->getLocation(), diag::note_template_param_here); + NoteTemplateParameterLocation(*Param); return ExprError(); } @@ -7580,7 +7576,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, if (!ArgType->isIntegralOrEnumerationType()) { Diag(Arg->getBeginLoc(), diag::err_template_arg_not_integral_or_enumeral) << ArgType << Arg->getSourceRange(); - Diag(Param->getLocation(), diag::note_template_param_here); + NoteTemplateParameterLocation(*Param); return ExprError(); } else if (!Arg->isValueDependent()) { class TmplArgICEDiagnoser : public VerifyICEDiagnoser { @@ -7618,7 +7614,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, // We can't perform this conversion. Diag(Arg->getBeginLoc(), diag::err_template_arg_not_convertible) << Arg->getType() << ParamType << Arg->getSourceRange(); - Diag(Param->getLocation(), diag::note_template_param_here); + NoteTemplateParameterLocation(*Param); return ExprError(); } @@ -7664,7 +7660,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, Diag(Arg->getBeginLoc(), diag::warn_template_arg_negative) << toString(OldValue, 10) << toString(Value, 10) << Param->getType() << Arg->getSourceRange(); - Diag(Param->getLocation(), diag::note_template_param_here); + NoteTemplateParameterLocation(*Param); } // Complain if we overflowed the template parameter's type. @@ -7679,7 +7675,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, Diag(Arg->getBeginLoc(), diag::warn_template_arg_too_large) << toString(OldValue, 10) << toString(Value, 10) << Param->getType() << Arg->getSourceRange(); - Diag(Param->getLocation(), diag::note_template_param_here); + NoteTemplateParameterLocation(*Param); } } @@ -7806,7 +7802,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, case NPV_NotNullPointer: Diag(Arg->getExprLoc(), diag::err_template_arg_not_convertible) << Arg->getType() << ParamType; - Diag(Param->getLocation(), diag::note_template_param_here); + NoteTemplateParameterLocation(*Param); return ExprError(); case NPV_Error: @@ -7941,6 +7937,37 @@ bool Sema::CheckTemplateTemplateArgument(TemplateTemplateParmDecl *Param, Arg.getLocation()); } +static Sema::SemaDiagnosticBuilder noteLocation(Sema &S, const NamedDecl &Decl, + unsigned HereDiagID, + unsigned ExternalDiagID) { + if (Decl.getLocation().isValid()) + return S.Diag(Decl.getLocation(), HereDiagID); + + SmallString<128> Str; + llvm::raw_svector_ostream Out(Str); + PrintingPolicy PP = S.getPrintingPolicy(); + PP.TerseOutput = 1; + Decl.print(Out, PP); + return S.Diag(Decl.getLocation(), ExternalDiagID) << Out.str(); +} + +void Sema::NoteTemplateLocation(const NamedDecl &Decl, + std::optional ParamRange) { + SemaDiagnosticBuilder DB = + noteLocation(*this, Decl, diag::note_template_decl_here, + diag::note_template_decl_external); + if (ParamRange && ParamRange->isValid()) { + assert(Decl.getLocation().isValid() && + "Parameter range has location when Decl does not"); + DB << *ParamRange; + } +} + +void Sema::NoteTemplateParameterLocation(const NamedDecl &Decl) { + noteLocation(*this, Decl, diag::note_template_param_here, + diag::note_template_param_external); +} + /// Given a non-type template argument that refers to a /// declaration and the type of its corresponding non-type template /// parameter, produce an expression that properly refers to that @@ -8666,9 +8693,7 @@ static bool CheckNonTypeTemplatePartialSpecializationArgs( S.Diag(IsDefaultArgument ? TemplateNameLoc : ArgExpr->getBeginLoc(), diag::err_dependent_typed_non_type_arg_in_partial_spec) << Param->getType(); - S.Diag(Param->getLocation(), diag::note_template_param_here) - << (IsDefaultArgument ? ParamUseRange : SourceRange()) - << ParamUseRange; + S.NoteTemplateParameterLocation(*Param); return true; } } @@ -11248,7 +11273,7 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword, else Diag(IILoc, diag::err_deduced_tst) << (int)getTemplateNameKindForDiagnostics(TemplateName(TD)); - Diag(TD->getLocation(), diag::note_template_decl_here); + NoteTemplateLocation(*TD); return QualType(); } return Context.getElaboratedType( diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 4ae027bd1bb6735d5bbbaaaf2db1a2cb2ae9e3bc..df6b40999e645c6825bae1fa591bff4e9bd53ed2 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -810,6 +810,10 @@ void Sema::PrintInstantiationStack() { Diags.Report(Active->PointOfInstantiation, diag::note_template_nsdmi_here) << FD << Active->InstantiationRange; + } else if (ClassTemplateDecl *CTD = dyn_cast(D)) { + Diags.Report(Active->PointOfInstantiation, + diag::note_template_class_instantiation_here) + << CTD << Active->InstantiationRange; } else { Diags.Report(Active->PointOfInstantiation, diag::note_template_type_alias_instantiation_here) diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 56d133f20a2935170486e0a34c23989081a36cb2..83610503ed9b16b12089c54dc5e8766ef5272bbc 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -3792,7 +3792,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, << Kind << Error << (int)SemaRef.getTemplateNameKindForDiagnostics(TN) << QualType(Deduced, 0) << AutoRange; if (auto *TD = TN.getAsTemplateDecl()) - SemaRef.Diag(TD->getLocation(), diag::note_template_decl_here); + SemaRef.NoteTemplateLocation(*TD); T = SemaRef.Context.IntTy; D.setInvalidType(true); diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index f22da838424b4155599c83341ac0f913f70a47f8..5b51ac40000d7a9894a25c3d7c2727f73dc4348a 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -2531,8 +2531,7 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) { Overridden = false; } - OptionalFileEntryRefDegradesToFileEntryPtr File = OptionalFileEntryRef( - expectedToOptional(FileMgr.getFileRef(Filename, /*OpenFile=*/false))); + auto File = FileMgr.getOptionalFileRef(Filename, /*OpenFile=*/false); // For an overridden file, create a virtual file with the stored // size/timestamp. @@ -2559,7 +2558,8 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) { // PCH. SourceManager &SM = getSourceManager(); // FIXME: Reject if the overrides are different. - if ((!Overridden && !Transient) && !SkipChecks && SM.isFileOverridden(File)) { + if ((!Overridden && !Transient) && !SkipChecks && + SM.isFileOverridden(*File)) { if (Complain) Error(diag::err_fe_pch_file_overridden, Filename); @@ -3152,7 +3152,7 @@ ASTReader::ReadControlBlock(ModuleFile &F, if (!bool(PP.getPreprocessorOpts().DisablePCHOrModuleValidation & DisableValidationForModuleKind::Module) && F.Kind != MK_ExplicitModule && F.Kind != MK_PrebuiltModule) { - auto BuildDir = PP.getFileManager().getDirectory(Blob); + auto BuildDir = PP.getFileManager().getOptionalDirectoryRef(Blob); if (!BuildDir || *BuildDir != M->Directory) { if (!canRecoverFromOutOfDate(F.FileName, ClientLoadCapabilities)) Diag(diag::err_imported_module_relocated) @@ -5786,7 +5786,7 @@ llvm::Error ASTReader::ReadSubmoduleBlock(ModuleFile &F, PartialDiagnostic(diag::err_module_file_conflict, ContextObj->DiagAllocator) << CurrentModule->getTopLevelModuleName() << CurFile->getName() - << F.File->getName(); + << F.File.getName(); return DiagnosticError::create(CurrentImportLoc, ConflictError); } } diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index bc16cfc67a24f9fa45292ca92612aee7b5f1101f..7140a14aefbf9b188f70145a30258342eacc9bb1 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -583,6 +583,9 @@ void ASTDeclReader::Visit(Decl *D) { } void ASTDeclReader::VisitDecl(Decl *D) { + BitsUnpacker DeclBits(Record.readInt()); + bool HasStandaloneLexicalDC = DeclBits.getNextBit(); + if (D->isTemplateParameter() || D->isTemplateParameterPack() || isa(D)) { // We don't want to deserialize the DeclContext of a template @@ -592,7 +595,8 @@ void ASTDeclReader::VisitDecl(Decl *D) { // return type of the function). Use the translation unit DeclContext as a // placeholder. GlobalDeclID SemaDCIDForTemplateParmDecl = readDeclID(); - GlobalDeclID LexicalDCIDForTemplateParmDecl = readDeclID(); + GlobalDeclID LexicalDCIDForTemplateParmDecl = + HasStandaloneLexicalDC ? readDeclID() : 0; if (!LexicalDCIDForTemplateParmDecl) LexicalDCIDForTemplateParmDecl = SemaDCIDForTemplateParmDecl; Reader.addPendingDeclContextInfo(D, @@ -601,7 +605,8 @@ void ASTDeclReader::VisitDecl(Decl *D) { D->setDeclContext(Reader.getContext().getTranslationUnitDecl()); } else { auto *SemaDC = readDeclAs(); - auto *LexicalDC = readDeclAs(); + auto *LexicalDC = + HasStandaloneLexicalDC ? readDeclAs() : nullptr; if (!LexicalDC) LexicalDC = SemaDC; // If the context is a class, we might not have actually merged it yet, in @@ -618,7 +623,6 @@ void ASTDeclReader::VisitDecl(Decl *D) { } D->setLocation(ThisDeclLoc); - BitsUnpacker DeclBits(Record.readInt()); D->InvalidDecl = DeclBits.getNextBit(); bool HasAttrs = DeclBits.getNextBit(); D->setImplicit(DeclBits.getNextBit()); @@ -765,7 +769,7 @@ ASTDeclReader::RedeclarableResult ASTDeclReader::VisitTagDecl(TagDecl *TD) { TD->setCompleteDefinitionRequired(TagDeclBits.getNextBit()); TD->setBraceRange(readSourceRange()); - switch (Record.readInt()) { + switch (TagDeclBits.getNextBits(/*Width=*/2)) { case 0: break; case 1: { // ExtInfo @@ -1089,7 +1093,8 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) { FD->setCachedLinkage((Linkage)FunctionDeclBits.getNextBits(/*Width=*/3)); FD->EndRangeLoc = readSourceLocation(); - FD->setDefaultLoc(readSourceLocation()); + if (FD->isExplicitlyDefaulted()) + FD->setDefaultLoc(readSourceLocation()); FD->ODRHash = Record.readInt(); FD->setHasODRHash(true); @@ -1703,7 +1708,7 @@ void ASTDeclReader::VisitParmVarDecl(ParmVarDecl *PD) { unsigned isObjCMethodParam = ParmVarDeclBits.getNextBit(); unsigned scopeDepth = ParmVarDeclBits.getNextBits(/*Width=*/7); unsigned scopeIndex = ParmVarDeclBits.getNextBits(/*Width=*/8); - unsigned declQualifier = Record.readInt(); + unsigned declQualifier = ParmVarDeclBits.getNextBits(/*Width=*/7); if (isObjCMethodParam) { assert(scopeDepth == 0); PD->setObjCMethodScopeInfo(scopeIndex); @@ -1716,7 +1721,9 @@ void ASTDeclReader::VisitParmVarDecl(ParmVarDecl *PD) { PD->ParmVarDeclBits.HasInheritedDefaultArg = ParmVarDeclBits.getNextBit(); if (ParmVarDeclBits.getNextBit()) // hasUninstantiatedDefaultArg. PD->setUninstantiatedDefaultArg(Record.readExpr()); - PD->ExplicitObjectParameterIntroducerLoc = Record.readSourceLocation(); + + if (ParmVarDeclBits.getNextBit()) // Valid explicit object parameter + PD->ExplicitObjectParameterIntroducerLoc = Record.readSourceLocation(); // FIXME: If this is a redeclaration of a function from another module, handle // inheritance of default arguments. diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index d7d0c0e5bb21b47823e3152dd001ae20bf707256..b3a6f619372b4a77e1e134075bf8f9586d8c289f 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -108,7 +108,7 @@ namespace clang { /// The number of record fields required for the Expr class /// itself. - static const unsigned NumExprFields = NumStmtFields + 4; + static const unsigned NumExprFields = NumStmtFields + 2; /// Read and initialize a ExplicitTemplateArgumentList structure. void ReadTemplateKWAndArgsInfo(ASTTemplateKWAndArgsInfo &Args, @@ -524,9 +524,13 @@ void ASTStmtReader::VisitCapturedStmt(CapturedStmt *S) { void ASTStmtReader::VisitExpr(Expr *E) { VisitStmt(E); E->setType(Record.readType()); - E->setDependence(static_cast(Record.readInt())); - E->setValueKind(static_cast(Record.readInt())); - E->setObjectKind(static_cast(Record.readInt())); + BitsUnpacker ExprBits(Record.readInt()); + E->setDependence( + static_cast(ExprBits.getNextBits(/*Width=*/5))); + E->setValueKind( + static_cast(ExprBits.getNextBits(/*Width=*/2))); + E->setObjectKind( + static_cast(ExprBits.getNextBits(/*Width=*/3))); assert(Record.getIdx() == NumExprFields && "Incorrect expression field count"); } @@ -995,14 +999,19 @@ void ASTStmtReader::VisitOMPIteratorExpr(OMPIteratorExpr *E) { void ASTStmtReader::VisitCallExpr(CallExpr *E) { VisitExpr(E); - unsigned NumArgs = Record.readInt(); - bool HasFPFeatures = Record.readInt(); + + BitsUnpacker CallExprBits = Record.readInt(); + + unsigned NumArgs = CallExprBits.getNextBits(/*Width=*/16); + bool HasFPFeatures = CallExprBits.getNextBit(); + E->setADLCallKind( + static_cast(CallExprBits.getNextBit())); assert((NumArgs == E->getNumArgs()) && "Wrong NumArgs!"); E->setRParenLoc(readSourceLocation()); E->setCallee(Record.readSubExpr()); for (unsigned I = 0; I != NumArgs; ++I) E->setArg(I, Record.readSubExpr()); - E->setADLCallKind(static_cast(Record.readInt())); + if (HasFPFeatures) E->setStoredFPFeatures( FPOptionsOverride::getFromOpaqueInt(Record.readInt())); @@ -2013,14 +2022,15 @@ ASTStmtReader::VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *E) { void ASTStmtReader::VisitOverloadExpr(OverloadExpr *E) { VisitExpr(E); - unsigned NumResults = Record.readInt(); - bool HasTemplateKWAndArgsInfo = Record.readInt(); + BitsUnpacker OverloadExprBits = Record.readInt(); + unsigned NumResults = OverloadExprBits.getNextBits(/*Width=*/14); + bool HasTemplateKWAndArgsInfo = OverloadExprBits.getNextBit(); assert((E->getNumDecls() == NumResults) && "Wrong NumResults!"); assert((E->hasTemplateKWAndArgsInfo() == HasTemplateKWAndArgsInfo) && "Wrong HasTemplateKWAndArgsInfo!"); if (HasTemplateKWAndArgsInfo) { - unsigned NumTemplateArgs = Record.readInt(); + unsigned NumTemplateArgs = OverloadExprBits.getNextBits(/*Width=*/14); ReadTemplateKWAndArgsInfo(*E->getTrailingASTTemplateKWAndArgsInfo(), E->getTrailingTemplateArgumentLoc(), NumTemplateArgs); @@ -3022,11 +3032,13 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { Record[ASTStmtReader::NumExprFields]); break; - case EXPR_CALL: - S = CallExpr::CreateEmpty( - Context, /*NumArgs=*/Record[ASTStmtReader::NumExprFields], - /*HasFPFeatures=*/Record[ASTStmtReader::NumExprFields + 1], Empty); + case EXPR_CALL: { + BitsUnpacker CallExprBits(Record[ASTStmtReader::NumExprFields]); + auto NumArgs = CallExprBits.getNextBits(/*Width=*/16); + auto HasFPFeatures = CallExprBits.getNextBit(); + S = CallExpr::CreateEmpty(Context, NumArgs, HasFPFeatures, Empty); break; + } case EXPR_RECOVERY: S = RecoveryExpr::CreateEmpty( @@ -3764,17 +3776,23 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { break; } - case EXPR_CXX_OPERATOR_CALL: - S = CXXOperatorCallExpr::CreateEmpty( - Context, /*NumArgs=*/Record[ASTStmtReader::NumExprFields], - /*HasFPFeatures=*/Record[ASTStmtReader::NumExprFields + 1], Empty); + case EXPR_CXX_OPERATOR_CALL: { + BitsUnpacker CallExprBits(Record[ASTStmtReader::NumExprFields]); + auto NumArgs = CallExprBits.getNextBits(/*Width=*/16); + auto HasFPFeatures = CallExprBits.getNextBit(); + S = CXXOperatorCallExpr::CreateEmpty(Context, NumArgs, HasFPFeatures, + Empty); break; + } - case EXPR_CXX_MEMBER_CALL: - S = CXXMemberCallExpr::CreateEmpty( - Context, /*NumArgs=*/Record[ASTStmtReader::NumExprFields], - /*HasFPFeatures=*/Record[ASTStmtReader::NumExprFields + 1], Empty); + case EXPR_CXX_MEMBER_CALL: { + BitsUnpacker CallExprBits(Record[ASTStmtReader::NumExprFields]); + auto NumArgs = CallExprBits.getNextBits(/*Width=*/16); + auto HasFPFeatures = CallExprBits.getNextBit(); + S = CXXMemberCallExpr::CreateEmpty(Context, NumArgs, HasFPFeatures, + Empty); break; + } case EXPR_CXX_REWRITTEN_BINARY_OPERATOR: S = new (Context) CXXRewrittenBinaryOperator(Empty); @@ -3833,11 +3851,14 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { S = new (Context) BuiltinBitCastExpr(Empty); break; - case EXPR_USER_DEFINED_LITERAL: - S = UserDefinedLiteral::CreateEmpty( - Context, /*NumArgs=*/Record[ASTStmtReader::NumExprFields], - /*HasFPFeatures=*/Record[ASTStmtReader::NumExprFields + 1], Empty); + case EXPR_USER_DEFINED_LITERAL: { + BitsUnpacker CallExprBits(Record[ASTStmtReader::NumExprFields]); + auto NumArgs = CallExprBits.getNextBits(/*Width=*/16); + auto HasFPFeatures = CallExprBits.getNextBit(); + S = UserDefinedLiteral::CreateEmpty(Context, NumArgs, HasFPFeatures, + Empty); break; + } case EXPR_CXX_STD_INITIALIZER_LIST: S = new (Context) CXXStdInitializerListExpr(Empty); @@ -3948,23 +3969,21 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { case EXPR_CXX_UNRESOLVED_MEMBER: S = UnresolvedMemberExpr::CreateEmpty( Context, - /*NumResults=*/Record[ASTStmtReader::NumExprFields], - /*HasTemplateKWAndArgsInfo=*/Record[ASTStmtReader::NumExprFields + 1], - /*NumTemplateArgs=*/ - Record[ASTStmtReader::NumExprFields + 1] - ? Record[ASTStmtReader::NumExprFields + 2] - : 0); + /*NumResults=*/Record[ASTStmtReader::NumExprFields] & ((1 << 14) - 1), + /*HasTemplateKWAndArgsInfo=*/ + (Record[ASTStmtReader::NumExprFields] >> 14) & (0x1), + /*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields] >> 14 & + ((1 << 14) - 1)); break; case EXPR_CXX_UNRESOLVED_LOOKUP: S = UnresolvedLookupExpr::CreateEmpty( Context, - /*NumResults=*/Record[ASTStmtReader::NumExprFields], - /*HasTemplateKWAndArgsInfo=*/Record[ASTStmtReader::NumExprFields + 1], - /*NumTemplateArgs=*/ - Record[ASTStmtReader::NumExprFields + 1] - ? Record[ASTStmtReader::NumExprFields + 2] - : 0); + /*NumResults=*/Record[ASTStmtReader::NumExprFields] & ((1 << 14) - 1), + /*HasTemplateKWAndArgsInfo=*/ + (Record[ASTStmtReader::NumExprFields] >> 14) & (0x1), + /*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields] >> 14 & + ((1 << 14) - 1)); break; case EXPR_TYPE_TRAIT: @@ -4024,11 +4043,14 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { S = new (Context) OpaqueValueExpr(Empty); break; - case EXPR_CUDA_KERNEL_CALL: - S = CUDAKernelCallExpr::CreateEmpty( - Context, /*NumArgs=*/Record[ASTStmtReader::NumExprFields], - /*HasFPFeatures=*/Record[ASTStmtReader::NumExprFields + 1], Empty); + case EXPR_CUDA_KERNEL_CALL: { + BitsUnpacker CallExprBits(Record[ASTStmtReader::NumExprFields]); + auto NumArgs = CallExprBits.getNextBits(/*Width=*/16); + auto HasFPFeatures = CallExprBits.getNextBit(); + S = CUDAKernelCallExpr::CreateEmpty(Context, NumArgs, HasFPFeatures, + Empty); break; + } case EXPR_ASTYPE: S = new (Context) AsTypeExpr(Empty); diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 6df815234e235fb50437308ae6dc75238123229c..91eb2af8f8ad6a55ce6b8d1b85b6111e93ce098c 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -1413,7 +1413,7 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context, // If we have calculated signature, there is no need to store // the size or timestamp. - Record.push_back(M.Signature ? 0 : M.File->getSize()); + Record.push_back(M.Signature ? 0 : M.File.getSize()); Record.push_back(M.Signature ? 0 : getTimestampForOutput(M.File)); llvm::append_range(Record, M.Signature); @@ -2182,8 +2182,8 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, "Writing to AST an overridden file is not supported"); // The source location entry is a file. Emit input file ID. - assert(InputFileIDs[Content->OrigEntry] != 0 && "Missed file entry"); - Record.push_back(InputFileIDs[Content->OrigEntry]); + assert(InputFileIDs[*Content->OrigEntry] != 0 && "Missed file entry"); + Record.push_back(InputFileIDs[*Content->OrigEntry]); Record.push_back(getAdjustedNumCreatedFIDs(FID)); @@ -4695,7 +4695,7 @@ void ASTWriter::collectNonAffectingInputFiles() { if (!isModuleMap(File.getFileCharacteristic()) || AffectingModuleMaps.empty() || - AffectingModuleMaps.find(Cache->OrigEntry) != AffectingModuleMaps.end()) + llvm::is_contained(AffectingModuleMaps, *Cache->OrigEntry)) continue; IsSLocAffecting[I] = false; diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp index bf082e5b8eac61ace9021013f75161a5aa9bc960..43169b2befc687ed5731f6d189655ff324996b6d 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -320,13 +320,8 @@ void ASTDeclWriter::Visit(Decl *D) { } void ASTDeclWriter::VisitDecl(Decl *D) { - Record.AddDeclRef(cast_or_null(D->getDeclContext())); - if (D->getDeclContext() != D->getLexicalDeclContext()) - Record.AddDeclRef(cast_or_null(D->getLexicalDeclContext())); - else - Record.push_back(0); - BitsPacker DeclBits; + DeclBits.addBit(D->getDeclContext() != D->getLexicalDeclContext()); DeclBits.addBit(D->isInvalidDecl()); DeclBits.addBit(D->hasAttrs()); DeclBits.addBit(D->isImplicit()); @@ -337,6 +332,10 @@ void ASTDeclWriter::VisitDecl(Decl *D) { DeclBits.addBits((uint64_t)D->getModuleOwnershipKind(), /*BitWidth=*/3); Record.push_back(DeclBits); + Record.AddDeclRef(cast_or_null(D->getDeclContext())); + if (D->getDeclContext() != D->getLexicalDeclContext()) + Record.AddDeclRef(cast_or_null(D->getLexicalDeclContext())); + if (D->hasAttrs()) Record.AddAttributes(D->getAttrs()); @@ -450,19 +449,18 @@ void ASTDeclWriter::VisitTagDecl(TagDecl *D) { TagDeclBits.addBit(D->isEmbeddedInDeclarator()); TagDeclBits.addBit(D->isFreeStanding()); TagDeclBits.addBit(D->isCompleteDefinitionRequired()); + TagDeclBits.addBits( + D->hasExtInfo() ? 1 : (D->getTypedefNameForAnonDecl() ? 2 : 0), + /*BitWidth=*/2); Record.push_back(TagDeclBits); Record.AddSourceRange(D->getBraceRange()); if (D->hasExtInfo()) { - Record.push_back(1); Record.AddQualifierInfo(*D->getExtInfo()); } else if (auto *TD = D->getTypedefNameForAnonDecl()) { - Record.push_back(2); Record.AddDeclRef(TD); Record.AddIdentifierRef(TD->getDeclName().getAsIdentifierInfo()); - } else { - Record.push_back(0); } } @@ -702,7 +700,8 @@ void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) { Record.push_back(FunctionDeclBits); Record.AddSourceLocation(D->getEndLoc()); - Record.AddSourceLocation(D->getDefaultLoc()); + if (D->isExplicitlyDefaulted()) + Record.AddSourceLocation(D->getDefaultLoc()); Record.push_back(D->getODRHash()); @@ -1176,15 +1175,18 @@ void ASTDeclWriter::VisitParmVarDecl(ParmVarDecl *D) { ParmVarDeclBits.addBit(D->isObjCMethodParameter()); ParmVarDeclBits.addBits(D->getFunctionScopeDepth(), /*BitsWidth=*/7); ParmVarDeclBits.addBits(D->getFunctionScopeIndex(), /*BitsWidth=*/8); + // FIXME: stable encoding + ParmVarDeclBits.addBits(D->getObjCDeclQualifier(), /*BitsWidth=*/7); ParmVarDeclBits.addBit(D->isKNRPromoted()); ParmVarDeclBits.addBit(D->hasInheritedDefaultArg()); ParmVarDeclBits.addBit(D->hasUninstantiatedDefaultArg()); + ParmVarDeclBits.addBit(D->getExplicitObjectParamThisLoc().isValid()); Record.push_back(ParmVarDeclBits); - Record.push_back(D->getObjCDeclQualifier()); // FIXME: stable encoding if (D->hasUninstantiatedDefaultArg()) Record.AddStmt(D->getUninstantiatedDefaultArg()); - Record.AddSourceLocation(D->getExplicitObjectParamThisLoc()); + if (D->getExplicitObjectParamThisLoc().isValid()) + Record.AddSourceLocation(D->getExplicitObjectParamThisLoc()); Code = serialization::DECL_PARM_VAR; // If the assumptions about the DECL_PARM_VAR abbrev are true, use it. Here @@ -2038,13 +2040,12 @@ void ASTWriter::WriteDeclAbbrevs() { Abv = std::make_shared(); Abv->Add(BitCodeAbbrevOp(serialization::DECL_FIELD)); // Decl + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, + 12)); // Packed DeclBits: HasStandaloneLexicalDC, + // isInvalidDecl, HasAttrs, isImplicit, isUsed, + // isReferenced, TopLevelDeclInObjCContainer, + // AccessSpecifier, ModuleOwnershipKind Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext - Abv->Add(BitCodeAbbrevOp(0)); // LexicalDeclContext - Abv->Add(BitCodeAbbrevOp( - BitCodeAbbrevOp::Fixed, - 11)); // Packed DeclBits: isInvalidDecl, HasAttrs, isImplicit, isUsed, - // isReferenced, TopLevelDeclInObjCContainer, AccessSpecifier, - // ModuleOwnershipKind Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID // NamedDecl Abv->Add(BitCodeAbbrevOp(0)); // NameKind = Identifier @@ -2068,13 +2069,12 @@ void ASTWriter::WriteDeclAbbrevs() { Abv = std::make_shared(); Abv->Add(BitCodeAbbrevOp(serialization::DECL_OBJC_IVAR)); // Decl + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, + 12)); // Packed DeclBits: HasStandaloneLexicalDC, + // isInvalidDecl, HasAttrs, isImplicit, isUsed, + // isReferenced, TopLevelDeclInObjCContainer, + // AccessSpecifier, ModuleOwnershipKind Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext - Abv->Add(BitCodeAbbrevOp(0)); // LexicalDeclContext - Abv->Add(BitCodeAbbrevOp( - BitCodeAbbrevOp::Fixed, - 11)); // Packed DeclBits: isInvalidDecl, HasAttrs, isImplicit, isUsed, - // isReferenced, TopLevelDeclInObjCContainer, AccessSpecifier, - // ModuleOwnershipKind Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID // NamedDecl Abv->Add(BitCodeAbbrevOp(0)); // NameKind = Identifier @@ -2103,13 +2103,12 @@ void ASTWriter::WriteDeclAbbrevs() { // Redeclarable Abv->Add(BitCodeAbbrevOp(0)); // No redeclaration // Decl + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, + 12)); // Packed DeclBits: HasStandaloneLexicalDC, + // isInvalidDecl, HasAttrs, isImplicit, isUsed, + // isReferenced, TopLevelDeclInObjCContainer, + // AccessSpecifier, ModuleOwnershipKind Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext - Abv->Add(BitCodeAbbrevOp(0)); // LexicalDeclContext - Abv->Add(BitCodeAbbrevOp( - BitCodeAbbrevOp::Fixed, - 11)); // Packed DeclBits: isInvalidDecl, HasAttrs, isImplicit, isUsed, - // isReferenced, TopLevelDeclInObjCContainer, AccessSpecifier, - // ModuleOwnershipKind Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID // NamedDecl Abv->Add(BitCodeAbbrevOp(0)); // NameKind = Identifier @@ -2122,11 +2121,11 @@ void ASTWriter::WriteDeclAbbrevs() { Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // IdentifierNamespace Abv->Add(BitCodeAbbrevOp( BitCodeAbbrevOp::Fixed, - 7)); // Packed Tag Decl Bits: getTagKind, isCompleteDefinition, - // EmbeddedInDeclarator, IsFreeStanding, isCompleteDefinitionRequired + 9)); // Packed Tag Decl Bits: getTagKind, isCompleteDefinition, + // EmbeddedInDeclarator, IsFreeStanding, + // isCompleteDefinitionRequired, ExtInfoKind Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SourceLocation Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SourceLocation - Abv->Add(BitCodeAbbrevOp(0)); // ExtInfoKind // EnumDecl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // AddTypeRef Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // IntegerType @@ -2145,13 +2144,12 @@ void ASTWriter::WriteDeclAbbrevs() { // Redeclarable Abv->Add(BitCodeAbbrevOp(0)); // No redeclaration // Decl + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, + 12)); // Packed DeclBits: HasStandaloneLexicalDC, + // isInvalidDecl, HasAttrs, isImplicit, isUsed, + // isReferenced, TopLevelDeclInObjCContainer, + // AccessSpecifier, ModuleOwnershipKind Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext - Abv->Add(BitCodeAbbrevOp(0)); // LexicalDeclContext - Abv->Add(BitCodeAbbrevOp( - BitCodeAbbrevOp::Fixed, - 11)); // Packed DeclBits: isInvalidDecl, HasAttrs, isImplicit, isUsed, - // isReferenced, TopLevelDeclInObjCContainer, AccessSpecifier, - // ModuleOwnershipKind Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID // NamedDecl Abv->Add(BitCodeAbbrevOp(0)); // NameKind = Identifier @@ -2164,11 +2162,11 @@ void ASTWriter::WriteDeclAbbrevs() { Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // IdentifierNamespace Abv->Add(BitCodeAbbrevOp( BitCodeAbbrevOp::Fixed, - 7)); // Packed Tag Decl Bits: getTagKind, isCompleteDefinition, - // EmbeddedInDeclarator, IsFreeStanding, isCompleteDefinitionRequired + 9)); // Packed Tag Decl Bits: getTagKind, isCompleteDefinition, + // EmbeddedInDeclarator, IsFreeStanding, + // isCompleteDefinitionRequired, ExtInfoKind Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SourceLocation Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SourceLocation - Abv->Add(BitCodeAbbrevOp(0)); // ExtInfoKind // RecordDecl Abv->Add(BitCodeAbbrevOp( BitCodeAbbrevOp::Fixed, @@ -2194,13 +2192,12 @@ void ASTWriter::WriteDeclAbbrevs() { // Redeclarable Abv->Add(BitCodeAbbrevOp(0)); // No redeclaration // Decl + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, + 12)); // Packed DeclBits: HasStandaloneLexicalDC, + // isInvalidDecl, HasAttrs, isImplicit, isUsed, + // isReferenced, TopLevelDeclInObjCContainer, + // AccessSpecifier, ModuleOwnershipKind Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext - Abv->Add(BitCodeAbbrevOp(0)); // LexicalDeclContext - Abv->Add(BitCodeAbbrevOp( - BitCodeAbbrevOp::Fixed, - 11)); // Packed DeclBits: isInvalidDecl, HasAttrs, isImplicit, isUsed, - // isReferenced, TopLevelDeclInObjCContainer, AccessSpecifier, - // ModuleOwnershipKind Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID // NamedDecl Abv->Add(BitCodeAbbrevOp(0)); // NameKind = Identifier @@ -2221,10 +2218,9 @@ void ASTWriter::WriteDeclAbbrevs() { // ParmVarDecl Abv->Add(BitCodeAbbrevOp( BitCodeAbbrevOp::Fixed, - 19)); // Packed Parm Var Decl bits: IsObjCMethodParameter, ScopeDepth, - // ScopeIndex, KNRPromoted, HasInheritedDefaultArg - Abv->Add(BitCodeAbbrevOp(0)); // ObjCDeclQualifier - Abv->Add(BitCodeAbbrevOp(0)); // HasUninstantiatedDefaultArg + 27)); // Packed Parm Var Decl bits: IsObjCMethodParameter, ScopeDepth, + // ScopeIndex, ObjCDeclQualifier, KNRPromoted, + // HasInheritedDefaultArg, HasUninstantiatedDefaultArg // Type Source Info Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TypeLoc @@ -2236,13 +2232,12 @@ void ASTWriter::WriteDeclAbbrevs() { // Redeclarable Abv->Add(BitCodeAbbrevOp(0)); // No redeclaration // Decl + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, + 12)); // Packed DeclBits: HasStandaloneLexicalDC, + // isInvalidDecl, HasAttrs, isImplicit, isUsed, + // isReferenced, TopLevelDeclInObjCContainer, + // AccessSpecifier, ModuleOwnershipKind Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext - Abv->Add(BitCodeAbbrevOp(0)); // LexicalDeclContext - Abv->Add(BitCodeAbbrevOp( - BitCodeAbbrevOp::Fixed, - 11)); // Packed DeclBits: isInvalidDecl, HasAttrs, isImplicit, isUsed, - // isReferenced, TopLevelDeclInObjCContainer, AccessSpecifier, - // ModuleOwnershipKind Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID // NamedDecl Abv->Add(BitCodeAbbrevOp(0)); // NameKind = Identifier @@ -2262,13 +2257,12 @@ void ASTWriter::WriteDeclAbbrevs() { // Redeclarable Abv->Add(BitCodeAbbrevOp(0)); // No redeclaration // Decl + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, + 12)); // Packed DeclBits: HasStandaloneLexicalDC, + // isInvalidDecl, HasAttrs, isImplicit, isUsed, + // isReferenced, TopLevelDeclInObjCContainer, + // AccessSpecifier, ModuleOwnershipKind Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext - Abv->Add(BitCodeAbbrevOp(0)); // LexicalDeclContext - Abv->Add(BitCodeAbbrevOp( - BitCodeAbbrevOp::Fixed, - 11)); // Packed DeclBits: isInvalidDecl, HasAttrs, isImplicit, isUsed, - // isReferenced, TopLevelDeclInObjCContainer, AccessSpecifier, - // ModuleOwnershipKind Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID // NamedDecl Abv->Add(BitCodeAbbrevOp(0)); // NameKind = Identifier @@ -2303,13 +2297,12 @@ void ASTWriter::WriteDeclAbbrevs() { // FIXME: Implement abbreviation for other template kinds. Abv->Add(BitCodeAbbrevOp(FunctionDecl::TK_NonTemplate)); // TemplateKind // Decl + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, + 12)); // Packed DeclBits: HasStandaloneLexicalDC, + // isInvalidDecl, HasAttrs, isImplicit, isUsed, + // isReferenced, TopLevelDeclInObjCContainer, + // AccessSpecifier, ModuleOwnershipKind Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext - Abv->Add(BitCodeAbbrevOp(0)); // LexicalDeclContext - Abv->Add(BitCodeAbbrevOp( - BitCodeAbbrevOp::Fixed, - 11)); // Packed DeclBits: isInvalidDecl, HasAttrs, isImplicit, isUsed, - // isReferenced, TopLevelDeclInObjCContainer, AccessSpecifier, - // ModuleOwnershipKind Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID // NamedDecl Abv->Add(BitCodeAbbrevOp(DeclarationName::Identifier)); // NameKind @@ -2346,16 +2339,14 @@ void ASTWriter::WriteDeclAbbrevs() { Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); DeclCXXMethodAbbrev = Stream.EmitAbbrev(std::move(Abv)); - unsigned ExprDependenceBits = llvm::BitWidth; // Abbreviation for EXPR_DECL_REF Abv = std::make_shared(); Abv->Add(BitCodeAbbrevOp(serialization::EXPR_DECL_REF)); //Stmt // Expr Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, ExprDependenceBits)); - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); //GetValueKind - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); //GetObjectKind + // DependenceKind, ValueKind, ObjectKind + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); //DeclRefExpr Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //HasQualifier Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //GetDeclFound @@ -2374,9 +2365,8 @@ void ASTWriter::WriteDeclAbbrevs() { //Stmt // Expr Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, ExprDependenceBits)); - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); //GetValueKind - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); //GetObjectKind + // DependenceKind, ValueKind, ObjectKind + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); //Integer Literal Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Location Abv->Add(BitCodeAbbrevOp(32)); // Bit Width @@ -2389,9 +2379,8 @@ void ASTWriter::WriteDeclAbbrevs() { //Stmt // Expr Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, ExprDependenceBits)); - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); //GetValueKind - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); //GetObjectKind + // DependenceKind, ValueKind, ObjectKind + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); //Character Literal Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // getValue Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Location @@ -2404,9 +2393,8 @@ void ASTWriter::WriteDeclAbbrevs() { // Stmt // Expr Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, ExprDependenceBits)); - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); //GetValueKind - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); //GetObjectKind + // DependenceKind, ValueKind, ObjectKind + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); // CastExpr Abv->Add(BitCodeAbbrevOp(0)); // PathSize Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // HasFPFeatures diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index 59be6828fafabf6ac17cbf155e1826dea560ac97..8524484ea8a0b98e559bdf0b20fb8d5f2fae4799 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -549,9 +549,14 @@ void ASTStmtWriter::VisitCapturedStmt(CapturedStmt *S) { void ASTStmtWriter::VisitExpr(Expr *E) { VisitStmt(E); Record.AddTypeRef(E->getType()); - Record.push_back(E->getDependence()); - Record.push_back(E->getValueKind()); - Record.push_back(E->getObjectKind()); + + BitsPacker ExprBits; + + ExprBits.addBits(E->getDependence(), /*BitsWidth=*/5); + ExprBits.addBits(E->getValueKind(), /*BitsWidth=*/2); + ExprBits.addBits(E->getObjectKind(), /*BitsWidth=*/3); + + Record.push_back(ExprBits); } void ASTStmtWriter::VisitConstantExpr(ConstantExpr *E) { @@ -866,14 +871,20 @@ void ASTStmtWriter::VisitOMPIteratorExpr(OMPIteratorExpr *E) { void ASTStmtWriter::VisitCallExpr(CallExpr *E) { VisitExpr(E); - Record.push_back(E->getNumArgs()); - Record.push_back(E->hasStoredFPFeatures()); + + BitsPacker CallExprBits; + // 16 bits should be sufficient to store the number args; + CallExprBits.addBits(E->getNumArgs(), /*BitsWidth=*/16); + CallExprBits.addBit(E->hasStoredFPFeatures()); + CallExprBits.addBit(static_cast(E->getADLCallKind())); + Record.push_back(CallExprBits); + Record.AddSourceLocation(E->getRParenLoc()); Record.AddStmt(E->getCallee()); for (CallExpr::arg_iterator Arg = E->arg_begin(), ArgEnd = E->arg_end(); Arg != ArgEnd; ++Arg) Record.AddStmt(*Arg); - Record.push_back(static_cast(E->getADLCallKind())); + if (E->hasStoredFPFeatures()) Record.push_back(E->getFPFeatures().getAsOpaqueInt()); Code = serialization::EXPR_CALL; @@ -1938,14 +1949,19 @@ ASTStmtWriter::VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *E) { void ASTStmtWriter::VisitOverloadExpr(OverloadExpr *E) { VisitExpr(E); - Record.push_back(E->getNumDecls()); - Record.push_back(E->hasTemplateKWAndArgsInfo()); + BitsPacker OverloadExprBits; + // 14 Bits should enough to store the number of decls. + OverloadExprBits.addBits(E->getNumDecls(), /*BitWidth=*/14); + OverloadExprBits.addBit(E->hasTemplateKWAndArgsInfo()); if (E->hasTemplateKWAndArgsInfo()) { const ASTTemplateKWAndArgsInfo &ArgInfo = *E->getTrailingASTTemplateKWAndArgsInfo(); - Record.push_back(ArgInfo.NumTemplateArgs); + // 14 Bits should enough to store the number of template args. + OverloadExprBits.addBits(ArgInfo.NumTemplateArgs, /*BitWidth=*/14); + Record.push_back(OverloadExprBits); AddTemplateKWAndArgsInfo(ArgInfo, E->getTrailingTemplateArgumentLoc()); - } + } else + Record.push_back(OverloadExprBits); for (OverloadExpr::decls_iterator OvI = E->decls_begin(), OvE = E->decls_end(); diff --git a/clang/lib/Serialization/GlobalModuleIndex.cpp b/clang/lib/Serialization/GlobalModuleIndex.cpp index fb80a1998d0efe90708dbcd7ca642c4f26cbec28..dd4fc3e009050f756b8a3df620d3d47053c095b1 100644 --- a/clang/lib/Serialization/GlobalModuleIndex.cpp +++ b/clang/lib/Serialization/GlobalModuleIndex.cpp @@ -342,8 +342,8 @@ bool GlobalModuleIndex::loadedModuleFile(ModuleFile *File) { // If the size and modification time match what we expected, record this // module file. bool Failed = true; - if (File->File->getSize() == Info.Size && - File->File->getModificationTime() == Info.ModTime) { + if (File->File.getSize() == Info.Size && + File->File.getModificationTime() == Info.ModTime) { Info.File = File; ModulesByFile[File] = Known->second; diff --git a/clang/lib/Serialization/ModuleManager.cpp b/clang/lib/Serialization/ModuleManager.cpp index de4cd3d05853ac0f31d27baf4ee046b16a97f9bf..51b6429412960efcc48fbfa846c80612a1391f49 100644 --- a/clang/lib/Serialization/ModuleManager.cpp +++ b/clang/lib/Serialization/ModuleManager.cpp @@ -52,8 +52,8 @@ ModuleFile *ModuleManager::lookupByFileName(StringRef Name) const { ModuleFile *ModuleManager::lookupByModuleName(StringRef Name) const { if (const Module *Mod = HeaderSearchInfo.getModuleMap().findModule(Name)) - if (const FileEntry *File = Mod->getASTFile()) - return lookup(File); + if (OptionalFileEntryRef File = Mod->getASTFile()) + return lookup(*File); return nullptr; } @@ -108,7 +108,7 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type, // Look for the file entry. This only fails if the expected size or // modification time differ. - OptionalFileEntryRefDegradesToFileEntryPtr Entry; + OptionalFileEntryRef Entry; if (Type == MK_ExplicitModule || Type == MK_PrebuiltModule) { // If we're not expecting to pull this file out of the module cache, it // might have a different mtime due to being moved across filesystems in @@ -123,7 +123,7 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type, return OutOfDate; } - if (!Entry && FileName != "-") { + if (!Entry) { ErrorStr = "module file not found"; return Missing; } @@ -150,7 +150,7 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type, }; // Check whether we already loaded this module, before - if (ModuleFile *ModuleEntry = Modules.lookup(Entry)) { + if (ModuleFile *ModuleEntry = Modules.lookup(*Entry)) { if (implicitModuleNamesMatch(Type, ModuleEntry, *Entry)) { // Check the stored signature. if (checkSignature(ModuleEntry->Signature, ExpectedSignature, ErrorStr)) @@ -163,10 +163,9 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type, } // Allocate a new module. - auto NewModule = std::make_unique(Type, Generation); + auto NewModule = std::make_unique(Type, *Entry, Generation); NewModule->Index = Chain.size(); NewModule->FileName = FileName.str(); - NewModule->File = Entry; NewModule->ImportLoc = ImportLoc; NewModule->InputFilesValidationTimestamp = 0; @@ -198,21 +197,15 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type, Entry->closeFile(); return OutOfDate; } else { - // Open the AST file. - llvm::ErrorOr> Buf((std::error_code())); - if (FileName == "-") { - Buf = llvm::MemoryBuffer::getSTDIN(); - } else { - // Get a buffer of the file and close the file descriptor when done. - // The file is volatile because in a parallel build we expect multiple - // compiler processes to use the same module file rebuilding it if needed. - // - // RequiresNullTerminator is false because module files don't need it, and - // this allows the file to still be mmapped. - Buf = FileMgr.getBufferForFile(*NewModule->File, - /*IsVolatile=*/true, - /*RequiresNullTerminator=*/false); - } + // Get a buffer of the file and close the file descriptor when done. + // The file is volatile because in a parallel build we expect multiple + // compiler processes to use the same module file rebuilding it if needed. + // + // RequiresNullTerminator is false because module files don't need it, and + // this allows the file to still be mmapped. + auto Buf = FileMgr.getBufferForFile(NewModule->File, + /*IsVolatile=*/true, + /*RequiresNullTerminator=*/false); if (!Buf) { ErrorStr = Buf.getError().message(); @@ -232,7 +225,7 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type, return OutOfDate; // We're keeping this module. Store it everywhere. - Module = Modules[Entry] = NewModule.get(); + Module = Modules[*Entry] = NewModule.get(); updateModuleImports(*NewModule, ImportedBy, ImportLoc); @@ -441,22 +434,19 @@ void ModuleManager::visit(llvm::function_ref Visitor, bool ModuleManager::lookupModuleFile(StringRef FileName, off_t ExpectedSize, time_t ExpectedModTime, OptionalFileEntryRef &File) { - File = std::nullopt; - if (FileName == "-") + if (FileName == "-") { + File = expectedToOptional(FileMgr.getSTDIN()); return false; + } // Open the file immediately to ensure there is no race between stat'ing and // opening the file. - OptionalFileEntryRef FileOrErr = - expectedToOptional(FileMgr.getFileRef(FileName, /*OpenFile=*/true, - /*CacheFailure=*/false)); - if (!FileOrErr) - return false; - - File = *FileOrErr; + File = FileMgr.getOptionalFileRef(FileName, /*OpenFile=*/true, + /*CacheFailure=*/false); - if ((ExpectedSize && ExpectedSize != File->getSize()) || - (ExpectedModTime && ExpectedModTime != File->getModificationTime())) + if (File && + ((ExpectedSize && ExpectedSize != File->getSize()) || + (ExpectedModTime && ExpectedModTime != File->getModificationTime()))) // Do not destroy File, as it may be referenced. If we need to rebuild it, // it will be destroyed by removeModules. return true; diff --git a/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp b/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp index ffc7236d1e2551a8aa7c79444a78fe746fcfe698..6c7a1601402efac74ed7009617e1cd9ff2409aad 100644 --- a/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "clang/AST/CharUnits.h" +#include "clang/AST/ParentMapContext.h" #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" #include "clang/StaticAnalyzer/Checkers/Taint.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" @@ -34,20 +35,46 @@ using llvm::formatv; namespace { enum OOB_Kind { OOB_Precedes, OOB_Exceeds, OOB_Taint }; -class ArrayBoundCheckerV2 : - public Checker { +struct Messages { + std::string Short, Full; +}; + +// NOTE: The `ArraySubscriptExpr` and `UnaryOperator` callbacks are `PostStmt` +// instead of `PreStmt` because the current implementation passes the whole +// expression to `CheckerContext::getSVal()` which only works after the +// symbolic evaluation of the expression. (To turn them into `PreStmt` +// callbacks, we'd need to duplicate the logic that evaluates these +// expressions.) The `MemberExpr` callback would work as `PreStmt` but it's +// defined as `PostStmt` for the sake of consistency with the other callbacks. +class ArrayBoundCheckerV2 : public Checker, + check::PostStmt, + check::PostStmt> { BugType BT{this, "Out-of-bound access"}; BugType TaintBT{this, "Out-of-bound access", categories::TaintedData}; + void performCheck(const Expr *E, CheckerContext &C) const; + void reportOOB(CheckerContext &C, ProgramStateRef ErrorState, OOB_Kind Kind, - NonLoc Offset, std::string RegName, std::string Msg) const; + NonLoc Offset, Messages Msgs) const; static bool isFromCtypeMacro(const Stmt *S, ASTContext &AC); + static bool isInAddressOf(const Stmt *S, ASTContext &AC); + public: - void checkLocation(SVal l, bool isLoad, const Stmt *S, - CheckerContext &C) const; + void checkPostStmt(const ArraySubscriptExpr *E, CheckerContext &C) const { + performCheck(E, C); + } + void checkPostStmt(const UnaryOperator *E, CheckerContext &C) const { + if (E->getOpcode() == UO_Deref) + performCheck(E, C); + } + void checkPostStmt(const MemberExpr *E, CheckerContext &C) const { + if (E->isArrow()) + performCheck(E->getBase(), C); + } }; + } // anonymous namespace /// For a given Location that can be represented as a symbolic expression @@ -149,9 +176,11 @@ getSimplifiedOffsets(NonLoc offset, nonloc::ConcreteInt extent, // where the first one corresponds to "value below threshold" and the second // corresponds to "value at or above threshold". Returns {nullptr, nullptr} in // the case when the evaluation fails. +// If the optional argument CheckEquality is true, then use BO_EQ instead of +// the default BO_LT after consistently applying the same simplification steps. static std::pair compareValueToThreshold(ProgramStateRef State, NonLoc Value, NonLoc Threshold, - SValBuilder &SVB) { + SValBuilder &SVB, bool CheckEquality = false) { if (auto ConcreteThreshold = Threshold.getAs()) { std::tie(Value, Threshold) = getSimplifiedOffsets(Value, *ConcreteThreshold, SVB); } @@ -167,8 +196,10 @@ compareValueToThreshold(ProgramStateRef State, NonLoc Value, NonLoc Threshold, return {nullptr, State}; } } + const BinaryOperatorKind OpKind = CheckEquality ? BO_EQ : BO_LT; auto BelowThreshold = - SVB.evalBinOpNN(State, BO_LT, Value, Threshold, SVB.getConditionType()).getAs(); + SVB.evalBinOpNN(State, OpKind, Value, Threshold, SVB.getConditionType()) + .getAs(); if (BelowThreshold) return State->assume(*BelowThreshold); @@ -217,16 +248,19 @@ static std::string getShortMsg(OOB_Kind Kind, std::string RegName) { return formatv(ShortMsgTemplates[Kind], RegName); } -static std::string getPrecedesMsg(std::string RegName, NonLoc Offset) { +static Messages getPrecedesMsgs(const SubRegion *Region, NonLoc Offset) { + std::string RegName = getRegionName(Region); SmallString<128> Buf; llvm::raw_svector_ostream Out(Buf); Out << "Access of " << RegName << " at negative byte offset"; if (auto ConcreteIdx = Offset.getAs()) Out << ' ' << ConcreteIdx->getValue(); - return std::string(Buf); + return {getShortMsg(OOB_Precedes, RegName), std::string(Buf)}; } -static std::string getExceedsMsg(ASTContext &ACtx, std::string RegName, - NonLoc Offset, NonLoc Extent, SVal Location) { + +static Messages getExceedsMsgs(ASTContext &ACtx, const SubRegion *Region, + NonLoc Offset, NonLoc Extent, SVal Location) { + std::string RegName = getRegionName(Region); const auto *EReg = Location.getAsRegion()->getAs(); assert(EReg && "this checker only handles element access"); QualType ElemType = EReg->getElementType(); @@ -273,20 +307,18 @@ static std::string getExceedsMsg(ASTContext &ACtx, std::string RegName, Out << "s"; } - return std::string(Buf); -} -static std::string getTaintMsg(std::string RegName) { - SmallString<128> Buf; - llvm::raw_svector_ostream Out(Buf); - Out << "Access of " << RegName - << " with a tainted offset that may be too large"; - return std::string(Buf); + return {getShortMsg(OOB_Exceeds, RegName), std::string(Buf)}; } -void ArrayBoundCheckerV2::checkLocation(SVal Location, bool IsLoad, - const Stmt *LoadS, - CheckerContext &C) const { +static Messages getTaintMsgs(const SubRegion *Region, const char *OffsetName) { + std::string RegName = getRegionName(Region); + return {formatv("Potential out of bound access to {0} with tainted {1}", + RegName, OffsetName), + formatv("Access of {0} with a tainted {1} that may be too large", + RegName, OffsetName)}; +} +void ArrayBoundCheckerV2::performCheck(const Expr *E, CheckerContext &C) const { // NOTE: Instead of using ProgramState::assumeInBound(), we are prototyping // some new logic here that reasons directly about memory region extents. // Once that logic is more mature, we can bring it back to assumeInBound() @@ -297,12 +329,14 @@ void ArrayBoundCheckerV2::checkLocation(SVal Location, bool IsLoad, // have some flexibility in defining the base region, we can achieve // various levels of conservatism in our buffer overflow checking. + const SVal Location = C.getSVal(E); + // The header ctype.h (from e.g. glibc) implements the isXXXXX() macros as // #define isXXXXX(arg) (LOOKUP_TABLE[arg] & BITMASK_FOR_XXXXX) // and incomplete analysis of these leads to false positives. As even // accurate reports would be confusing for the users, just disable reports // from these macros: - if (isFromCtypeMacro(LoadS, C.getASTContext())) + if (isFromCtypeMacro(E, C.getASTContext())) return; ProgramStateRef State = C.getState(); @@ -331,9 +365,8 @@ void ArrayBoundCheckerV2::checkLocation(SVal Location, bool IsLoad, if (PrecedesLowerBound && !WithinLowerBound) { // We know that the index definitely precedes the lower bound. - std::string RegName = getRegionName(Reg); - std::string Msg = getPrecedesMsg(RegName, ByteOffset); - reportOOB(C, PrecedesLowerBound, OOB_Precedes, ByteOffset, RegName, Msg); + Messages Msgs = getPrecedesMsgs(Reg, ByteOffset); + reportOOB(C, PrecedesLowerBound, OOB_Precedes, ByteOffset, Msgs); return; } @@ -350,17 +383,38 @@ void ArrayBoundCheckerV2::checkLocation(SVal Location, bool IsLoad, if (ExceedsUpperBound) { if (!WithinUpperBound) { // We know that the index definitely exceeds the upper bound. - std::string RegName = getRegionName(Reg); - std::string Msg = getExceedsMsg(C.getASTContext(), RegName, ByteOffset, - *KnownSize, Location); - reportOOB(C, ExceedsUpperBound, OOB_Exceeds, ByteOffset, RegName, Msg); + if (isa(E) && isInAddressOf(E, C.getASTContext())) { + // ...but this is within an addressof expression, so we need to check + // for the exceptional case that `&array[size]` is valid. + auto [EqualsToThreshold, NotEqualToThreshold] = + compareValueToThreshold(ExceedsUpperBound, ByteOffset, *KnownSize, + SVB, /*CheckEquality=*/true); + if (EqualsToThreshold && !NotEqualToThreshold) { + // We are definitely in the exceptional case, so return early + // instead of reporting a bug. + C.addTransition(EqualsToThreshold); + return; + } + } + Messages Msgs = getExceedsMsgs(C.getASTContext(), Reg, ByteOffset, + *KnownSize, Location); + reportOOB(C, ExceedsUpperBound, OOB_Exceeds, ByteOffset, Msgs); return; } if (isTainted(State, ByteOffset)) { - // Both cases are possible, but the index is tainted, so report. + // Both cases are possible, but the offset is tainted, so report. std::string RegName = getRegionName(Reg); - std::string Msg = getTaintMsg(RegName); - reportOOB(C, ExceedsUpperBound, OOB_Taint, ByteOffset, RegName, Msg); + + // Diagnostic detail: "tainted offset" is always correct, but the + // common case is that 'idx' is tainted in 'arr[idx]' and then it's + // nicer to say "tainted index". + const char *OffsetName = "offset"; + if (const auto *ASE = dyn_cast(E)) + if (isTainted(State, ASE->getIdx(), C.getLocationContext())) + OffsetName = "index"; + + Messages Msgs = getTaintMsgs(Reg, OffsetName); + reportOOB(C, ExceedsUpperBound, OOB_Taint, ByteOffset, Msgs); return; } } @@ -374,17 +428,14 @@ void ArrayBoundCheckerV2::checkLocation(SVal Location, bool IsLoad, void ArrayBoundCheckerV2::reportOOB(CheckerContext &C, ProgramStateRef ErrorState, OOB_Kind Kind, - NonLoc Offset, std::string RegName, - std::string Msg) const { + NonLoc Offset, Messages Msgs) const { ExplodedNode *ErrorNode = C.generateErrorNode(ErrorState); if (!ErrorNode) return; - std::string ShortMsg = getShortMsg(Kind, RegName); - auto BR = std::make_unique( - Kind == OOB_Taint ? TaintBT : BT, ShortMsg, Msg, ErrorNode); + Kind == OOB_Taint ? TaintBT : BT, Msgs.Short, Msgs.Full, ErrorNode); // Track back the propagation of taintedness. if (Kind == OOB_Taint) @@ -413,6 +464,18 @@ bool ArrayBoundCheckerV2::isFromCtypeMacro(const Stmt *S, ASTContext &ACtx) { (MacroName == "isupper") || (MacroName == "isxdigit")); } +bool ArrayBoundCheckerV2::isInAddressOf(const Stmt *S, ASTContext &ACtx) { + ParentMapContext &ParentCtx = ACtx.getParentMapContext(); + do { + const DynTypedNodeList Parents = ParentCtx.getParents(*S); + if (Parents.empty()) + return false; + S = Parents[0].get(); + } while (isa_and_nonnull(S)); + const auto *UnaryOp = dyn_cast_or_null(S); + return UnaryOp && UnaryOp->getOpcode() == UO_AddrOf; +} + void ento::registerArrayBoundCheckerV2(CheckerManager &mgr) { mgr.registerChecker(); } diff --git a/clang/lib/StaticAnalyzer/Checkers/BitwiseShiftChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/BitwiseShiftChecker.cpp index d4aa9fa1339f47cacd307e01f8a61e30fa254807..339927c165fe000ff1078c4bb8b907e61bc341e9 100644 --- a/clang/lib/StaticAnalyzer/Checkers/BitwiseShiftChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/BitwiseShiftChecker.cpp @@ -344,7 +344,7 @@ BitwiseShiftValidator::createBugReport(StringRef ShortMsg, StringRef Msg) const } // anonymous namespace class BitwiseShiftChecker : public Checker> { - mutable std::unique_ptr BTPtr; + BugType BT{this, "Bitwise shift", "Suspicious operation"}; public: void checkPreStmt(const BinaryOperator *B, CheckerContext &Ctx) const { @@ -353,11 +353,7 @@ public: if (Op != BO_Shl && Op != BO_Shr) return; - if (!BTPtr) - BTPtr = std::make_unique(this, "Bitwise shift", - "Suspicious operation"); - - BitwiseShiftValidator(B, Ctx, *BTPtr, Pedantic).run(); + BitwiseShiftValidator(B, Ctx, BT, Pedantic).run(); } bool Pedantic = false; diff --git a/clang/lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp index 5844f4399100183cc224688f3560ee6596581b87..7c51673422a0a2b2ddbbdc8303e3bda09b56ed36 100644 --- a/clang/lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp @@ -22,10 +22,12 @@ #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" +#include "llvm/Support/FormatVariadic.h" #include using namespace clang; using namespace ento; +using llvm::formatv; namespace { // This evaluator checks two SVals for equality. The first SVal is provided via @@ -87,17 +89,22 @@ void EnumCastOutOfRangeChecker::reportWarning(CheckerContext &C, EnumValueCastOutOfRange.reset( new BugType(this, "Enum cast out of range")); - llvm::SmallString<128> Msg{"The value provided to the cast expression is " - "not in the valid range of values for "}; - StringRef EnumName{E->getName()}; - if (EnumName.empty()) { - Msg += "the enum"; - } else { - Msg += '\''; - Msg += EnumName; - Msg += '\''; + std::string ValueStr = "", NameStr = "the enum"; + + // Try to add details to the message: + const auto ConcreteValue = + C.getSVal(CE->getSubExpr()).getAs(); + if (ConcreteValue) { + ValueStr = formatv(" '{0}'", ConcreteValue->getValue()); + } + if (StringRef EnumName{E->getName()}; !EnumName.empty()) { + NameStr = formatv("'{0}'", EnumName); } + std::string Msg = formatv("The value{0} provided to the cast expression is " + "not in the valid range of values for {1}", + ValueStr, NameStr); + auto BR = std::make_unique(*EnumValueCastOutOfRange, Msg, N); bugreporter::trackExpressionValue(N, CE->getSubExpr(), *BR); @@ -152,6 +159,9 @@ void EnumCastOutOfRangeChecker::checkPreStmt(const CastExpr *CE, // Every initialization an enum with a fixed underlying type but without any // enumerators would produce a warning if we were to continue at this point. // The most notable example is std::byte in the C++17 standard library. + // TODO: Create heuristics to bail out when the enum type is intended to be + // used to store combinations of flag values (to mitigate the limitation + // described in the docs). if (DeclValues.size() == 0) return; diff --git a/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp index a4799b5f762caee2957d9ade00bfbaff85e75d0d..925fc90e355431778894e2ee0aa717a4a6e87002 100644 --- a/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp @@ -1072,6 +1072,9 @@ void StreamChecker::evalFtell(const FnDescription *Desc, const CallEvent &Call, ProgramStateRef StateFailed = State->BindExpr( CE, C.getLocationContext(), SVB.makeIntVal(-1, C.getASTContext().LongTy)); + // This function does not affect the stream state. + // Still we add success and failure state with the appropriate return value. + // StdLibraryFunctionsChecker can change these states (set the 'errno' state). C.addTransition(StateNotFailed); C.addTransition(StateFailed); } diff --git a/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp b/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp index 1058ddb8254cde9246e855a27bef64bd69643a09..f65da413bb87c35d46ceb76d5daf1d085d7d27d7 100644 --- a/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp +++ b/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp @@ -521,7 +521,7 @@ ModuleDepCollectorPP::handleTopLevelModule(const Module *M) { serialization::ModuleFile *MF = MDC.ScanInstance.getASTReader()->getModuleManager().lookup( - M->getASTFile()); + *M->getASTFile()); MDC.ScanInstance.getASTReader()->visitInputFileInfos( *MF, /*IncludeSystem=*/true, [&](const serialization::InputFileInfo &IFI, bool IsSystem) { diff --git a/clang/test/AST/HLSL/RWBuffer-AST.hlsl b/clang/test/AST/HLSL/RWBuffer-AST.hlsl index 9dd9244b73eedf3443a9af9666bead19c60fabf9..c1613520a146c8c4efbb7a084b7049fabf9c08a3 100644 --- a/clang/test/AST/HLSL/RWBuffer-AST.hlsl +++ b/clang/test/AST/HLSL/RWBuffer-AST.hlsl @@ -13,8 +13,6 @@ // EMPTY: ClassTemplateDecl 0x{{[0-9A-Fa-f]+}} <> implicit RWBuffer // EMPTY-NEXT: TemplateTypeParmDecl 0x{{[0-9A-Fa-f]+}} <> class depth 0 index 0 element_type -// EMPTY-NEXT: TemplateArgument type 'float' -// EMPTY-NEXT: BuiltinType 0x{{[0-9A-Fa-f]+}} 'float' // EMPTY-NEXT: CXXRecordDecl 0x{{[0-9A-Fa-f]+}} <> implicit class RWBuffer // EMPTY-NEXT: FinalAttr 0x{{[0-9A-Fa-f]+}} <> Implicit final @@ -33,8 +31,6 @@ RWBuffer Buffer; // CHECK: ClassTemplateDecl 0x{{[0-9A-Fa-f]+}} <> implicit RWBuffer // CHECK-NEXT: TemplateTypeParmDecl 0x{{[0-9A-Fa-f]+}} <> class depth 0 index 0 element_type -// CHECK-NEXT: TemplateArgument type 'float' -// CHECK-NEXT: BuiltinType 0x{{[0-9A-Fa-f]+}} 'float' // CHECK-NEXT: CXXRecordDecl 0x{{[0-9A-Fa-f]+}} <> implicit class RWBuffer definition // CHECK: FinalAttr 0x{{[0-9A-Fa-f]+}} <> Implicit final diff --git a/clang/test/AST/HLSL/pch.hlsl b/clang/test/AST/HLSL/pch.hlsl index 74254fedf27cb5bc1b4106c82e9c472325d47262..27fae8f499daac737e0c59d542a1cdf5293aeabc 100644 --- a/clang/test/AST/HLSL/pch.hlsl +++ b/clang/test/AST/HLSL/pch.hlsl @@ -6,7 +6,7 @@ // Make sure PCH works by using function declared in PCH header and declare a RWBuffer in current file. // CHECK:FunctionDecl 0x[[FOO:[0-9a-f]+]] <{{.*}}:2:1, line:4:1> line:2:8 imported used foo 'float2 (float2, float2)' -// CHECK:VarDecl 0x{{[0-9a-f]+}} <{{.*}}:10:1, col:23> col:23 Buffer 'hlsl::RWBuffer':'hlsl::RWBuffer<>' +// CHECK:VarDecl 0x{{[0-9a-f]+}} <{{.*}}:10:1, col:23> col:23 Buffer 'hlsl::RWBuffer' hlsl::RWBuffer Buffer; float2 bar(float2 a, float2 b) { diff --git a/clang/test/AST/HLSL/pch_with_buf.hlsl b/clang/test/AST/HLSL/pch_with_buf.hlsl index 4e657606cbcb124ec727b294e2baa4e8a3d06f85..e8eae533af6294046dd3df8c3f074b72f9f035e7 100644 --- a/clang/test/AST/HLSL/pch_with_buf.hlsl +++ b/clang/test/AST/HLSL/pch_with_buf.hlsl @@ -5,9 +5,9 @@ // Make sure PCH works by using function declared in PCH header. // CHECK:FunctionDecl 0x[[FOO:[0-9a-f]+]] <{{.*}}:2:1, line:4:1> line:2:8 imported used foo 'float2 (float2, float2)' // Make sure buffer defined in PCH works. -// CHECK:VarDecl 0x{{[0-9a-f]+}} col:17 imported Buf 'RWBuffer':'hlsl::RWBuffer<>' +// CHECK:VarDecl 0x{{[0-9a-f]+}} col:17 imported Buf 'RWBuffer' // Make sure declare a RWBuffer in current file works. -// CHECK:VarDecl 0x{{[0-9a-f]+}} <{{.*}}:11:1, col:23> col:23 Buf2 'hlsl::RWBuffer':'hlsl::RWBuffer<>' +// CHECK:VarDecl 0x{{[0-9a-f]+}} <{{.*}}:11:1, col:23> col:23 Buf2 'hlsl::RWBuffer' hlsl::RWBuffer Buf2; float2 bar(float2 a, float2 b) { diff --git a/clang/test/AST/HLSL/resource_binding_attr.hlsl b/clang/test/AST/HLSL/resource_binding_attr.hlsl index 6836071971111eafe1db21ddf295b4a514ed63d6..71900f2dbda5503ef2c4fe5fc579faeddd5dca83 100644 --- a/clang/test/AST/HLSL/resource_binding_attr.hlsl +++ b/clang/test/AST/HLSL/resource_binding_attr.hlsl @@ -23,15 +23,15 @@ float foo() { return a + b; } -// CHECK: VarDecl 0x{{[0-9a-f]+}} <{{.*}}> col:17 UAV 'RWBuffer':'hlsl::RWBuffer<>' callinit -// CHECK-NEXT:-CXXConstructExpr 0x{{[0-9a-f]+}} 'RWBuffer':'hlsl::RWBuffer<>' 'void ()' +// CHECK: VarDecl 0x{{[0-9a-f]+}} <{{.*}}> col:17 UAV 'RWBuffer':'hlsl::RWBuffer' callinit +// CHECK-NEXT:-CXXConstructExpr 0x{{[0-9a-f]+}} 'RWBuffer':'hlsl::RWBuffer' 'void ()' // CHECK-NEXT:-HLSLResourceBindingAttr 0x{{[0-9a-f]+}} "u3" "space0" RWBuffer UAV : register(u3); -// CHECK: -VarDecl 0x{{[0-9a-f]+}} <{{.*}}> col:17 UAV1 'RWBuffer':'hlsl::RWBuffer<>' callinit -// CHECK-NEXT:-CXXConstructExpr 0x{{[0-9a-f]+}} 'RWBuffer':'hlsl::RWBuffer<>' 'void ()' +// CHECK: -VarDecl 0x{{[0-9a-f]+}} <{{.*}}> col:17 UAV1 'RWBuffer':'hlsl::RWBuffer' callinit +// CHECK-NEXT:-CXXConstructExpr 0x{{[0-9a-f]+}} 'RWBuffer':'hlsl::RWBuffer' 'void ()' // CHECK-NEXT:-HLSLResourceBindingAttr 0x{{[0-9a-f]+}} "u2" "space0" -// CHECK-NEXT:-VarDecl 0x{{[0-9a-f]+}} col:38 UAV2 'RWBuffer':'hlsl::RWBuffer<>' callinit -// CHECK-NEXT:-CXXConstructExpr 0x{{[0-9a-f]+}} 'RWBuffer':'hlsl::RWBuffer<>' 'void ()' +// CHECK-NEXT:-VarDecl 0x{{[0-9a-f]+}} col:38 UAV2 'RWBuffer':'hlsl::RWBuffer' callinit +// CHECK-NEXT:-CXXConstructExpr 0x{{[0-9a-f]+}} 'RWBuffer':'hlsl::RWBuffer' 'void ()' // CHECK-NEXT:-HLSLResourceBindingAttr 0x{{[0-9a-f]+}} "u4" "space0" RWBuffer UAV1 : register(u2), UAV2 : register(u4); diff --git a/clang/test/AST/Interp/arrays.cpp b/clang/test/AST/Interp/arrays.cpp index 34e0086fb9ee8ca731fde2f94256d6c80b61ca2f..c455731e76699ffca179adae6f2eee2b05d39edc 100644 --- a/clang/test/AST/Interp/arrays.cpp +++ b/clang/test/AST/Interp/arrays.cpp @@ -27,6 +27,10 @@ static_assert(foo[2][3] == &m, ""); static_assert(foo[2][4] == nullptr, ""); +constexpr int SomeInt[] = {1}; +constexpr int getSomeInt() { return *SomeInt; } +static_assert(getSomeInt() == 1, ""); + /// A init list for a primitive value. constexpr int f{5}; static_assert(f == 5, ""); diff --git a/clang/test/AST/Interp/builtin-functions.cpp b/clang/test/AST/Interp/builtin-functions.cpp index 0726dab37cb4eb0ea3df8b8a364eda98704fa32a..ce7c8bd357908b2b0862cccdf77bc279526a8359 100644 --- a/clang/test/AST/Interp/builtin-functions.cpp +++ b/clang/test/AST/Interp/builtin-functions.cpp @@ -331,3 +331,35 @@ namespace bitreverse { char bitreverse3[__builtin_bitreverse32(0x12345678) == 0x1E6A2C48 ? 1 : -1]; char bitreverse4[__builtin_bitreverse64(0x0123456789ABCDEFULL) == 0xF7B3D591E6A2C480 ? 1 : -1]; } + +namespace expect { + constexpr int a() { + return 12; + } + static_assert(__builtin_expect(a(),1) == 12, ""); + static_assert(__builtin_expect_with_probability(a(), 1, 1.0) == 12, ""); +} + +namespace rotateleft { + char rotateleft1[__builtin_rotateleft8(0x01, 5) == 0x20 ? 1 : -1]; + char rotateleft2[__builtin_rotateleft16(0x3210, 11) == 0x8190 ? 1 : -1]; + char rotateleft3[__builtin_rotateleft32(0x76543210, 22) == 0x841D950C ? 1 : -1]; + char rotateleft4[__builtin_rotateleft64(0xFEDCBA9876543210ULL, 55) == 0x87F6E5D4C3B2A19ULL ? 1 : -1]; +} + +namespace rotateright { + char rotateright1[__builtin_rotateright8(0x01, 5) == 0x08 ? 1 : -1]; + char rotateright2[__builtin_rotateright16(0x3210, 11) == 0x4206 ? 1 : -1]; + char rotateright3[__builtin_rotateright32(0x76543210, 22) == 0x50C841D9 ? 1 : -1]; + char rotateright4[__builtin_rotateright64(0xFEDCBA9876543210ULL, 55) == 0xB97530ECA86421FDULL ? 1 : -1]; +} + +namespace ffs { + char ffs1[__builtin_ffs(0) == 0 ? 1 : -1]; + char ffs2[__builtin_ffs(1) == 1 ? 1 : -1]; + char ffs3[__builtin_ffs(0xfbe71) == 1 ? 1 : -1]; + char ffs4[__builtin_ffs(0xfbe70) == 5 ? 1 : -1]; + char ffs5[__builtin_ffs(1U << (BITSIZE(int) - 1)) == BITSIZE(int) ? 1 : -1]; + char ffs6[__builtin_ffsl(0x10L) == 5 ? 1 : -1]; + char ffs7[__builtin_ffsll(0x100LL) == 9 ? 1 : -1]; +} diff --git a/clang/test/AST/Interp/cxx23.cpp b/clang/test/AST/Interp/cxx23.cpp index e284a66626fb331f69fc84298fe9326c78c8e8db..bd1cf186d519c55c5a5210ba3bac891248029496 100644 --- a/clang/test/AST/Interp/cxx23.cpp +++ b/clang/test/AST/Interp/cxx23.cpp @@ -4,9 +4,6 @@ // RUN: %clang_cc1 -std=c++23 -fsyntax-only -fcxx-exceptions -verify=expected23 %s -fexperimental-new-constant-interpreter -// expected23-no-diagnostics - - /// FIXME: The new interpreter is missing all the 'control flows through...' diagnostics. constexpr int f(int n) { // ref20-error {{constexpr function never produces a constant expression}} \ @@ -82,3 +79,27 @@ constexpr int k(int n) { return m; } constexpr int k0 = k(0); + +namespace StaticLambdas { + constexpr auto static_capture_constexpr() { + char n = 'n'; + return [n] static { return n; }(); // expected23-error {{a static lambda cannot have any captures}} \ + // expected20-error {{a static lambda cannot have any captures}} \ + // expected20-warning {{are a C++23 extension}} \ + // expected20-warning {{is a C++23 extension}} \ + // ref23-error {{a static lambda cannot have any captures}} \ + // ref20-error {{a static lambda cannot have any captures}} \ + // ref20-warning {{are a C++23 extension}} \ + // ref20-warning {{is a C++23 extension}} + } + static_assert(static_capture_constexpr()); // expected23-error {{static assertion expression is not an integral constant expression}} \ + // expected20-error {{static assertion expression is not an integral constant expression}} \ + // ref23-error {{static assertion expression is not an integral constant expression}} \ + // ref20-error {{static assertion expression is not an integral constant expression}} + + constexpr auto capture_constexpr() { + char n = 'n'; + return [n] { return n; }(); + } + static_assert(capture_constexpr()); +} diff --git a/clang/test/AST/Interp/floats.cpp b/clang/test/AST/Interp/floats.cpp index e17167f5bf6dbbf66da24ec3edd3704fded2c4d1..45c31c759e47fc6e33d6d44f4e5203ec110213ac 100644 --- a/clang/test/AST/Interp/floats.cpp +++ b/clang/test/AST/Interp/floats.cpp @@ -39,6 +39,10 @@ constexpr float m = 5.0f / 0.0f; // ref-error {{must be initialized by a constan static_assert(~2.0f == 3, ""); // ref-error {{invalid argument type 'float' to unary expression}} \ // expected-error {{invalid argument type 'float' to unary expression}} + +typedef int tdb[(long long)4e20]; //expected-error {{variable length}} \ + //ref-error {{variable length}} + /// Initialized by a double. constexpr float df = 0.0; /// The other way around. diff --git a/clang/test/AST/Interp/intap.cpp b/clang/test/AST/Interp/intap.cpp index c93ec331296647b0e9c5fec4f534a427abe8c3ae..b99422dc8f93125a6d04237f6b90b4755f020127 100644 --- a/clang/test/AST/Interp/intap.cpp +++ b/clang/test/AST/Interp/intap.cpp @@ -57,9 +57,25 @@ namespace APCast { } #ifdef __SIZEOF_INT128__ +typedef __int128 int128_t; +typedef unsigned __int128 uint128_t; +static const __uint128_t UINT128_MAX =__uint128_t(__int128_t(-1L)); +static_assert(UINT128_MAX == -1, ""); +static_assert(UINT128_MAX == 1, ""); // expected-error {{static assertion failed}} \ + // expected-note {{'340282366920938463463374607431768211455 == 1'}} \ + // ref-error {{static assertion failed}} \ + // ref-note {{'340282366920938463463374607431768211455 == 1'}} + +static const __int128_t INT128_MAX = UINT128_MAX >> (__int128_t)1; +static_assert(INT128_MAX != 0, ""); +static_assert(INT128_MAX == 0, ""); // expected-error {{failed}} \ + // expected-note {{evaluates to '170141183460469231731687303715884105727 == 0'}} \ + // ref-error {{failed}} \ + // ref-note {{evaluates to '170141183460469231731687303715884105727 == 0'}} +static const __int128_t INT128_MIN = -INT128_MAX - 1; + namespace i128 { - typedef __int128 int128_t; - typedef unsigned __int128 uint128_t; + constexpr int128_t I128_1 = 12; static_assert(I128_1 == 12, ""); static_assert(I128_1 != 10, ""); @@ -200,4 +216,50 @@ namespace BitOps { static_assert((Max ^ UZero) == Max, ""); } +namespace IncDec { +#if __cplusplus >= 201402L + constexpr int128_t maxPlus1(bool Pre) { + int128_t a = INT128_MAX; + + if (Pre) + ++a; // ref-note {{value 170141183460469231731687303715884105728 is outside the range}} \ + // expected-note {{value 170141183460469231731687303715884105728 is outside the range}} + else + a++; // ref-note {{value 170141183460469231731687303715884105728 is outside the range}} \ + // expected-note {{value 170141183460469231731687303715884105728 is outside the range}} + return a; + } + static_assert(maxPlus1(true) == 0, ""); // ref-error {{not an integral constant expression}} \ + // ref-note {{in call to}} \ + // expected-error {{not an integral constant expression}} \ + // expected-note {{in call to}} + static_assert(maxPlus1(false) == 0, ""); // ref-error {{not an integral constant expression}} \ + // ref-note {{in call to}} \ + // expected-error {{not an integral constant expression}} \ + // expected-note {{in call to}} + + constexpr int128_t inc1(bool Pre) { + int128_t A = 0; + if (Pre) + ++A; + else + A++; + return A; + } + static_assert(inc1(true) == 1, ""); + static_assert(inc1(false) == 1, ""); + + constexpr int128_t dec1(bool Pre) { + int128_t A = 2; + if (Pre) + --A; + else + A--; + return A; + } + static_assert(dec1(true) == 1, ""); + static_assert(dec1(false) == 1, ""); +#endif +} + #endif diff --git a/clang/test/AST/ms-constexpr.cpp b/clang/test/AST/ms-constexpr.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e85af8494f3344a0ac42641ede76f1cd28551bb1 --- /dev/null +++ b/clang/test/AST/ms-constexpr.cpp @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -fms-compatibility -fms-compatibility-version=19.33 -std=c++20 -ast-dump -verify %s | FileCheck %s +// expected-no-diagnostics + +// CHECK: used f1 'bool ()' +// CHECK: MSConstexprAttr 0x{{[0-9a-f]+}} +[[msvc::constexpr]] bool f1() { return true; } + +// CHECK: used constexpr f2 'bool ()' +// CHECK-NEXT: CompoundStmt 0x{{[0-9a-f]+}} +// CHECK-NEXT: AttributedStmt 0x{{[0-9a-f]+}} +// CHECK-NEXT: MSConstexprAttr 0x{{[0-9a-f]+}} +// CHECK-NEXT: ReturnStmt 0x{{[0-9a-f]+}} +constexpr bool f2() { [[msvc::constexpr]] return f1(); } +static_assert(f2()); + +struct S1 { + // CHECK: used vm 'bool ()' virtual + // CHECK: MSConstexprAttr 0x{{[0-9a-f]+}} + [[msvc::constexpr]] virtual bool vm() { return true; } + + // CHECK: used constexpr cm 'bool ()' + // CHECK-NEXT: CompoundStmt 0x{{[0-9a-f]+}} + // CHECK-NEXT: AttributedStmt 0x{{[0-9a-f]+}} + // CHECK-NEXT: MSConstexprAttr 0x{{[0-9a-f]+}} + // CHECK-NEXT: ReturnStmt 0x{{[0-9a-f]+}} + constexpr bool cm() { [[msvc::constexpr]] return vm(); } +}; +static_assert(S1{}.cm()); diff --git a/clang/test/Analysis/enum-cast-out-of-range.c b/clang/test/Analysis/enum-cast-out-of-range.c index 4e5c9bb9ffdec41e1cdd823e45e8e463fdb3edc8..a6eef92f418d165237f7a1cc9d3ee33585c3d1bd 100644 --- a/clang/test/Analysis/enum-cast-out-of-range.c +++ b/clang/test/Analysis/enum-cast-out-of-range.c @@ -1,5 +1,5 @@ // RUN: %clang_analyze_cc1 \ -// RUN: -analyzer-checker=core,alpha.cplusplus.EnumCastOutOfRange \ +// RUN: -analyzer-checker=core,optin.core.EnumCastOutOfRange \ // RUN: -analyzer-output text \ // RUN: -verify %s diff --git a/clang/test/Analysis/enum-cast-out-of-range.cpp b/clang/test/Analysis/enum-cast-out-of-range.cpp index 0eb740664ecdc7c8009ef0b04a8214036794e7bd..a5ac4f3fd056705cbc4b1f32a6d1c394e068f127 100644 --- a/clang/test/Analysis/enum-cast-out-of-range.cpp +++ b/clang/test/Analysis/enum-cast-out-of-range.cpp @@ -1,5 +1,5 @@ // RUN: %clang_analyze_cc1 \ -// RUN: -analyzer-checker=core,alpha.cplusplus.EnumCastOutOfRange \ +// RUN: -analyzer-checker=core,optin.core.EnumCastOutOfRange \ // RUN: -std=c++11 -verify %s // expected-note@+1 + {{enum declared here}} @@ -43,115 +43,115 @@ struct S { }; void unscopedUnspecified() { - unscoped_unspecified_t InvalidBeforeRangeBegin = static_cast(-5); // expected-warning {{The value provided to the cast expression is not in the valid range of values for 'unscoped_unspecified_t'}} + unscoped_unspecified_t InvalidBeforeRangeBegin = static_cast(-5); // expected-warning {{The value '-5' provided to the cast expression is not in the valid range of values for 'unscoped_unspecified_t'}} unscoped_unspecified_t ValidNegativeValue1 = static_cast(-4); // OK. unscoped_unspecified_t ValidNegativeValue2 = static_cast(-3); // OK. - unscoped_unspecified_t InvalidInsideRange1 = static_cast(-2); // expected-warning {{The value provided to the cast expression is not in the valid range of values for 'unscoped_unspecified_t'}} - unscoped_unspecified_t InvalidInsideRange2 = static_cast(-1); // expected-warning {{The value provided to the cast expression is not in the valid range of values for 'unscoped_unspecified_t'}} - unscoped_unspecified_t InvalidInsideRange3 = static_cast(0); // expected-warning {{The value provided to the cast expression is not in the valid range of values for 'unscoped_unspecified_t'}} + unscoped_unspecified_t InvalidInsideRange1 = static_cast(-2); // expected-warning {{The value '-2' provided to the cast expression is not in the valid range of values for 'unscoped_unspecified_t'}} + unscoped_unspecified_t InvalidInsideRange2 = static_cast(-1); // expected-warning {{The value '-1' provided to the cast expression is not in the valid range of values for 'unscoped_unspecified_t'}} + unscoped_unspecified_t InvalidInsideRange3 = static_cast(0); // expected-warning {{The value '0' provided to the cast expression is not in the valid range of values for 'unscoped_unspecified_t'}} unscoped_unspecified_t ValidPositiveValue1 = static_cast(1); // OK. unscoped_unspecified_t ValidPositiveValue2 = static_cast(2); // OK. - unscoped_unspecified_t InvalidInsideRange4 = static_cast(3); // expected-warning {{The value provided to the cast expression is not in the valid range of values for 'unscoped_unspecified_t'}} + unscoped_unspecified_t InvalidInsideRange4 = static_cast(3); // expected-warning {{The value '3' provided to the cast expression is not in the valid range of values for 'unscoped_unspecified_t'}} unscoped_unspecified_t ValidPositiveValue3 = static_cast(4); // OK. - unscoped_unspecified_t InvalidAfterRangeEnd = static_cast(5); // expected-warning {{The value provided to the cast expression is not in the valid range of values for 'unscoped_unspecified_t'}} + unscoped_unspecified_t InvalidAfterRangeEnd = static_cast(5); // expected-warning {{The value '5' provided to the cast expression is not in the valid range of values for 'unscoped_unspecified_t'}} } void unscopedSpecified() { - unscoped_specified_t InvalidBeforeRangeBegin = static_cast(-5); // expected-warning {{The value provided to the cast expression is not in the valid range of values for 'unscoped_specified_t'}} + unscoped_specified_t InvalidBeforeRangeBegin = static_cast(-5); // expected-warning {{The value '-5' provided to the cast expression is not in the valid range of values for 'unscoped_specified_t'}} unscoped_specified_t ValidNegativeValue1 = static_cast(-4); // OK. unscoped_specified_t ValidNegativeValue2 = static_cast(-3); // OK. - unscoped_specified_t InvalidInsideRange1 = static_cast(-2); // expected-warning {{The value provided to the cast expression is not in the valid range of values for 'unscoped_specified_t'}} - unscoped_specified_t InvalidInsideRange2 = static_cast(-1); // expected-warning {{The value provided to the cast expression is not in the valid range of values for 'unscoped_specified_t'}} - unscoped_specified_t InvalidInsideRange3 = static_cast(0); // expected-warning {{The value provided to the cast expression is not in the valid range of values for 'unscoped_specified_t'}} + unscoped_specified_t InvalidInsideRange1 = static_cast(-2); // expected-warning {{The value '-2' provided to the cast expression is not in the valid range of values for 'unscoped_specified_t'}} + unscoped_specified_t InvalidInsideRange2 = static_cast(-1); // expected-warning {{The value '-1' provided to the cast expression is not in the valid range of values for 'unscoped_specified_t'}} + unscoped_specified_t InvalidInsideRange3 = static_cast(0); // expected-warning {{The value '0' provided to the cast expression is not in the valid range of values for 'unscoped_specified_t'}} unscoped_specified_t ValidPositiveValue1 = static_cast(1); // OK. unscoped_specified_t ValidPositiveValue2 = static_cast(2); // OK. - unscoped_specified_t InvalidInsideRange4 = static_cast(3); // expected-warning {{The value provided to the cast expression is not in the valid range of values for 'unscoped_specified_t'}} + unscoped_specified_t InvalidInsideRange4 = static_cast(3); // expected-warning {{The value '3' provided to the cast expression is not in the valid range of values for 'unscoped_specified_t'}} unscoped_specified_t ValidPositiveValue3 = static_cast(4); // OK. - unscoped_specified_t InvalidAfterRangeEnd = static_cast(5); // expected-warning {{The value provided to the cast expression is not in the valid range of values for 'unscoped_specified_t'}} + unscoped_specified_t InvalidAfterRangeEnd = static_cast(5); // expected-warning {{The value '5' provided to the cast expression is not in the valid range of values for 'unscoped_specified_t'}} } void scopedUnspecified() { - scoped_unspecified_t InvalidBeforeRangeBegin = static_cast(-5); // expected-warning{{The value provided to the cast expression is not in the valid range of values for 'scoped_unspecified_t'}} + scoped_unspecified_t InvalidBeforeRangeBegin = static_cast(-5); // expected-warning{{The value '-5' provided to the cast expression is not in the valid range of values for 'scoped_unspecified_t'}} scoped_unspecified_t ValidNegativeValue1 = static_cast(-4); // OK. scoped_unspecified_t ValidNegativeValue2 = static_cast(-3); // OK. - scoped_unspecified_t InvalidInsideRange1 = static_cast(-2); // expected-warning {{The value provided to the cast expression is not in the valid range of values for 'scoped_unspecified_t'}} - scoped_unspecified_t InvalidInsideRange2 = static_cast(-1); // expected-warning {{The value provided to the cast expression is not in the valid range of values for 'scoped_unspecified_t'}} - scoped_unspecified_t InvalidInsideRange3 = static_cast(0); // expected-warning {{The value provided to the cast expression is not in the valid range of values for 'scoped_unspecified_t'}} + scoped_unspecified_t InvalidInsideRange1 = static_cast(-2); // expected-warning {{The value '-2' provided to the cast expression is not in the valid range of values for 'scoped_unspecified_t'}} + scoped_unspecified_t InvalidInsideRange2 = static_cast(-1); // expected-warning {{The value '-1' provided to the cast expression is not in the valid range of values for 'scoped_unspecified_t'}} + scoped_unspecified_t InvalidInsideRange3 = static_cast(0); // expected-warning {{The value '0' provided to the cast expression is not in the valid range of values for 'scoped_unspecified_t'}} scoped_unspecified_t ValidPositiveValue1 = static_cast(1); // OK. scoped_unspecified_t ValidPositiveValue2 = static_cast(2); // OK. - scoped_unspecified_t InvalidInsideRange4 = static_cast(3); // expected-warning {{The value provided to the cast expression is not in the valid range of values for 'scoped_unspecified_t'}} + scoped_unspecified_t InvalidInsideRange4 = static_cast(3); // expected-warning {{The value '3' provided to the cast expression is not in the valid range of values for 'scoped_unspecified_t'}} scoped_unspecified_t ValidPositiveValue3 = static_cast(4); // OK. - scoped_unspecified_t InvalidAfterRangeEnd = static_cast(5); // expected-warning {{The value provided to the cast expression is not in the valid range of values for 'scoped_unspecified_t'}} + scoped_unspecified_t InvalidAfterRangeEnd = static_cast(5); // expected-warning {{The value '5' provided to the cast expression is not in the valid range of values for 'scoped_unspecified_t'}} } void scopedSpecified() { - scoped_specified_t InvalidBeforeRangeBegin = static_cast(-5); // expected-warning {{The value provided to the cast expression is not in the valid range of values for 'scoped_specified_t'}} + scoped_specified_t InvalidBeforeRangeBegin = static_cast(-5); // expected-warning {{The value '-5' provided to the cast expression is not in the valid range of values for 'scoped_specified_t'}} scoped_specified_t ValidNegativeValue1 = static_cast(-4); // OK. scoped_specified_t ValidNegativeValue2 = static_cast(-3); // OK. - scoped_specified_t InvalidInsideRange1 = static_cast(-2); // expected-warning {{The value provided to the cast expression is not in the valid range of values for 'scoped_specified_t'}} - scoped_specified_t InvalidInsideRange2 = static_cast(-1); // expected-warning {{The value provided to the cast expression is not in the valid range of values for 'scoped_specified_t'}} - scoped_specified_t InvalidInsideRange3 = static_cast(0); // expected-warning {{The value provided to the cast expression is not in the valid range of values for 'scoped_specified_t'}} + scoped_specified_t InvalidInsideRange1 = static_cast(-2); // expected-warning {{The value '-2' provided to the cast expression is not in the valid range of values for 'scoped_specified_t'}} + scoped_specified_t InvalidInsideRange2 = static_cast(-1); // expected-warning {{The value '-1' provided to the cast expression is not in the valid range of values for 'scoped_specified_t'}} + scoped_specified_t InvalidInsideRange3 = static_cast(0); // expected-warning {{The value '0' provided to the cast expression is not in the valid range of values for 'scoped_specified_t'}} scoped_specified_t ValidPositiveValue1 = static_cast(1); // OK. scoped_specified_t ValidPositiveValue2 = static_cast(2); // OK. - scoped_specified_t InvalidInsideRange4 = static_cast(3); // expected-warning {{The value provided to the cast expression is not in the valid range of values for 'scoped_specified_t'}} + scoped_specified_t InvalidInsideRange4 = static_cast(3); // expected-warning {{The value '3' provided to the cast expression is not in the valid range of values for 'scoped_specified_t'}} scoped_specified_t ValidPositiveValue3 = static_cast(4); // OK. - scoped_specified_t InvalidAfterRangeEnd = static_cast(5); // expected-warning {{The value provided to the cast expression is not in the valid range of values for 'scoped_specified_t'}} + scoped_specified_t InvalidAfterRangeEnd = static_cast(5); // expected-warning {{The value '5' provided to the cast expression is not in the valid range of values for 'scoped_specified_t'}} } void unscopedUnspecifiedCStyle() { - unscoped_unspecified_t InvalidBeforeRangeBegin = (unscoped_unspecified_t)(-5); // expected-warning {{The value provided to the cast expression is not in the valid range of values for 'unscoped_unspecified_t'}} + unscoped_unspecified_t InvalidBeforeRangeBegin = (unscoped_unspecified_t)(-5); // expected-warning {{The value '-5' provided to the cast expression is not in the valid range of values for 'unscoped_unspecified_t'}} unscoped_unspecified_t ValidNegativeValue1 = (unscoped_unspecified_t)(-4); // OK. unscoped_unspecified_t ValidNegativeValue2 = (unscoped_unspecified_t)(-3); // OK. - unscoped_unspecified_t InvalidInsideRange1 = (unscoped_unspecified_t)(-2); // expected-warning {{The value provided to the cast expression is not in the valid range of values for 'unscoped_unspecified_t'}} - unscoped_unspecified_t InvalidInsideRange2 = (unscoped_unspecified_t)(-1); // expected-warning {{The value provided to the cast expression is not in the valid range of values for 'unscoped_unspecified_t'}} - unscoped_unspecified_t InvalidInsideRange3 = (unscoped_unspecified_t)(0); // expected-warning {{The value provided to the cast expression is not in the valid range of values for 'unscoped_unspecified_t'}} + unscoped_unspecified_t InvalidInsideRange1 = (unscoped_unspecified_t)(-2); // expected-warning {{The value '-2' provided to the cast expression is not in the valid range of values for 'unscoped_unspecified_t'}} + unscoped_unspecified_t InvalidInsideRange2 = (unscoped_unspecified_t)(-1); // expected-warning {{The value '-1' provided to the cast expression is not in the valid range of values for 'unscoped_unspecified_t'}} + unscoped_unspecified_t InvalidInsideRange3 = (unscoped_unspecified_t)(0); // expected-warning {{The value '0' provided to the cast expression is not in the valid range of values for 'unscoped_unspecified_t'}} unscoped_unspecified_t ValidPositiveValue1 = (unscoped_unspecified_t)(1); // OK. unscoped_unspecified_t ValidPositiveValue2 = (unscoped_unspecified_t)(2); // OK. - unscoped_unspecified_t InvalidInsideRange4 = (unscoped_unspecified_t)(3); // expected-warning {{The value provided to the cast expression is not in the valid range of values for 'unscoped_unspecified_t'}} + unscoped_unspecified_t InvalidInsideRange4 = (unscoped_unspecified_t)(3); // expected-warning {{The value '3' provided to the cast expression is not in the valid range of values for 'unscoped_unspecified_t'}} unscoped_unspecified_t ValidPositiveValue3 = (unscoped_unspecified_t)(4); // OK. - unscoped_unspecified_t InvalidAfterRangeEnd = (unscoped_unspecified_t)(5); // expected-warning {{The value provided to the cast expression is not in the valid range of values for 'unscoped_unspecified_t'}} + unscoped_unspecified_t InvalidAfterRangeEnd = (unscoped_unspecified_t)(5); // expected-warning {{The value '5' provided to the cast expression is not in the valid range of values for 'unscoped_unspecified_t'}} } void unscopedSpecifiedCStyle() { - unscoped_specified_t InvalidBeforeRangeBegin = (unscoped_specified_t)(-5); // expected-warning {{The value provided to the cast expression is not in the valid range of values for 'unscoped_specified_t'}} + unscoped_specified_t InvalidBeforeRangeBegin = (unscoped_specified_t)(-5); // expected-warning {{The value '-5' provided to the cast expression is not in the valid range of values for 'unscoped_specified_t'}} unscoped_specified_t ValidNegativeValue1 = (unscoped_specified_t)(-4); // OK. unscoped_specified_t ValidNegativeValue2 = (unscoped_specified_t)(-3); // OK. - unscoped_specified_t InvalidInsideRange1 = (unscoped_specified_t)(-2); // expected-warning {{The value provided to the cast expression is not in the valid range of values for 'unscoped_specified_t'}} - unscoped_specified_t InvalidInsideRange2 = (unscoped_specified_t)(-1); // expected-warning {{The value provided to the cast expression is not in the valid range of values for 'unscoped_specified_t'}} - unscoped_specified_t InvalidInsideRange3 = (unscoped_specified_t)(0); // expected-warning {{The value provided to the cast expression is not in the valid range of values for 'unscoped_specified_t'}} + unscoped_specified_t InvalidInsideRange1 = (unscoped_specified_t)(-2); // expected-warning {{The value '-2' provided to the cast expression is not in the valid range of values for 'unscoped_specified_t'}} + unscoped_specified_t InvalidInsideRange2 = (unscoped_specified_t)(-1); // expected-warning {{The value '-1' provided to the cast expression is not in the valid range of values for 'unscoped_specified_t'}} + unscoped_specified_t InvalidInsideRange3 = (unscoped_specified_t)(0); // expected-warning {{The value '0' provided to the cast expression is not in the valid range of values for 'unscoped_specified_t'}} unscoped_specified_t ValidPositiveValue1 = (unscoped_specified_t)(1); // OK. unscoped_specified_t ValidPositiveValue2 = (unscoped_specified_t)(2); // OK. - unscoped_specified_t InvalidInsideRange4 = (unscoped_specified_t)(3); // expected-warning {{The value provided to the cast expression is not in the valid range of values for 'unscoped_specified_t'}} + unscoped_specified_t InvalidInsideRange4 = (unscoped_specified_t)(3); // expected-warning {{The value '3' provided to the cast expression is not in the valid range of values for 'unscoped_specified_t'}} unscoped_specified_t ValidPositiveValue3 = (unscoped_specified_t)(4); // OK. - unscoped_specified_t InvalidAfterRangeEnd = (unscoped_specified_t)(5); // expected-warning {{The value provided to the cast expression is not in the valid range of values for 'unscoped_specified_t'}} + unscoped_specified_t InvalidAfterRangeEnd = (unscoped_specified_t)(5); // expected-warning {{The value '5' provided to the cast expression is not in the valid range of values for 'unscoped_specified_t'}} } void scopedUnspecifiedCStyle() { - scoped_unspecified_t InvalidBeforeRangeBegin = (scoped_unspecified_t)(-5); // expected-warning{{The value provided to the cast expression is not in the valid range of values for 'scoped_unspecified_t'}} + scoped_unspecified_t InvalidBeforeRangeBegin = (scoped_unspecified_t)(-5); // expected-warning{{The value '-5' provided to the cast expression is not in the valid range of values for 'scoped_unspecified_t'}} scoped_unspecified_t ValidNegativeValue1 = (scoped_unspecified_t)(-4); // OK. scoped_unspecified_t ValidNegativeValue2 = (scoped_unspecified_t)(-3); // OK. - scoped_unspecified_t InvalidInsideRange1 = (scoped_unspecified_t)(-2); // expected-warning {{The value provided to the cast expression is not in the valid range of values for 'scoped_unspecified_t'}} - scoped_unspecified_t InvalidInsideRange2 = (scoped_unspecified_t)(-1); // expected-warning {{The value provided to the cast expression is not in the valid range of values for 'scoped_unspecified_t'}} - scoped_unspecified_t InvalidInsideRange3 = (scoped_unspecified_t)(0); // expected-warning {{The value provided to the cast expression is not in the valid range of values for 'scoped_unspecified_t'}} + scoped_unspecified_t InvalidInsideRange1 = (scoped_unspecified_t)(-2); // expected-warning {{The value '-2' provided to the cast expression is not in the valid range of values for 'scoped_unspecified_t'}} + scoped_unspecified_t InvalidInsideRange2 = (scoped_unspecified_t)(-1); // expected-warning {{The value '-1' provided to the cast expression is not in the valid range of values for 'scoped_unspecified_t'}} + scoped_unspecified_t InvalidInsideRange3 = (scoped_unspecified_t)(0); // expected-warning {{The value '0' provided to the cast expression is not in the valid range of values for 'scoped_unspecified_t'}} scoped_unspecified_t ValidPositiveValue1 = (scoped_unspecified_t)(1); // OK. scoped_unspecified_t ValidPositiveValue2 = (scoped_unspecified_t)(2); // OK. - scoped_unspecified_t InvalidInsideRange4 = (scoped_unspecified_t)(3); // expected-warning {{The value provided to the cast expression is not in the valid range of values for 'scoped_unspecified_t'}} + scoped_unspecified_t InvalidInsideRange4 = (scoped_unspecified_t)(3); // expected-warning {{The value '3' provided to the cast expression is not in the valid range of values for 'scoped_unspecified_t'}} scoped_unspecified_t ValidPositiveValue3 = (scoped_unspecified_t)(4); // OK. - scoped_unspecified_t InvalidAfterRangeEnd = (scoped_unspecified_t)(5); // expected-warning {{The value provided to the cast expression is not in the valid range of values for 'scoped_unspecified_t'}} + scoped_unspecified_t InvalidAfterRangeEnd = (scoped_unspecified_t)(5); // expected-warning {{The value '5' provided to the cast expression is not in the valid range of values for 'scoped_unspecified_t'}} } void scopedSpecifiedCStyle() { - scoped_specified_t InvalidBeforeRangeBegin = (scoped_specified_t)(-5); // expected-warning {{The value provided to the cast expression is not in the valid range of values for 'scoped_specified_t'}} + scoped_specified_t InvalidBeforeRangeBegin = (scoped_specified_t)(-5); // expected-warning {{The value '-5' provided to the cast expression is not in the valid range of values for 'scoped_specified_t'}} scoped_specified_t ValidNegativeValue1 = (scoped_specified_t)(-4); // OK. scoped_specified_t ValidNegativeValue2 = (scoped_specified_t)(-3); // OK. - scoped_specified_t InvalidInsideRange1 = (scoped_specified_t)(-2); // expected-warning {{The value provided to the cast expression is not in the valid range of values for 'scoped_specified_t'}} - scoped_specified_t InvalidInsideRange2 = (scoped_specified_t)(-1); // expected-warning {{The value provided to the cast expression is not in the valid range of values for 'scoped_specified_t'}} - scoped_specified_t InvalidInsideRange3 = (scoped_specified_t)(0); // expected-warning {{The value provided to the cast expression is not in the valid range of values for 'scoped_specified_t'}} + scoped_specified_t InvalidInsideRange1 = (scoped_specified_t)(-2); // expected-warning {{The value '-2' provided to the cast expression is not in the valid range of values for 'scoped_specified_t'}} + scoped_specified_t InvalidInsideRange2 = (scoped_specified_t)(-1); // expected-warning {{The value '-1' provided to the cast expression is not in the valid range of values for 'scoped_specified_t'}} + scoped_specified_t InvalidInsideRange3 = (scoped_specified_t)(0); // expected-warning {{The value '0' provided to the cast expression is not in the valid range of values for 'scoped_specified_t'}} scoped_specified_t ValidPositiveValue1 = (scoped_specified_t)(1); // OK. scoped_specified_t ValidPositiveValue2 = (scoped_specified_t)(2); // OK. - scoped_specified_t InvalidInsideRange4 = (scoped_specified_t)(3); // expected-warning {{The value provided to the cast expression is not in the valid range of values for 'scoped_specified_t'}} + scoped_specified_t InvalidInsideRange4 = (scoped_specified_t)(3); // expected-warning {{The value '3' provided to the cast expression is not in the valid range of values for 'scoped_specified_t'}} scoped_specified_t ValidPositiveValue3 = (scoped_specified_t)(4); // OK. - scoped_specified_t InvalidAfterRangeEnd = (scoped_specified_t)(5); // expected-warning {{The value provided to the cast expression is not in the valid range of values for 'scoped_specified_t'}} + scoped_specified_t InvalidAfterRangeEnd = (scoped_specified_t)(5); // expected-warning {{The value '5' provided to the cast expression is not in the valid range of values for 'scoped_specified_t'}} } unscoped_unspecified_t unused; @@ -194,13 +194,13 @@ void rangeConstrained6(int input) { void rangeConstrained7(int input) { if (input >= 3 && input <= 3) - auto value = static_cast(input); // expected-warning {{The value provided to the cast expression is not in the valid range of values for 'scoped_specified_t'}} + auto value = static_cast(input); // expected-warning {{The value '3' provided to the cast expression is not in the valid range of values for 'scoped_specified_t'}} } void enumBitFieldAssignment() { S s; s.E = static_cast(4); // OK. - s.E = static_cast(5); // expected-warning {{The value provided to the cast expression is not in the valid range of values for 'unscoped_unspecified_t'}} + s.E = static_cast(5); // expected-warning {{The value '5' provided to the cast expression is not in the valid range of values for 'unscoped_unspecified_t'}} } @@ -219,3 +219,14 @@ void empty_enums_init_with_zero_should_not_warn() { ignore_unused(eu, ef, efu); } + +//Test the example from checkers.rst: +enum WidgetKind { A=1, B, C, X=99 }; // expected-note {{enum declared here}} + +void foo() { + WidgetKind c = static_cast(3); // OK + WidgetKind x = static_cast(99); // OK + WidgetKind d = static_cast(4); // expected-warning {{The value '4' provided to the cast expression is not in the valid range of values for 'WidgetKind'}} + + ignore_unused(c, x, d); +} diff --git a/clang/test/Analysis/out-of-bounds-diagnostics.c b/clang/test/Analysis/out-of-bounds-diagnostics.c index da1573665fa795120de9cabdcd045b91de5fd405..769a8954f7966915a346a2259e40ea6cef0cb7a3 100644 --- a/clang/test/Analysis/out-of-bounds-diagnostics.c +++ b/clang/test/Analysis/out-of-bounds-diagnostics.c @@ -9,6 +9,14 @@ void arrayUnderflow(void) { // expected-note@-2 {{Access of 'array' at negative byte offset -12}} } +int underflowWithDeref(void) { + int *p = array; + --p; + return *p; + // expected-warning@-1 {{Out of bound access to memory preceding 'array'}} + // expected-note@-2 {{Access of 'array' at negative byte offset -4}} +} + int scanf(const char *restrict fmt, ...); void taintedIndex(void) { @@ -17,6 +25,38 @@ void taintedIndex(void) { // expected-note@-1 {{Taint originated here}} // expected-note@-2 {{Taint propagated to the 2nd argument}} array[index] = 5; + // expected-warning@-1 {{Potential out of bound access to 'array' with tainted index}} + // expected-note@-2 {{Access of 'array' with a tainted index that may be too large}} +} + +int *taintedIndexAfterTheEndPtr(void) { + // NOTE: Technically speaking, this testcase does not trigger any UB because + // &array[10] is the after-the-end pointer which is well-defined; but this is + // a bug-prone situation and far from the idiomatic use of `&array[size]`, so + // it's better to report an error. This report can be easily silenced by + // writing array+index instead of &array[index]. + int index; + scanf("%d", &index); + // expected-note@-1 {{Taint originated here}} + // expected-note@-2 {{Taint propagated to the 2nd argument}} + if (index < 0 || index > 10) + return array; + // expected-note@-2 {{Assuming 'index' is >= 0}} + // expected-note@-3 {{Left side of '||' is false}} + // expected-note@-4 {{Assuming 'index' is <= 10}} + // expected-note@-5 {{Taking false branch}} + return &array[index]; + // expected-warning@-1 {{Potential out of bound access to 'array' with tainted index}} + // expected-note@-2 {{Access of 'array' with a tainted index that may be too large}} +} + +void taintedOffset(void) { + int index; + scanf("%d", &index); + // expected-note@-1 {{Taint originated here}} + // expected-note@-2 {{Taint propagated to the 2nd argument}} + int *p = array + index; + p[0] = 5; // expected-warning@-1 {{Potential out of bound access to 'array' with tainted offset}} // expected-note@-2 {{Access of 'array' with a tainted offset that may be too large}} } @@ -27,6 +67,47 @@ void arrayOverflow(void) { // expected-note@-2 {{Access of 'array' at index 12, while it holds only 10 'int' elements}} } +void flippedOverflow(void) { + 12[array] = 5; + // expected-warning@-1 {{Out of bound access to memory after the end of 'array'}} + // expected-note@-2 {{Access of 'array' at index 12, while it holds only 10 'int' elements}} +} + +int *afterTheEndPtr(void) { + // This is an unusual but standard-compliant way of writing (array + 10). + return &array[10]; // no-warning +} + +int useAfterTheEndPtr(void) { + // ... but dereferencing the after-the-end pointer is still invalid. + return *afterTheEndPtr(); + // expected-warning@-1 {{Out of bound access to memory after the end of 'array'}} + // expected-note@-2 {{Access of 'array' at index 10, while it holds only 10 'int' elements}} +} + +int *afterAfterTheEndPtr(void) { + // This is UB, it's invalid to form an after-after-the-end pointer. + return &array[11]; + // expected-warning@-1 {{Out of bound access to memory after the end of 'array'}} + // expected-note@-2 {{Access of 'array' at index 11, while it holds only 10 'int' elements}} +} + +int *potentialAfterTheEndPtr(int idx) { + if (idx < 10) { /* ...do something... */ } + // expected-note@-1 {{Assuming 'idx' is >= 10}} + // expected-note@-2 {{Taking false branch}} + return &array[idx]; + // expected-warning@-1 {{Out of bound access to memory after the end of 'array'}} + // expected-note@-2 {{Access of 'array' at an overflowing index, while it holds only 10 'int' elements}} + // NOTE: On the idx >= 10 branch the normal "optimistic" behavior would've + // been continuing with the assumption that idx == 10 and the return value is + // a legitimate after-the-end pointer. The checker deviates from this by + // reporting an error because this situation is very suspicious and far from + // the idiomatic `&array[size]` expressions. If the report is FP, the + // developer can easily silence it by writing array+idx instead of + // &array[idx]. +} + int scalar; int scalarOverflow(void) { return (&scalar)[1]; @@ -41,12 +122,6 @@ int oneElementArrayOverflow(void) { // expected-note@-2 {{Access of 'oneElementArray' at index 1, while it holds only a single 'int' element}} } -short convertedArray(void) { - return ((short*)array)[47]; - // expected-warning@-1 {{Out of bound access to memory after the end of 'array'}} - // expected-note@-2 {{Access of 'array' at index 47, while it holds only 20 'short' elements}} -} - struct vec { int len; double elems[64]; @@ -64,6 +139,28 @@ double arrayInStructPtr(struct vec *pv) { // expected-note@-2 {{Access of the field 'elems' at index 64, while it holds only 64 'double' elements}} } +struct item { + int a, b; +} itemArray[20] = {0}; + +int arrayOfStructs(void) { + return itemArray[35].a; + // expected-warning@-1 {{Out of bound access to memory after the end of 'itemArray'}} + // expected-note@-2 {{Access of 'itemArray' at index 35, while it holds only 20 'struct item' elements}} +} + +int arrayOfStructsArrow(void) { + return (itemArray + 35)->b; + // expected-warning@-1 {{Out of bound access to memory after the end of 'itemArray'}} + // expected-note@-2 {{Access of 'itemArray' at index 35, while it holds only 20 'struct item' elements}} +} + +short convertedArray(void) { + return ((short*)array)[47]; + // expected-warning@-1 {{Out of bound access to memory after the end of 'array'}} + // expected-note@-2 {{Access of 'array' at index 47, while it holds only 20 'short' elements}} +} + struct two_bytes { char lo, hi; }; @@ -85,7 +182,9 @@ int intFromString(void) { } int intFromStringDivisible(void) { - // However, this is reported with indices/elements, because the extent happens to be a multiple of 4. + // However, this is reported with indices/elements, because the extent + // (of the string that consists of 'a', 'b', 'c' and '\0') happens to be a + // multiple of 4 bytes (= sizeof(int)). return ((const int*)"abc")[20]; // expected-warning@-1 {{Out of bound access to memory after the end of the string literal}} // expected-note@-2 {{Access of the string literal at index 20, while it holds only a single 'int' element}} diff --git a/clang/test/Analysis/out-of-bounds-new.cpp b/clang/test/Analysis/out-of-bounds-new.cpp index af4ec47d8358aab4f7d3b240a711be9b7bb1eae8..f541bdf810d79ce6ee20360a137f92f94802e39b 100644 --- a/clang/test/Analysis/out-of-bounds-new.cpp +++ b/clang/test/Analysis/out-of-bounds-new.cpp @@ -154,3 +154,29 @@ void test_dynamic_size2(unsigned m,unsigned n){ unsigned *U = nullptr; U = new unsigned[m + n + 1]; } + +//Test creating invalid references, which break the invariant that a reference +//is always holding a value, and could lead to nasty runtime errors. +//(This is not related to operator new, but placed in this file because the +//other test files are not C++.) +int array[10] = {0}; + +void test_after_the_end_reference() { + int &ref = array[10]; // expected-warning{{Out of bound access to memory}} +} + +void test_after_after_the_end_reference() { + int &ref = array[11]; // expected-warning{{Out of bound access to memory}} +} + +int test_reference_that_might_be_after_the_end(int idx) { + // This TC produces no warning because separate analysis of (idx == 10) is + // only introduced _after_ the creation of the reference ref. + if (idx < 0 || idx > 10) + return -2; + int &ref = array[idx]; + if (idx == 10) + return -1; + return ref; +} + diff --git a/clang/test/Analysis/taint-diagnostic-visitor.c b/clang/test/Analysis/taint-diagnostic-visitor.c index 67dc67e627b3b9c0ffb743bf96809a2710396e36..a3fa1639bffeee5c0e366090edd02749f9309599 100644 --- a/clang/test/Analysis/taint-diagnostic-visitor.c +++ b/clang/test/Analysis/taint-diagnostic-visitor.c @@ -29,8 +29,8 @@ int taintDiagnosticOutOfBound(void) { int Array[] = {1, 2, 3, 4, 5}; scanf("%d", &index); // expected-note {{Taint originated here}} // expected-note@-1 {{Taint propagated to the 2nd argument}} - return Array[index]; // expected-warning {{Potential out of bound access to 'Array' with tainted offset}} - // expected-note@-1 {{Access of 'Array' with a tainted offset that may be too large}} + return Array[index]; // expected-warning {{Potential out of bound access to 'Array' with tainted index}} + // expected-note@-1 {{Access of 'Array' with a tainted index that may be too large}} } int taintDiagnosticDivZero(int operand) { diff --git a/clang/test/C/C2x/n2836_n2939.c b/clang/test/C/C2x/n2836_n2939.c new file mode 100644 index 0000000000000000000000000000000000000000..13e23c3def80ddc59013d37cd51581ad3c034275 --- /dev/null +++ b/clang/test/C/C2x/n2836_n2939.c @@ -0,0 +1,83 @@ +// RUN: %clang_cc1 -x c -std=c2x -fsyntax-only -verify %s +// RUN: %clang_cc1 -x c -std=c2x -E -DPP_ONLY=1 %s | FileCheck %s --strict-whitespace + +/* WG14 N2836: Clang 15 + * Identifier Syntax using Unicode Standard Annex 31 + */ + +/* WG14 N2939: Clang 15 + * Identifier Syntax Fixes + */ + +// Some of the tests below are derived from clang/test/Lexer/unicode.c. + +// This file contains Unicode characters; please do not "fix" them! + +// No diagnostics for pragma directives. +#pragma mark ¡Unicode! + +// lone non-identifier characters are allowed in preprocessing. +#define COPYRIGHT Copyright © 2012 +#define XSTR(X) #X +#define STR(X) XSTR(X) + +static const char *copyright = STR(COPYRIGHT); // no-warning +// CHECK: static const char *copyright = "Copyright © {{2012}}"; + +#if PP_ONLY +COPYRIGHT +// CHECK: Copyright © {{2012}} +#endif + +// The characters in the following identifiers are no longer valid as either +// start or continuation characters as of C23. These are taken from section 1 +// of N2836. +extern int \N{CONSTRUCTION WORKER}; // expected-error {{expected identifier or '('}} +extern int X\N{CONSTRUCTION WORKER}; // expected-error {{character not allowed in an identifier}} +extern int \U0001F477; // expected-error {{expected identifier or '('}} +extern int X\U0001F477; // expected-error {{character not allowed in an identifier}} +extern int 👷; // expected-error {{unexpected character }} \ + // expected-warning {{declaration does not declare anything}} +extern int X👷; // expected-error {{character not allowed in an identifier}} +extern int 🕐; // expected-error {{unexpected character }} \ + // expected-warning {{declaration does not declare anything}} +extern int X🕐; // expected-error {{character not allowed in an identifier}} +extern int 💀; // expected-error {{unexpected character }} \ + // expected-warning {{declaration does not declare anything}} +extern int X💀; // expected-error {{character not allowed in an identifier}} +extern int 👊; // expected-error {{unexpected character }} \ + // expected-warning {{declaration does not declare anything}} +extern int X👊; // expected-error {{character not allowed in an identifier}} +extern int 🚀; // expected-error {{unexpected character }} \ + // expected-warning {{declaration does not declare anything}} +extern int X🚀; // expected-error {{character not allowed in an identifier}} +extern int 😀; // expected-error {{unexpected character }} \ + // expected-warning {{declaration does not declare anything}} +extern int X😀; // expected-error {{character not allowed in an identifier}} + +// The characters in the following identifiers are not allowed as start +// characters, but are allowed as continuation characters. +extern int \N{ARABIC-INDIC DIGIT ZERO}; // expected-error {{expected identifier or '('}} +extern int X\N{ARABIC-INDIC DIGIT ZERO}; +extern int \u0661; // expected-error {{expected identifier or '('}} +extern int X\u0661; +extern int ٢; // expected-error {{character not allowed at the start of an identifier}} \\ + // expected-warning {{declaration does not declare anything}} +extern int X٠; + +// The characters in the following identifiers are not valid start or +// continuation characters in the standard, but are accepted as a conforming +// extension. +extern int \N{SUPERSCRIPT ZERO}; // expected-error {{expected identifier or '('}} +extern int X\N{SUPERSCRIPT ZERO}; // expected-warning {{mathematical notation character in an identifier is a Clang extension}} +extern int \u00B9; // expected-error {{expected identifier or '('}} +extern int X\u00B9; // expected-warning {{mathematical notation character in an identifier is a Clang extension}} +extern int ²; // expected-error {{character not allowed at the start of an identifier}} \\ + // expected-warning {{declaration does not declare anything}} +extern int X²; // expected-warning {{mathematical notation character in an identifier is a Clang extension}} +extern int \N{PARTIAL DIFFERENTIAL}; // expected-warning {{mathematical notation character in an identifier is a Clang extension}} +extern int X\N{PARTIAL DIFFERENTIAL}; // expected-warning {{mathematical notation character in an identifier is a Clang extension}} +extern int \u2207; // expected-warning {{mathematical notation character in an identifier is a Clang extension}} +extern int X\u2207; // expected-warning {{mathematical notation character in an identifier is a Clang extension}} +extern int ∞; // expected-warning {{mathematical notation character in an identifier is a Clang extension}} +extern int X∞; // expected-warning {{mathematical notation character in an identifier is a Clang extension}} diff --git a/clang/test/CXX/class.access/class.friend/p6.cpp b/clang/test/CXX/class.access/class.friend/p6.cpp index 2fe20fe77fc8f2179e6f430a2c0233a7a0ebf9b8..47104e29dc6b3c7554bf750840d5a8da47ad533b 100644 --- a/clang/test/CXX/class.access/class.friend/p6.cpp +++ b/clang/test/CXX/class.access/class.friend/p6.cpp @@ -22,3 +22,16 @@ void local() { friend void f() { } // expected-error{{friend function cannot be defined in a local class}} }; } + +template void f3(T); + +namespace N { + template void f4(T); +} + +template struct A { + friend void f3(T) {} + friend void f3(T) {} // expected-error{{friend function specialization cannot be defined}} + friend void N::f4(T) {} // expected-error{{friend function definition cannot be qualified with 'N::'}} + friend void N::f4(T) {} // expected-error{{friend function definition cannot be qualified with 'N::'}} +}; diff --git a/clang/test/CXX/drs/dr10xx.cpp b/clang/test/CXX/drs/dr10xx.cpp index f30ed1cb3e49673be0d1db66130620ccc459c4d3..77c59078414c69bdb012207d68ba774cf41f64e2 100644 --- a/clang/test/CXX/drs/dr10xx.cpp +++ b/clang/test/CXX/drs/dr10xx.cpp @@ -1,9 +1,9 @@ -// RUN: %clang_cc1 -std=c++98 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++11 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++14 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++17 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++20 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++23 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++98 %s -verify=expected -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++11 %s -verify=expected -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++14 %s -verify=expected,since-cxx14 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++17 %s -verify=expected,since-cxx14 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++20 %s -verify=expected,since-cxx14 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++23 %s -verify=expected,since-cxx14 -fexceptions -fcxx-exceptions -pedantic-errors namespace std { __extension__ typedef __SIZE_TYPE__ size_t; @@ -18,30 +18,40 @@ namespace dr1004 { // dr1004: 5 template struct A {}; template struct B1 {}; template class> struct B2 {}; - template void f(); // expected-note {{[with X = dr1004::A]}} - template class X> void f(); // expected-note {{[with X = dr1004::A]}} - template class X> void g(); // expected-note {{[with X = dr1004::A]}} - template void g(); // expected-note {{[with X = dr1004::A]}} + template void f(); // #dr1004-f-1 + template class X> void f(); // #dr1004-f-2 + template class X> void g(); // #dr1004-g-1 + template void g(); // #dr1004-g-2 struct C : A { B1 b1a; B2 b2a; void h() { - f(); // expected-error {{ambiguous}} - g(); // expected-error {{ambiguous}} + f(); + // expected-error@-1 {{call to 'f' is ambiguous}} + // expected-note@#dr1004-f-1 {{candidate function [with X = dr1004::A]}} + // expected-note@#dr1004-f-2 {{candidate function [with X = dr1004::A]}} + g(); + // expected-error@-1 {{call to 'g' is ambiguous}} + // expected-note@#dr1004-g-1 {{candidate function [with X = dr1004::A]}} + // expected-note@#dr1004-g-2 {{candidate function [with X = dr1004::A]}} } }; // This example (from the standard) is actually ill-formed, because // name lookup of "T::template A" names the constructor. - template class U = T::template A> struct Third { }; // expected-error {{is a constructor name}} - Third > t; // expected-note {{in instantiation of default argument}} + template class U = T::template A> struct Third { }; + // expected-error@-1 {{is a constructor name}} + // expected-note@#dr1004-t {{in instantiation of default argument}} + Third > t; // #dr1004-t } namespace dr1042 { // dr1042: 3.5 #if __cplusplus >= 201402L // C++14 added an attribute that we can test the semantics of. - using foo [[deprecated]] = int; // expected-note {{'foo' has been explicitly marked deprecated here}} - foo f = 12; // expected-warning {{'foo' is deprecated}} + using foo [[deprecated]] = int; // #dr1042-using + foo f = 12; + // since-cxx14-warning@-1 {{'foo' is deprecated}} + // since-cxx14-note@#dr1042-using {{'foo' has been explicitly marked deprecated here}} #elif __cplusplus >= 201103L // C++11 did not have any attributes that could be applied to an alias // declaration, so the best we can test is that we accept an empty attribute @@ -76,7 +86,8 @@ namespace dr1054 { // dr1054: no // which copy-initializes a temporary from 'a'. Therefore this is // ill-formed because A does not have a volatile copy constructor. // (We might want to track this aspect under dr1383 instead?) - a; // expected-warning {{assign into a variable to force a volatile load}} + a; + // expected-warning@-1 {{expression result unused; assign into a variable to force a volatile load}} } } diff --git a/clang/test/CXX/drs/dr11xx.cpp b/clang/test/CXX/drs/dr11xx.cpp index 23756ff1927eccf3378142a4c850ec1caf835fad..86e726ae8c7419208ab05efe38df163a8571c14e 100644 --- a/clang/test/CXX/drs/dr11xx.cpp +++ b/clang/test/CXX/drs/dr11xx.cpp @@ -1,30 +1,30 @@ -// RUN: %clang_cc1 -std=c++98 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++11 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++14 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++17 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++2a %s -verify -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++98 %s -verify=expected,cxx98 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++11 %s -verify=expected -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++14 %s -verify=expected -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++17 %s -verify=expected -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++2a %s -verify=expected -fexceptions -fcxx-exceptions -pedantic-errors -namespace dr1111 { // dr1111: yes +namespace dr1111 { // dr1111: 3.2 namespace example1 { -template struct set; +template struct set; // #dr1111-struct-set struct X { - template void set(const T &value); + template void set(const T &value); // #dr1111-func-set }; void foo() { X x; -#pragma clang diagnostic push -#if __cplusplus < 201103L -#pragma clang diagnostic ignored "-Wambiguous-member-template" -#endif + // FIXME: should we backport C++11 behavior? x.set(3.2); -#pragma clang diagnostic pop + // cxx98-error@-1 {{lookup of 'set' in member access expression is ambiguous; using member of 'X'}} + // cxx98-note@#dr1111-func-set {{lookup in the object type 'X' refers here}} + // cxx98-note@#dr1111-struct-set {{lookup from the current scope refers here}} } struct Y {}; void bar() { Y y; - y.set(3.2); // expected-error {{no member named 'set' in 'dr1111::example1::Y'}} + y.set(3.2); + // expected-error@-1 {{no member named 'set' in 'dr1111::example1::Y'}} } } // namespace example1 @@ -46,8 +46,10 @@ void baz() { namespace dr1113 { // dr1113: partial namespace named { - extern int a; // expected-note {{previous}} - static int a; // expected-error {{static declaration of 'a' follows non-static}} + extern int a; // #dr1113-a + static int a; + // expected-error@-1 {{static declaration of 'a' follows non-static}} + // expected-note@#dr1113-a {{previous declaration is here}} } namespace { extern int a; diff --git a/clang/test/CXX/drs/dr12xx.cpp b/clang/test/CXX/drs/dr12xx.cpp index c23a515ba56cb99d80234b1b8bc44e14c32c33a3..adf7f56711c4519b6c8476614dc02a5e9f98dce5 100644 --- a/clang/test/CXX/drs/dr12xx.cpp +++ b/clang/test/CXX/drs/dr12xx.cpp @@ -1,9 +1,9 @@ -// RUN: %clang_cc1 -std=c++98 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++11 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++14 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++17 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++20 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++23 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++98 %s -verify=expected,cxx98-14,cxx98 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++11 %s -verify=expected,cxx98-14,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++14 %s -verify=expected,cxx98-14,since-cxx14,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++17 %s -verify=expected,since-cxx17,since-cxx14,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++20 %s -verify=expected,since-cxx17,since-cxx14,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++23 %s -verify=expected,since-cxx17,since-cxx14,since-cxx11,since-cxx23 -fexceptions -fcxx-exceptions -pedantic-errors // dr1200: na @@ -40,28 +40,33 @@ struct S { S* operator()(); int N; int M; -#if __cplusplus > 202002L +#if __cplusplus >= 202302L template static constexpr auto V = 0; void f(char); void f(int); void mem(S s) { - auto(s)()->M; //expected-warning {{expression result unused}} - auto(s)()->V; //expected-warning {{expression result unused}} + auto(s)()->M; + // since-cxx23-warning@-1 {{expression result unused}} + auto(s)()->V; + // since-cxx23-warning@-1 {{expression result unused}} auto(s)()->f(0); } #endif }; void f(S s) { { -#if __cplusplus > 202002L - auto(s)()->N; //expected-warning {{expression result unused}} +#if __cplusplus >= 202302L + auto(s)()->N; + //since-cxx23-warning@-1 {{expression result unused}} #endif auto(s)()->M; } { - S(s)()->N; //expected-warning {{expression result unused}} - S(s)()->M; //expected-warning {{expression result unused}} + S(s)()->N; + // since-cxx11-warning@-1 {{expression result unused}} + S(s)()->M; + // since-cxx11-warning@-1 {{expression result unused}} } } @@ -74,23 +79,27 @@ void g() { A a(B ()->C); A b(auto ()->C); static_assert(sizeof(B ()->C[1] == sizeof(int)), ""); - sizeof(auto () -> C[1]); // expected-error{{function cannot return array type 'C[1]'}} + sizeof(auto () -> C[1]); + // since-cxx11-error@-1 {{function cannot return array type 'C[1]' (aka 'dr1223::BB[1]')}} } } #endif #if __cplusplus >= 201103L -namespace dr1227 { // dr1227: yes -template struct A { using X = typename T::X; }; // expected-error {{type 'int' cannot be used prior to '::' because it has no members}} +namespace dr1227 { // dr1227: 3.0 +template struct A { using X = typename T::X; }; +// since-cxx11-error@-1 {{type 'int' cannot be used prior to '::' because it has no members}} +// since-cxx11-note@#dr1227-g {{in instantiation of template class 'dr1227::A' requested here}} +// since-cxx11-note@#dr1227-g-int {{while substituting explicitly-specified template arguments into function template 'g'}} template typename T::X f(typename A::X); template void f(...) { } -template auto g(typename A::X) -> typename T::X; // expected-note {{in instantiation of template class 'dr1227::A' requested here}} +template auto g(typename A::X) -> typename T::X; // #dr1227-g template void g(...) { } void h() { f(0); // OK, substituting return type causes deduction to fail - g(0); // expected-note {{while substituting explicitly-specified template arguments into function template 'g'}} + g(0); // #dr1227-g-int } } #endif @@ -109,15 +118,21 @@ struct Derived : Base { namespace dr1265 { // dr1265: 5 #if __cplusplus >= 201103L - auto a = 0, b() -> int; // expected-error {{declaration with trailing return type must be the only declaration in its group}} - auto b() -> int, d = 0; // expected-error {{declaration with trailing return type must be the only declaration in its group}} - auto e() -> int, f() -> int; // expected-error {{declaration with trailing return type must be the only declaration in its group}} + auto a = 0, b() -> int; + // since-cxx11-error@-1 {{declaration with trailing return type must be the only declaration in its group}} + auto b() -> int, d = 0; + // since-cxx11-error@-1 {{declaration with trailing return type must be the only declaration in its group}} + auto e() -> int, f() -> int; + // since-cxx11-error@-1 {{declaration with trailing return type must be the only declaration in its group}} #endif #if __cplusplus >= 201402L - auto g(), h = 0; // expected-error {{function with deduced return type must be the only declaration in its group}} - auto i = 0, j(); // expected-error {{function with deduced return type must be the only declaration in its group}} - auto k(), l(); // expected-error {{function with deduced return type must be the only declaration in its group}} + auto g(), h = 0; + // since-cxx14-error@-1 {{function with deduced return type must be the only declaration in its group}} + auto i = 0, j(); + // since-cxx14-error@-1 {{function with deduced return type must be the only declaration in its group}} + auto k(), l(); + // since-cxx14-error@-1 {{function with deduced return type must be the only declaration in its group}} #endif } @@ -130,16 +145,16 @@ namespace dr1295 { // dr1295: 4 X x = {1}; - unsigned const &r1 = static_cast(x).bitfield; // expected-error 0-1{{C++11}} - unsigned const &r2 = static_cast(x.bitfield); // expected-error 0-1{{C++11}} + unsigned const &r1 = static_cast(x).bitfield; + // cxx98-error@-1 {{rvalue references are a C++11 extension}} + unsigned const &r2 = static_cast(x.bitfield); + // cxx98-error@-1 {{rvalue references are a C++11 extension}} - template struct Y {}; - Y y; -#if __cplusplus <= 201402L - // expected-error@-2 {{does not refer to any declaration}} expected-note@-3 {{here}} -#else - // expected-error@-4 {{refers to subobject}} -#endif + template struct Y {}; // #dr1295-Y + Y y; // #dr1295-y + // cxx98-14-error@-1 {{non-type template argument does not refer to any declaration}} + // cxx98-14-note@#dr1295-Y {{template parameter is declared here}} + // since-cxx17-error@#dr1295-y {{non-type template argument refers to subobject 'x.bitfield'}} #if __cplusplus >= 201103L const unsigned other = 0; diff --git a/clang/test/CXX/drs/dr13xx.cpp b/clang/test/CXX/drs/dr13xx.cpp index 3510695954e27c11335fc6d42db9ef39a579354d..359c04b3e0f3d4e011cf55c05c092ac113a11442 100644 --- a/clang/test/CXX/drs/dr13xx.cpp +++ b/clang/test/CXX/drs/dr13xx.cpp @@ -1,7 +1,10 @@ -// RUN: %clang_cc1 -std=c++98 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++11 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++14 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++17 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++98 %s -verify=expected,cxx98-14,cxx98 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++11 %s -verify=expected,cxx11-17,cxx11-14,cxx98-14,since-cxx11,cxx11 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++14 %s -verify=expected,cxx11-17,cxx11-14,since-cxx14,cxx98-14,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++17 %s -verify=expected,cxx11-17,since-cxx14,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++20 %s -verify=expected,since-cxx14,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++23 %s -verify=expected,since-cxx14,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++2c %s -verify=expected,since-cxx14,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors __extension__ typedef __SIZE_TYPE__ size_t; @@ -14,11 +17,13 @@ namespace std { } #if __cplusplus >= 201103L -namespace dr1305 { // dr1305: yes -struct Incomplete; // expected-note {{forward declaration of 'dr1305::Incomplete'}} +namespace dr1305 { // dr1305: 3.0 +struct Incomplete; // #dr1305-Incomplete struct Complete {}; -int incomplete = alignof(Incomplete(&)[]); // expected-error {{invalid application of 'alignof' to an incomplete type 'Incomplete'}} +int incomplete = alignof(Incomplete(&)[]); +// since-cxx11-error@-1 {{invalid application of 'alignof' to an incomplete type 'Incomplete'}} +// since-cxx11-note@#dr1305-Incomplete {{forward declaration of 'dr1305::Incomplete'}} int complete = alignof(Complete(&)[]); } #endif @@ -36,9 +41,11 @@ void caller() { } // namespace dr1307 namespace dr1310 { // dr1310: 5 - struct S {} * sp = new S::S; // expected-error {{qualified reference to 'S' is a constructor name}} + struct S {} * sp = new S::S; + // expected-error@-1 {{qualified reference to 'S' is a constructor name rather than a type in this context}} void f() { - S::S(a); // expected-error {{qualified reference to 'S' is a constructor name}} + S::S(a); + // expected-error@-1 {{qualified reference to 'S' is a constructor name rather than a type in this context}} } struct T { int n; typedef int U; typedef T V; }; int k = T().T::T::n; @@ -64,39 +71,67 @@ namespace dr1310 { // dr1310: 5 template struct W : WBase { typedef int X; int n; }; void w_test() { - W::W w1a; // expected-error {{qualified reference to 'W' is a constructor name}} + W::W w1a; + // expected-error@-1 {{qualified reference to 'W' is a constructor name rather than a type in this context}} W::W::X w1ax; - W::W w1b; // expected-error {{qualified reference to 'W' is a constructor name}} + W::W w1b; + // expected-error@-1 {{qualified reference to 'W' is a constructor name rather than a template name in this context}} W::W::X w1bx; - typename W::W w2a; // expected-error {{qualified reference to 'W' is a constructor name}} expected-error 0-1{{outside of a template}} - typename W::W::X w2ax; // expected-error 0-1{{outside of a template}} - typename W::W w2b; // expected-error {{qualified reference to 'W' is a constructor name}} expected-error 0-1{{outside of a template}} - typename W::W::X w2bx; // expected-error 0-1{{outside of a template}} - W::template W w3; // expected-error {{qualified reference to 'W' is a constructor name}} expected-error 0-1{{outside of a template}} - W::template W::X w3x; // expected-error 0-1{{outside of a template}} - typename W::template W w4; // expected-error {{qualified reference to 'W' is a constructor name}} expected-error 0-2{{outside of a template}} - typename W::template W::X w4x; // expected-error 0-2{{outside of a template}} - - TT::W> tt1; // expected-error {{qualified reference to 'W' is a constructor name}} - TTy::W> tt1a; // expected-error {{qualified reference to 'W' is a constructor name}} - TT::template W> tt2; // expected-error {{qualified reference to 'W' is a constructor name}} expected-error 0-1{{outside of a template}} + typename W::W w2a; + // expected-error@-1 {{ISO C++ specifies that qualified reference to 'W' is a constructor name rather than a type in this context, despite preceding 'typename' keyword}} + // cxx98-error@-2 {{'typename' occurs outside of a template}} + typename W::W::X w2ax; + // cxx98-error@-1 {{'typename' occurs outside of a template}} + typename W::W w2b; + // expected-error@-1 {{ISO C++ specifies that qualified reference to 'W' is a constructor name rather than a template name in this context, despite preceding 'typename' keyword}} + // cxx98-error@-2 {{'typename' occurs outside of a template}} + typename W::W::X w2bx; + // cxx98-error@-1 {{'typename' occurs outside of a template}} + W::template W w3; + // expected-error@-1 {{ISO C++ specifies that qualified reference to 'W' is a constructor name rather than a template name in this context, despite preceding 'template' keyword}} + // cxx98-error@-2 {{'template' keyword outside of a template}} + W::template W::X w3x; + // cxx98-error@-1 {{'template' keyword outside of a template}} + typename W::template W w4; + // expected-error@-1 {{ISO C++ specifies that qualified reference to 'W' is a constructor name rather than a template name in this context, despite preceding 'template' keyword}} + // cxx98-error@-2 {{'template' keyword outside of a template}} + // cxx98-error@-3 {{'typename' occurs outside of a template}} + typename W::template W::X w4x; + // cxx98-error@-1 {{'template' keyword outside of a template}} + // cxx98-error@-2 {{'typename' occurs outside of a template}} + + TT::W> tt1; + // expected-error@-1 {{qualified reference to 'W' is a constructor name rather than a type in this context}} + TTy::W> tt1a; + // expected-error@-1 {{qualified reference to 'W' is a constructor name rather than a type in this context}} + TT::template W> tt2; + // expected-error@-1 {{ISO C++ specifies that qualified reference to 'W' is a constructor name rather than a template name in this context, despite preceding 'template' keyword}} + // cxx98-error@-2 {{'template' keyword outside of a template}} TT::WBase> tt3; TTy::WBase> tt3a; - TT::template WBase> tt4; // expected-error 0-1{{outside of a template}} + TT::template WBase> tt4; + // cxx98-error@-1 {{'template' keyword outside of a template}} W w; (void)w.W::W::n; (void)w.W::W::n; (void)w.W::W::n; - (void)w.W::template W::n; // expected-error 0-1{{outside of a template}} + (void)w.W::template W::n; + // cxx98-error@-1 {{'template' keyword outside of a template}} } template void wt_test() { - typename W::W w2a; // expected-error {{qualified reference to 'W' is a constructor name}} - typename W::template W w4; // expected-error {{qualified reference to 'W' is a constructor name}} - TTy tt2; // expected-error {{qualified reference to 'W' is a constructor name}} - TT tt3; // expected-error {{qualified reference to 'W' is a constructor name}} + typename W::W w2a; + // expected-error@-1 {{ISO C++ specifies that qualified reference to 'W' is a constructor name rather than a type in this context, despite preceding 'typename' keyword}} + // cxx98-note@#dr1310-W-int {{in instantiation of function template specialization 'dr1310::wt_test >' requested here}} + // since-cxx11-note@#dr1310-W-int {{in instantiation of function template specialization 'dr1310::wt_test>' requested here}} + typename W::template W w4; + // expected-error@-1 {{ISO C++ specifies that qualified reference to 'W' is a constructor name rather than a template name in this context, despite preceding 'template' keyword}} + TTy tt2; + // expected-error@-1 {{ISO C++ specifies that qualified reference to 'W' is a constructor name rather than a type in this context, despite preceding 'typename' keyword}} + TT tt3; + // expected-error@-1 {{ISO C++ specifies that qualified reference to 'W' is a constructor name rather than a template name in this context, despite preceding 'template' keyword}} } template void wt_test_good() { @@ -111,18 +146,19 @@ namespace dr1310 { // dr1310: 5 (void)w.template W::W::n; (void)w.template W::template W::n; } - template void wt_test >(); // expected-note {{instantiation of}} + template void wt_test >(); // #dr1310-W-int template void wt_test_good >(); } namespace dr1315 { // dr1315: partial template struct A {}; - template // expected-note {{non-deducible template parameter 'I'}} - struct A {}; // expected-error {{contains a template parameter that cannot be deduced}} + template struct A {}; + // expected-error@-1 {{class template partial specialization contains a template parameter that cannot be deduced; this partial specialization will never be used}} + // expected-note@-2 {{non-deducible template parameter 'I'}} template struct A {}; template struct B; - template struct B {}; // expected-note {{matches}} + template struct B {}; // #dr1315-B-1 B<1, 2, 3> b1; // Multiple declarations with the same dependent expression are equivalent @@ -131,8 +167,11 @@ namespace dr1315 { // dr1315: partial B<1, 2, 2>::type b2; // Multiple declarations with differing dependent expressions are unordered. - template struct B {}; // expected-note {{matches}} - B<1, 2, 4> b3; // expected-error {{ambiguous}} + template struct B {}; // #dr1315-B-2 + B<1, 2, 4> b3; + // expected-error@-1 {{ambiguous partial specializations of 'B<1, 2, 4>'}} + // expected-note@#dr1315-B-1 {{partial specialization matches [with I = 1, K = 4]}} + // expected-note@#dr1315-B-2 {{partial specialization matches [with I = 1, K = 4]}} // FIXME: Under dr1315, this is perhaps valid, but that is not clear: this // fails the "more specialized than the primary template" test because the @@ -146,7 +185,9 @@ namespace dr1315 { // dr1315: partial namespace dr1330 { // dr1330: 4 c++11 // exception-specifications are parsed in a context where the class is complete. struct A { - void f() throw(T) {} // expected-error 0-1{{C++17}} expected-note 0-1{{noexcept}} + void f() throw(T) {} + // since-cxx17-error@-1 {{ISO C++17 does not allow dynamic exception specifications}} + // since-cxx17-note@-2 {{use 'noexcept(false)' instead}} struct T {}; #if __cplusplus >= 201103L @@ -156,8 +197,12 @@ namespace dr1330 { // dr1330: 4 c++11 #endif }; - void (A::*af1)() throw(A::T) = &A::f; // expected-error 0-1{{C++17}} expected-note 0-1{{noexcept}} - void (A::*af2)() throw() = &A::f; // expected-error-re {{{{not superset|different exception spec}}}} + void (A::*af1)() throw(A::T) = &A::f; + // since-cxx17-error@-1 {{ISO C++17 does not allow dynamic exception specifications}} + // since-cxx17-note@-2 {{use 'noexcept(false)' instead}} + void (A::*af2)() throw() = &A::f; + // cxx98-14-error@-1 {{target exception specification is not superset of source}} + // since-cxx17-error@-2 {{cannot initialize a variable of type 'void (dr1330::A::*)() throw()' with an rvalue of type 'void (dr1330::A::*)() throw(T)': different exception specifications}} #if __cplusplus >= 201103L static_assert(noexcept(A().g()), ""); @@ -166,7 +211,9 @@ namespace dr1330 { // dr1330: 4 c++11 // Likewise, they're instantiated separately from an enclosing class template. template struct B { - void f() throw(T, typename U::type) {} // expected-error 0-1{{C++17}} expected-note 0-1{{noexcept}} + void f() throw(T, typename U::type) {} + // since-cxx17-error@-1 {{ISO C++17 does not allow dynamic exception specifications}} + // since-cxx17-note@-2 {{use 'noexcept(false)' instead}} struct T {}; #if __cplusplus >= 201103L @@ -183,9 +230,6 @@ namespace dr1330 { // dr1330: 4 c++11 static const int value = true; }; - void (B

::*bpf1)() throw(B

::T, int) = &B

::f; // expected-error 0-1{{C++17}} expected-note 0-1{{noexcept}} -#if __cplusplus < 201103L - // expected-error@-2 {{not superset}} // FIXME: We only delay instantiation in C++11 onwards. In C++98, something // weird happens: instantiation of B

fails because it references T before // it's instantiated, but the diagnostic is suppressed in @@ -193,20 +237,20 @@ namespace dr1330 { // dr1330: 4 c++11 // obviously a bad way to react to this situation; we should still producing // the "T has not yet been instantiated" error here, rather than giving // confusing errors later on. -#endif - void (B

::*bpf2)() throw(int) = &B

::f; // expected-error 0-1{{C++17}} expected-note 0-1{{noexcept}} -#if __cplusplus <= 201402L - // expected-error@-2 {{not superset}} -#else - // expected-warning@-4 {{not superset}} -#endif + void (B

::*bpf1)() throw(B

::T, int) = &B

::f; + // since-cxx17-error@-1 {{ISO C++17 does not allow dynamic exception specifications}} + // since-cxx17-note@-2 {{use 'noexcept(false)' instead}} + // cxx98-error@-3 {{target exception specification is not superset of source}} + + void (B

::*bpf2)() throw(int) = &B

::f; + // since-cxx17-error@-1 {{ISO C++17 does not allow dynamic exception specifications}} + // since-cxx17-note@-2 {{use 'noexcept(false)' instead}} + // cxx98-14-error@-3 {{target exception specification is not superset of source}} + // since-cxx17-warning@-4 {{target exception specification is not superset of source}} void (B

::*bpf3)() = &B

::f; void (B

::*bpf4)() throw() = &B

::f; -#if __cplusplus <= 201402L - // expected-error@-2 {{not superset}} -#else - // expected-error@-4 {{different exception specifications}} -#endif + // cxx98-14-error@-1 {{target exception specification is not superset of source}} + // since-cxx17-error@-2 {{cannot initialize a variable of type 'void (B

::*)() throw()' with an rvalue of type 'void (dr1330::B::*)() throw(T, typename P::type)': different exception specifications}} #if __cplusplus >= 201103L static_assert(noexcept(B

{ -#if __cplusplus < 201103L +#if __cplusplus == 199711L static const int n = 0; #else static const int n = *P; @@ -40,11 +40,13 @@ namespace dr2100 { // dr2100: 12 template struct B { static const int n = 1; int f() { - return Y::declared_later; // expected-error {{no member named 'declared_later'}} + return Y::declared_later; + // expected-error@-1 {{no member named 'declared_later' in 'dr2100::Y<1>'}} } int g() { static const int n = 2; - return Y::declared_later; // expected-error {{no member named 'declared_later'}} + return Y::declared_later; + // expected-error@-1 {{no member named 'declared_later' in 'dr2100::Y<2>'}} } }; template struct Y { @@ -55,10 +57,12 @@ namespace dr2100 { // dr2100: 12 namespace dr2103 { // dr2103: yes void f() { int a; - int &r = a; // expected-note {{here}} + int &r = a; // #dr2103-r struct Inner { void f() { - int &s = r; // expected-error {{enclosing function}} + int &s = r; + // expected-error@-1 {{reference to local variable 'r' declared in enclosing function 'dr2103::f'}} + // expected-note@#dr2103-r {{'r' declared here}} (void)s; } }; @@ -84,28 +88,46 @@ namespace dr2126 { // dr2126: 12 A &b = (A &)(const A &)A{1}; // const temporary A &&c = (A &&)(const A &)A{1}; // const temporary - A &&d = {1}; // non-const temporary expected-note {{here}} - const A &e = (A &)(A &&) A{1}; // non-const temporary expected-note {{here}} - A &&f = (A &&)(A &&) A{1}; // non-const temporary expected-note {{here}} + A &&d = {1}; // non-const temporary #dr21260-d + const A &e = (A &)(A &&) A{1}; // non-const temporary #dr21260-e + A &&f = (A &&)(A &&) A{1}; // non-const temporary #dr21260-f constexpr const A &g = {1}; // const temporary - constexpr A &&h = {1}; // non-const temporary expected-note {{here}} + constexpr A &&h = {1}; // non-const temporary #dr21260-h struct B { const A &a; }; - B i = {{1}}; // extending decl not usable in constant expr expected-note {{here}} - const B j = {{1}}; // extending decl not usable in constant expr expected-note {{here}} + B i = {{1}}; // extending decl not usable in constant expr #dr21260-i + const B j = {{1}}; // extending decl not usable in constant expr #dr21260-j constexpr B k = {{1}}; // extending decl usable in constant expr static_assert(a.n == 1, ""); static_assert(b.n == 1, ""); static_assert(c.n == 1, ""); - static_assert(d.n == 1, ""); // expected-error {{constant}} expected-note {{read of temporary}} - static_assert(e.n == 1, ""); // expected-error {{constant}} expected-note {{read of temporary}} - static_assert(f.n == 1, ""); // expected-error {{constant}} expected-note {{read of temporary}} + static_assert(d.n == 1, ""); + // since-cxx11-error@-1 {{static assertion expression is not an integral constant expression}} + // since-cxx11-note@-2 {{read of temporary is not allowed in a constant expression outside the expression that created the temporary}} + // since-cxx11-note@#dr21260-d {{temporary created here}} + static_assert(e.n == 1, ""); + // since-cxx11-error@-1 {{static assertion expression is not an integral constant expression}} + // since-cxx11-note@-2 {{read of temporary is not allowed in a constant expression outside the expression that created the temporary}} + // since-cxx11-note@#dr21260-e {{temporary created here}} + static_assert(f.n == 1, ""); + // since-cxx11-error@-1 {{static assertion expression is not an integral constant expression}} + // since-cxx11-note@-2 {{read of temporary is not allowed in a constant expression outside the expression that created the temporary}} + // since-cxx11-note@#dr21260-f {{temporary created here}} static_assert(g.n == 1, ""); - static_assert(h.n == 1, ""); // expected-error {{constant}} expected-note {{read of temporary}} - static_assert(i.a.n == 1, ""); // expected-error {{constant}} expected-note {{read of non-constexpr variable}} - static_assert(j.a.n == 1, ""); // expected-error {{constant}} expected-note {{read of temporary}} + static_assert(h.n == 1, ""); + // since-cxx11-error@-1 {{static assertion expression is not an integral constant expression}} + // since-cxx11-note@-2 {{read of temporary is not allowed in a constant expression outside the expression that created the temporary}} + // since-cxx11-note@#dr21260-h {{temporary created here}} + static_assert(i.a.n == 1, ""); + // since-cxx11-error@-1 {{static assertion expression is not an integral constant expression}} + // since-cxx11-note@-2 {{read of non-constexpr variable 'i' is not allowed in a constant expression}} + // since-cxx11-note@#dr21260-i {{declared here}} + static_assert(j.a.n == 1, ""); + // since-cxx11-error@-1 {{static assertion expression is not an integral constant expression}} + // since-cxx11-note@-2 {{read of temporary is not allowed in a constant expression outside the expression that created the temporary}} + // since-cxx11-note@#dr21260-j {{temporary created here}} static_assert(k.a.n == 1, ""); #endif } @@ -128,19 +150,27 @@ struct B{}; void foo() { struct A *b = (1 == 1) ? new struct A : new struct A; - struct S *a = (1 == 1) ? new struct S : new struct S; // expected-error 2{{allocation of incomplete type}} // expected-note 2{{forward}} + struct S *a = (1 == 1) ? new struct S : new struct S; + // expected-error@-1 {{allocation of incomplete type 'struct S'}} + // expected-note@-2 {{forward declaration of 'S'}} + // expected-error@-3 {{allocation of incomplete type 'struct S'}} + // expected-note@-4 {{forward declaration of 'S'}} #if __cplusplus >= 201103L A *aa = new struct A{}; B *bb = new struct B{}; - (void)new struct C{}; // expected-error {{allocation of incomplete type }} // expected-note {{forward}} + (void)new struct C{}; + // since-cxx11-error@-1 {{allocation of incomplete type 'struct C'}} + // since-cxx11-note@-2 {{forward declaration of 'C'}} struct A *c = (1 == 1) ? new struct A {} : new struct A {}; - alignof(struct D{}); // expected-error {{cannot be defined in a type specifier}} + alignof(struct D{}); + // since-cxx11-error@-1 {{'D' cannot be defined in a type specifier}} #endif - sizeof(struct E{}); // expected-error {{cannot be defined in a type specifier}} + sizeof(struct E{}); + // expected-error@-1 {{'E' cannot be defined in a type specifier}} } } @@ -149,7 +179,8 @@ namespace dr2157 { // dr2157: 11 #if __cplusplus >= 201103L enum E : int; struct X { - enum dr2157::E : int(); // expected-error {{only allows ':' in member enumeration declaration to introduce a fixed underlying type}} + enum dr2157::E : int(); + // since-cxx11-error@-1 {{ISO C++ only allows ':' in member enumeration declaration to introduce a fixed underlying type, not an anonymous bit-field}} }; #endif } @@ -159,11 +190,13 @@ namespace dr2157 { // dr2157: 11 namespace dr2170 { // dr2170: 9 #if __cplusplus >= 201103L void f() { - constexpr int arr[3] = {1, 2, 3}; // expected-note {{here}} + constexpr int arr[3] = {1, 2, 3}; // #dr2170-arr struct S { int get(int n) { return arr[n]; } - const int &get_ref(int n) { return arr[n]; } // expected-error {{enclosing function}} - // FIXME: expected-warning@-1 {{reference to stack}} + const int &get_ref(int n) { return arr[n]; } + // since-cxx11-warning@-1 {{reference to stack memory associated with local variable 'arr' returned}} FIXME + // since-cxx11-error@-2 {{reference to local variable 'arr' declared in enclosing function 'dr2170::f'}} + // since-cxx11-note@#dr2170-arr {{'arr' declared here}} }; } #endif @@ -198,22 +231,32 @@ static_assert(!__is_trivially_assignable(NonConstCopy &&, NonConstCopy &&), ""); namespace dr2180 { // dr2180: yes class A { - A &operator=(const A &); // expected-note 0-2{{here}} - A &operator=(A &&); // expected-note 0-2{{here}} expected-error 0-1{{extension}} + A &operator=(const A &); // #dr2180-A-copy + A &operator=(A &&); // #dr2180-A-move + // cxx98-error@-1 {{rvalue references are a C++11 extension}} }; - struct B : virtual A { + struct B : virtual A { // #dr2180-B B &operator=(const B &); - B &operator=(B &&); // expected-error 0-1{{extension}} + B &operator=(B &&); + // cxx98-error@-1 {{rvalue references are a C++11 extension}} virtual void foo() = 0; }; -#if __cplusplus < 201103L - B &B::operator=(const B&) = default; // expected-error {{private member}} expected-error {{extension}} expected-note {{here}} - B &B::operator=(B&&) = default; // expected-error {{private member}} expected-error 2{{extension}} expected-note {{here}} -#else - B &B::operator=(const B&) = default; // expected-error {{would delete}} expected-note@-9{{inaccessible copy assignment}} - B &B::operator=(B&&) = default; // expected-error {{would delete}} expected-note@-10{{inaccessible move assignment}} -#endif + B &B::operator=(const B&) = default; // #dr2180-B-copy + // cxx98-error@-1 {{defaulted function definitions are a C++11 extension}} + // cxx98-error@-2 {{'operator=' is a private member of 'dr2180::A'}} + // cxx98-note@-3 {{in defaulted copy assignment operator for 'dr2180::B' first required here}} + // cxx98-note@#dr2180-A-copy {{implicitly declared private here}} + // since-cxx11-error@#dr2180-B-copy {{defaulting this copy assignment operator would delete it after its first declaration}} + // since-cxx11-note@#dr2180-B {{copy assignment operator of 'B' is implicitly deleted because base class 'A' has an inaccessible copy assignment operator}} + B &B::operator=(B&&) = default; // #dr2180-B-move + // cxx98-error@-1 {{rvalue references are a C++11 extension}} + // cxx98-error@-2 {{defaulted function definitions are a C++11 extension}} + // cxx98-error@-3 {{'operator=' is a private member of 'dr2180::A'}} + // cxx98-note@-4 {{in defaulted move assignment operator for 'dr2180::B' first required here}} + // cxx98-note@#dr2180-A-move {{implicitly declared private here}} + // since-cxx11-error@#dr2180-B-move {{defaulting this move assignment operator would delete it after its first declaration}} + // since-cxx11-note@#dr2180-B {{move assignment operator of 'B' is implicitly deleted because base class 'A' has an inaccessible move assignment operator}} } namespace dr2199 { // dr2199: 3.8 diff --git a/clang/test/CXX/drs/dr22xx.cpp b/clang/test/CXX/drs/dr22xx.cpp index cd849443b1119bac90c7e62a736584ddb923e55e..19518247b5289c3921a320eab4aa5f5065bd3477 100644 --- a/clang/test/CXX/drs/dr22xx.cpp +++ b/clang/test/CXX/drs/dr22xx.cpp @@ -1,14 +1,19 @@ -// RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++1z -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -verify=expected -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors + #if __cplusplus >= 201103L namespace dr2211 { // dr2211: 8 void f() { int a; - auto f = [a](int a) { (void)a; }; // expected-error {{a lambda parameter cannot shadow an explicitly captured entity}} - // expected-note@-1{{variable 'a' is explicitly captured here}} + auto f = [a](int a) { (void)a; }; + // since-cxx11-error@-1 {{a lambda parameter cannot shadow an explicitly captured entity}} + // since-cxx11-note@-2 {{variable 'a' is explicitly captured here}} auto g = [=](int a) { (void)a; }; } } @@ -24,9 +29,12 @@ struct A; namespace dr2229 { // dr2229: 7 struct AnonBitfieldQualifiers { - const unsigned : 1; // expected-error {{anonymous bit-field cannot have qualifiers}} - volatile unsigned : 1; // expected-error {{anonymous bit-field cannot have qualifiers}} - const volatile unsigned : 1; // expected-error {{anonymous bit-field cannot have qualifiers}} + const unsigned : 1; + // expected-error@-1 {{anonymous bit-field cannot have qualifiers}} + volatile unsigned : 1; + // expected-error@-1 {{anonymous bit-field cannot have qualifiers}} + const volatile unsigned : 1; + // expected-error@-1 {{anonymous bit-field cannot have qualifiers}} unsigned : 1; const unsigned i1 : 1; @@ -98,7 +106,8 @@ namespace MultilevelSpecialization { template void f(int i = 0, int (&... arr)[V]); }; template<> template - void B::f(int i, int (&arr1)[a], int (&arr2)[b]) {} // expected-error {{does not match}} + void B::f(int i, int (&arr1)[a], int (&arr2)[b]) {} + // since-cxx11-error@-1 {{out-of-line definition of 'f' does not match any declaration in 'dr2233::MultilevelSpecialization::B'}} template<> template<> void B::f<1, 1>(int i, int (&arr1a)[1], int (&arr2a)[1]) {} } @@ -134,10 +143,10 @@ struct C { explicit operator D(); } c; B b1(a); const B &b2{a}; // FIXME ill-formed const B &b3(a); -// expected-error@-1 {{no viable conversion from 'struct A' to 'const B'}} -// expected-note@#dr2267-struct-B {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'struct A' to 'const B &' for 1st argument}} -// expected-note@#dr2267-struct-B {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'struct A' to 'B &&' for 1st argument}} -// expected-note@#dr2267-struct-B {{explicit constructor is not a candidate}} +// since-cxx11-error@-1 {{no viable conversion from 'struct A' to 'const B'}} +// since-cxx11-note@#dr2267-struct-B {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'struct A' to 'const B &' for 1st argument}} +// since-cxx11-note@#dr2267-struct-B {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'struct A' to 'B &&' for 1st argument}} +// since-cxx11-note@#dr2267-struct-B {{explicit constructor is not a candidate}} D d1(c); const D &d2{c}; // FIXME ill-formed diff --git a/clang/test/CXX/drs/dr2354.cpp b/clang/test/CXX/drs/dr2354.cpp deleted file mode 100644 index 3efb0ba555669071aa5ae1ff473a2f01825aa5e3..0000000000000000000000000000000000000000 --- a/clang/test/CXX/drs/dr2354.cpp +++ /dev/null @@ -1,10 +0,0 @@ -// RUN: %clang_cc1 -x c++ -verify %s - -// dr2354: 15 - -namespace DR2354 { - -enum alignas(64) A {}; // expected-error {{'alignas' attribute cannot be applied to an enumeration}} -enum struct alignas(64) B {}; // expected-error {{'alignas' attribute cannot be applied to an enumeration}} - -} // namespace DR2354 diff --git a/clang/test/CXX/drs/dr2390.cpp b/clang/test/CXX/drs/dr2390.cpp index d8ab1e9a1b3853bd60f38a186fe8294c334a776e..3931365b568cebfc2a87a2c9278fda69b84796f8 100644 --- a/clang/test/CXX/drs/dr2390.cpp +++ b/clang/test/CXX/drs/dr2390.cpp @@ -1,6 +1,6 @@ // RUN: %clang_cc1 -E -P %s -o - | FileCheck %s -// dr2390: yes +// dr2390: 14 namespace PR48462 { // Test that macro expansion of the builtin argument works. diff --git a/clang/test/CXX/drs/dr23xx.cpp b/clang/test/CXX/drs/dr23xx.cpp index 6cb10067739f8eb415439cd964b57ef2b4e781cf..9ced61d2aae30dc5e4ebf0239802f9d4dbf419ce 100644 --- a/clang/test/CXX/drs/dr23xx.cpp +++ b/clang/test/CXX/drs/dr23xx.cpp @@ -1,9 +1,10 @@ -// RUN: %clang_cc1 -std=c++98 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors 2>&1 -// RUN: %clang_cc1 -std=c++11 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s -// RUN: %clang_cc1 -std=c++14 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s -// RUN: %clang_cc1 -std=c++17 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s -// RUN: %clang_cc1 -std=c++20 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s -// RUN: %clang_cc1 -std=c++23 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s +// RUN: %clang_cc1 -std=c++98 %s -verify=expected -fexceptions -fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s +// RUN: %clang_cc1 -std=c++11 %s -verify=expected,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s +// RUN: %clang_cc1 -std=c++14 %s -verify=expected,since-cxx11,since-cxx14 -fexceptions -fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s +// RUN: %clang_cc1 -std=c++17 %s -verify=expected,since-cxx11,since-cxx14,since-cxx17 -fexceptions -fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s +// RUN: %clang_cc1 -std=c++20 %s -verify=expected,since-cxx11,since-cxx14,since-cxx17,since-cxx20 -fexceptions -fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s +// RUN: %clang_cc1 -std=c++23 %s -verify=expected,since-cxx11,since-cxx14,since-cxx17,since-cxx20 -fexceptions -fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s +// RUN: %clang_cc1 -std=c++2c %s -verify=expected,since-cxx11,since-cxx14,since-cxx17,since-cxx20 -fexceptions -fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s #if __cplusplus >= 201103L namespace dr2303 { // dr2303: 12 @@ -14,8 +15,14 @@ struct A<> {}; template struct A : A {}; struct B : A {}; -struct C : A, A {}; // expected-warning {{direct base 'A' is inaccessible}} -struct D : A, A {}; // expected-warning {{direct base 'A' is inaccessible}} +struct C : A, A {}; +/* since-cxx11-warning@-1 {{direct base 'A' is inaccessible due to ambiguity: + struct dr2303::C -> A -> A + struct dr2303::C -> A}} */ +struct D : A, A {}; +/* since-cxx11-warning@-1 {{direct base 'A' is inaccessible due to ambiguity: + struct dr2303::D -> A + struct dr2303::D -> A -> A}} */ struct E : A {}; struct F : B, E {}; @@ -32,7 +39,10 @@ void g() { f2(&b); f(C{}); f(D{}); - f(F{}); // expected-error {{ambiguous conversion from derived class}} + f(F{}); + /* since-cxx11-error@-1 {{ambiguous conversion from derived class 'const F' to base class 'const A': + struct dr2303::F -> B -> A + struct dr2303::F -> E -> A}} */ } } //namespace dr2303 #endif @@ -65,8 +75,10 @@ namespace dr2352 { // dr2352: 10 int *const *const &f2() { return p; } int **const &f3() { return p; } - const int **const &f4() { return p; } // expected-error {{reference to type 'const int **const' could not bind to an lvalue of type 'int **'}} - const int *const *&f5() { return p; } // expected-error {{binding reference of type 'const int *const *' to value of type 'int **' not permitted due to incompatible qualifiers}} + const int **const &f4() { return p; } + // expected-error@-1 {{reference to type 'const int **const' could not bind to an lvalue of type 'int **'}} + const int *const *&f5() { return p; } + // expected-error@-1 {{binding reference of type 'const int *const *' to value of type 'int **' not permitted due to incompatible qualifiers}} // FIXME: We permit this as a speculative defect resolution, allowing // qualification conversions when forming a glvalue conditional expression. @@ -76,7 +88,8 @@ namespace dr2352 { // dr2352: 10 // FIXME: Should we compute the composite pointer type here and produce an // lvalue of type 'const int *const * const'? const int * const * r; - void *y = &(true ? p : r); // expected-error {{rvalue of type 'const int *const *'}} + void *y = &(true ? p : r); + // expected-error@-1 {{rvalue of type 'const int *const *'}} // FIXME: We order these as a speculative defect resolution. void f(const int * const * const &r); @@ -124,12 +137,22 @@ namespace dr2353 { // dr2353: 9 #pragma clang __debug dump not_use_2 } +namespace dr2354 { // dr2354: 15 +#if __cplusplus >= 201103L +enum alignas(64) A {}; +// since-cxx11-error@-1 {{'alignas' attribute cannot be applied to an enumeration}} +enum struct alignas(64) B {}; +// since-cxx11-error@-1 {{'alignas' attribute cannot be applied to an enumeration}} +#endif +} // namespace dr2354 + #if __cplusplus >= 201402L namespace dr2358 { // dr2358: 16 void f2() { int i = 1; void g1(int = [xxx=1] { return xxx; }()); // OK - void g2(int = [xxx=i] { return xxx; }()); // expected-error {{default argument references local variable 'i' of enclosing function}} + void g2(int = [xxx=i] { return xxx; }()); + // since-cxx14-error@-1 {{default argument references local variable 'i' of enclosing function}} } } #endif @@ -148,7 +171,7 @@ class C { }; } // namespace dr2370 -#if __cplusplus >= 201707L +#if __cplusplus >= 201702L // Otherwise, if the qualified-id std::tuple_size names a complete class // type **with a member value**, the expression std::tuple_size::value shall // be a well-formed integral constant expression @@ -165,7 +188,8 @@ template <> struct std::tuple_size { } // namespace std namespace dr2386 { void no_value() { auto [x, y] = Bad1(); } -void wrong_value() { auto [x, y] = Bad2(); } // expected-error {{decomposes into 42 elements}} +void wrong_value() { auto [x, y] = Bad2(); } +// since-cxx17-error@-1 {{type 'Bad2' decomposes into 42 elements, but only 2 names were provided}} } // namespace dr2386 #endif @@ -177,7 +201,8 @@ namespace dr2387 { // dr2387: 9 extern template int a<0>; // ok template static int b = 0; - extern template int b<0>; // expected-error {{internal linkage}} + extern template int b<0>; + // since-cxx14-error@-1 {{explicit instantiation declaration of 'b<0>' with internal linkage}} template const int c = 0; extern template const int c<0>; // ok, has external linkage despite 'const' diff --git a/clang/test/CXX/drs/dr2406.cpp b/clang/test/CXX/drs/dr2406.cpp deleted file mode 100644 index 7ea0870fb70b380216aa5df74b9d4da813502d3e..0000000000000000000000000000000000000000 --- a/clang/test/CXX/drs/dr2406.cpp +++ /dev/null @@ -1,30 +0,0 @@ -// RUN: %clang_cc1 -x c++ %s -verify - -// dr2406: yes - -void fallthrough(int n) { - void g(), h(), i(); - switch (n) { - case 1: - case 2: - g(); - [[fallthrough]]; - case 3: // warning on fallthrough discouraged - do { - [[fallthrough]]; // expected-error {{fallthrough annotation does not directly precede switch label}} - } while (false); - case 6: - do { - [[fallthrough]]; // expected-error {{fallthrough annotation does not directly precede switch label}} - } while (n); - case 7: - while (false) { - [[fallthrough]]; // expected-error {{fallthrough annotation does not directly precede switch label}} - } - case 5: - h(); - case 4: // implementation may warn on fallthrough - i(); - [[fallthrough]]; // expected-error {{fallthrough annotation does not directly precede switch label}} - } -} diff --git a/clang/test/CXX/drs/dr24xx.cpp b/clang/test/CXX/drs/dr24xx.cpp index 3fd8539be53d810d251bcd4b13a2fa99dc9f882d..b34ceb420788fcd7a71669fa558f87c24eb12444 100644 --- a/clang/test/CXX/drs/dr24xx.cpp +++ b/clang/test/CXX/drs/dr24xx.cpp @@ -1,9 +1,52 @@ -// RUN: %clang_cc1 -std=c++20 %s -verify -// RUN: %clang_cc1 -std=c++23 %s -verify +// RUN: %clang_cc1 -std=c++98 %s -verify=expected +// RUN: %clang_cc1 -std=c++11 %s -verify=expected +// RUN: %clang_cc1 -std=c++14 %s -verify=expected +// RUN: %clang_cc1 -std=c++17 %s -verify=expected,since-cxx17 +// RUN: %clang_cc1 -std=c++20 %s -verify=expected,since-cxx17 +// RUN: %clang_cc1 -std=c++23 %s -verify=expected,since-cxx17 +// RUN: %clang_cc1 -std=c++2c %s -verify=expected,since-cxx17 + +#if __cplusplus <= 201402L // expected-no-diagnostics +#endif + +namespace dr2406 { // dr2406: 5 +#if __cplusplus >= 201703L +void fallthrough(int n) { + void g(), h(), i(); + switch (n) { + case 1: + case 2: + g(); + [[fallthrough]]; + case 3: // warning on fallthrough discouraged + do { + [[fallthrough]]; + // since-cxx17-error@-1 {{fallthrough annotation does not directly precede switch label}} + } while (false); + case 6: + do { + [[fallthrough]]; + // since-cxx17-error@-1 {{fallthrough annotation does not directly precede switch label}} + } while (n); + case 7: + while (false) { + [[fallthrough]]; + // since-cxx17-error@-1 {{fallthrough annotation does not directly precede switch label}} + } + case 5: + h(); + case 4: // implementation may warn on fallthrough + i(); + [[fallthrough]]; + // since-cxx17-error@-1 {{fallthrough annotation does not directly precede switch label}} + } +} +#endif +} namespace dr2450 { // dr2450: 18 drafting -#if __cplusplus > 202002L +#if __cplusplus >= 202302L struct S {int a;}; template void f(){} @@ -17,7 +60,7 @@ f<{.a= 0}>(); } namespace dr2459 { // dr2459: 18 drafting -#if __cplusplus > 202002L +#if __cplusplus >= 202302L struct A { constexpr A(float) {} }; diff --git a/clang/test/CXX/drs/dr25xx.cpp b/clang/test/CXX/drs/dr25xx.cpp index 3644e4c328b1bcbcab69b5d494eb6794d50e05b2..8c34b03c22d5b1af7c1340fc1d819f5ca1c748b7 100644 --- a/clang/test/CXX/drs/dr25xx.cpp +++ b/clang/test/CXX/drs/dr25xx.cpp @@ -1,23 +1,23 @@ -// RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors - -#if __cplusplus < 201103L +// RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -verify=expected -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -verify=expected,cxx11-14,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -verify=expected,cxx11-14,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11,since-cxx20 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11,since-cxx20,since-cxx23 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11,since-cxx20,since-cxx23 -fexceptions -fcxx-exceptions -pedantic-errors + +#if __cplusplus == 199711L // expected-no-diagnostics #endif -namespace dr2516 { // dr2516: yes +namespace dr2516 { // dr2516: 3.0 // NB: reusing 1482 test #if __cplusplus >= 201103L template struct S { typedef char I; }; enum E2 : S::I { e }; -// expected-error@-1 {{use of undeclared identifier 'E2'}} +// since-cxx11-error@-1 {{use of undeclared identifier 'E2'}} #endif } // namespace dr2516 @@ -27,24 +27,24 @@ namespace dr2518 { // dr2518: 17 template void f(T t) { if constexpr (sizeof(T) != sizeof(int)) { -#if __cplusplus < 201703L -// expected-error@-2 {{constexpr if is a C++17 extension}} -#endif - static_assert(false, "must be int-sized"); // expected-error {{must be int-size}} + // cxx11-14-error@-1 {{constexpr if is a C++17 extension}} + static_assert(false, "must be int-sized"); + // since-cxx11-error@-1 {{static assertion failed: must be int-sized}} + // since-cxx11-note@#dr2518-f-c {{in instantiation of function template specialization 'dr2518::f' requested here}} } } void g(char c) { f(0); - f(c); // expected-note {{requested here}} + f(c); // #dr2518-f-c } template struct S { - static_assert(false); // expected-error {{static assertion failed}} -#if __cplusplus < 201703L -// expected-error@-2 {{'static_assert' with no message is a C++17 extension}} -#endif + static_assert(false); + // cxx11-14-error@-1 {{'static_assert' with no message is a C++17 extension}} + // since-cxx11-error@-2 {{static assertion failed}} + // since-cxx11-note@#dr2518-S-double {{in instantiation of template class 'dr2518::S' requested here}} }; template <> @@ -56,7 +56,7 @@ struct S {}; int test_specialization() { S s1; S s2; - S s3; // expected-note {{in instantiation of template class 'dr2518::S' requested here}} + S s3; // #dr2518-S-double } #endif @@ -67,16 +67,16 @@ namespace dr2521 { // dr2521: 17 #pragma clang diagnostic push #pragma clang diagnostic warning "-Wdeprecated-literal-operator" long double operator"" _\u03C0___(long double); -// expected-warning@-1 {{identifier '_π___' preceded by whitespace in a literal operator declaration is deprecated}} -// expected-warning@-2 {{user-defined literal suffixes containing '__' are reserved}} +// since-cxx11-warning@-1 {{identifier '_π___' preceded by whitespace in a literal operator declaration is deprecated}} +// since-cxx11-warning@-2 {{user-defined literal suffixes containing '__' are reserved}} template decltype(sizeof 0) operator"" _div(); -// expected-warning@-1 {{identifier '_div' preceded by whitespace in a literal operator declaration is deprecated}} +// since-cxx11-warning@-1 {{identifier '_div' preceded by whitespace in a literal operator declaration is deprecated}} using ::dr2521::operator"" _\u03C0___; using ::dr2521::operator""_div; -// expected-warning@-2 {{identifier '_π___' preceded by whitespace in a literal operator declaration is deprecated}} +// since-cxx11-warning@-2 {{identifier '_π___' preceded by whitespace in a literal operator declaration is deprecated}} #pragma clang diagnostic pop #endif } // namespace dr2521 @@ -85,12 +85,16 @@ using ::dr2521::operator""_div; #if __cplusplus >= 202302L namespace dr2553 { // dr2553: 18 struct B { - virtual void f(this B&); // expected-error {{an explicit object parameter cannot appear in a virtual function}} - static void f(this B&); // expected-error {{an explicit object parameter cannot appear in a static function}} - virtual void g(); // expected-note {{here}} + virtual void f(this B&); + // since-cxx23-error@-1 {{an explicit object parameter cannot appear in a virtual function}} + static void f(this B&); + // since-cxx23-error@-1 {{an explicit object parameter cannot appear in a static function}} + virtual void g(); // #dr2553-g }; struct D : B { - void g(this D&); // expected-error {{an explicit object parameter cannot appear in a virtual function}} + void g(this D&); + // since-cxx23-error@-1 {{an explicit object parameter cannot appear in a virtual function}} + // since-cxx23-note@#dr2553-g {{overridden virtual function is here}} }; } @@ -99,19 +103,25 @@ struct D : B { #if __cplusplus >= 202302L namespace dr2554 { // dr2554: 18 review struct B { - virtual void f(); // expected-note 3{{here}} + virtual void f(); // #dr2554-g }; struct D : B { - void f(this D&); // expected-error {{an explicit object parameter cannot appear in a virtual function}} + void f(this D&); + // since-cxx23-error@-1 {{an explicit object parameter cannot appear in a virtual function}} + // since-cxx23-note@#dr2554-g {{overridden virtual function is here}} }; struct D2 : B { - void f(this B&); // expected-error {{an explicit object parameter cannot appear in a virtual function}} + void f(this B&); + // since-cxx23-error@-1 {{an explicit object parameter cannot appear in a virtual function}} + // since-cxx23-note@#dr2554-g {{overridden virtual function is here}} }; struct T {}; struct D3 : B { - void f(this T&); // expected-error {{an explicit object parameter cannot appear in a virtual function}} + void f(this T&); + // since-cxx23-error@-1 {{an explicit object parameter cannot appear in a virtual function}} + // since-cxx23-note@#dr2554-g {{overridden virtual function is here}} }; } @@ -153,48 +163,48 @@ namespace dr2565 { // dr2565: 16 static_assert(is_referenceable::value); template - concept TwoParams = requires (T *a, U b){ true;}; // #TPC + concept TwoParams = requires (T *a, U b){ true;}; // #dr2565-TPC template - requires TwoParams // #TPSREQ + requires TwoParams // #dr2565-TPSREQ struct TwoParamsStruct{}; using TPSU = TwoParamsStruct; - // expected-error@-1{{constraints not satisfied for class template 'TwoParamsStruct'}} - // expected-note@#TPSREQ{{because 'TwoParams' evaluated to false}} - // expected-note@#TPC{{because 'b' would be invalid: argument may not have 'void' type}} + // since-cxx20-error@-1 {{constraints not satisfied for class template 'TwoParamsStruct'}} + // since-cxx20-note@#dr2565-TPSREQ {{because 'TwoParams' evaluated to false}} + // since-cxx20-note@#dr2565-TPC {{because 'b' would be invalid: argument may not have 'void' type}} template - concept Variadic = requires (U* ... a, T b){ true;}; // #VC + concept Variadic = requires (U* ... a, T b){ true;}; // #dr2565-VC template - requires Variadic // #VSREQ + requires Variadic // #dr2565-VSREQ struct VariadicStruct{}; using VSU = VariadicStruct; - // expected-error@-1{{constraints not satisfied for class template 'VariadicStruct'}} - // expected-note@#VSREQ{{because 'Variadic' evaluated to false}} - // expected-note@#VC{{because 'b' would be invalid: argument may not have 'void' type}} + // since-cxx20-error@-1 {{constraints not satisfied for class template 'VariadicStruct'}} + // since-cxx20-note@#dr2565-VSREQ {{because 'Variadic' evaluated to false}} + // since-cxx20-note@#dr2565-VC {{because 'b' would be invalid: argument may not have 'void' type}} template - // expected-error@+1 {{unknown type name 'ErrorRequires'}} concept ErrorRequires = requires (ErrorRequires auto x) { + // since-cxx20-error@-1 {{unknown type name 'ErrorRequires'}} x; }; static_assert(ErrorRequires); - // expected-error@-1{{static assertion failed}} - // expected-note@-2{{because substituted constraint expression is ill-formed: constraint depends on a previously diagnosed expression}} + // since-cxx20-error@-1 {{static assertion failed}} + // since-cxx20-note@-2 {{because substituted constraint expression is ill-formed: constraint depends on a previously diagnosed expression}} template - // expected-error@+2 {{unknown type name 'NestedErrorInRequires'}} concept NestedErrorInRequires = requires (T x) { requires requires (NestedErrorInRequires auto y) { + // since-cxx20-error@-1 {{unknown type name 'NestedErrorInRequires'}} y; }; }; static_assert(NestedErrorInRequires); - // expected-error@-1{{static assertion failed}} - // expected-note@-2{{because substituted constraint expression is ill-formed: constraint depends on a previously diagnosed expression}} + // expected-error@-1 {{static assertion failed}} + // expected-note@-2 {{because substituted constraint expression is ill-formed: constraint depends on a previously diagnosed expression}} #endif } diff --git a/clang/test/CXX/drs/dr26xx.cpp b/clang/test/CXX/drs/dr26xx.cpp index 8517cd5872b183dec666244c681f9e944621c670..dd4bb1ff6ae2e1ed2b2ad15262f9f73fba2826bf 100644 --- a/clang/test/CXX/drs/dr26xx.cpp +++ b/clang/test/CXX/drs/dr26xx.cpp @@ -1,8 +1,14 @@ -// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -verify -// RUN: %clang_cc1 -std=c++2b -triple x86_64-unknown-unknown %s -verify +// RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -verify=expected +// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11,cxx11 +// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11 +// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11 +// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11,since-cxx20 +// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11,since-cxx20,since-cxx23 +// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11,since-cxx20,since-cxx23 -namespace dr2621 { // dr2621: yes +namespace dr2621 { // dr2621: 16 +#if __cplusplus >= 202002L enum class E { a }; namespace One { using E_t = E; @@ -12,33 +18,39 @@ auto v = a; namespace Two { using dr2621::E; int E; // we see this -using enum E; // expected-error {{unknown type name E}} +using enum E; +// since-cxx20-error@-1 {{unknown type name E}} } +#endif } namespace dr2628 { // dr2628: no open // this was reverted for the 16.x release // due to regressions, see the issue for more details: // https://github.com/llvm/llvm-project/issues/60777 - +#if __cplusplus >= 202002L template struct foo { // The expected notes below should be removed when dr2628 is fully implemented again - constexpr foo() requires (!A && !B) = delete; // expected-note {{candidate function [with A = false, B = false]}} #DR2628_CTOR - constexpr foo() requires (A || B) = delete; // expected-note {{candidate function [with A = false, B = false]}} + constexpr foo() requires (!A && !B) = delete; // #dr2628-ctor-1 + constexpr foo() requires (A || B) = delete; // #dr2628-ctor-2 }; void f() { // The FIXME's below should be the expected errors when dr2628 is // fully implemented again. - // FIXME-expected-error {{call to deleted}} - foo fooable; // expected-error {{ambiguous deduction for template arguments of 'foo'}} - // FIXME-expected-note@#DR2628_CTOR {{marked deleted here}} + foo fooable; // #dr2628-fooable + // since-cxx20-error@-1 {{ambiguous deduction for template arguments of 'foo'}} + // since-cxx20-note@#dr2628-ctor-1 {{candidate function [with A = false, B = false]}} + // since-cxx20-note@#dr2628-ctor-2 {{candidate function [with A = false, B = false]}} + // FIXME-since-cxx20-error@#dr2628-fooable {{call to deleted}} + // FIXME-since-cxx20-note@#dr2628-ctor {{marked deleted here}} } - +#endif } namespace dr2631 { // dr2631: 16 +#if __cplusplus >= 202002L constexpr int g(); consteval int f() { return g(); @@ -52,9 +64,11 @@ namespace dr2631 { // dr2631: 16 int test() { return k(); } +#endif } namespace dr2635 { // dr2635: 16 +#if __cplusplus >= 202002L template concept UnaryC = true; template @@ -67,66 +81,79 @@ template T get_T(); void use() { - // expected-error@+1{{decomposition declaration cannot be declared with constrained 'auto'}} UnaryC auto [a, b] = get_S(); - // expected-error@+1{{decomposition declaration cannot be declared with constrained 'auto'}} + // since-cxx20-error@-1 {{decomposition declaration cannot be declared with constrained 'auto'}} BinaryC auto [c, d] = get_S(); + // since-cxx20-error@-1 {{decomposition declaration cannot be declared with constrained 'auto'}} } template void TemplUse() { - // expected-error@+1{{decomposition declaration cannot be declared with constrained 'auto'}} UnaryC auto [a, b] = get_T(); - // expected-error@+1{{decomposition declaration cannot be declared with constrained 'auto'}} + // since-cxx20-error@-1 {{decomposition declaration cannot be declared with constrained 'auto'}} BinaryC auto [c, d] = get_T(); + // since-cxx20-error@-1 {{decomposition declaration cannot be declared with constrained 'auto'}} } +#endif } - // dr2636: na +// dr2636: na namespace dr2640 { // dr2640: 16 -int \N{Λ} = 0; //expected-error {{'Λ' is not a valid Unicode character name}} \ - //expected-error {{expected unqualified-id}} -const char* emoji = "\N{🤡}"; // expected-error {{'🤡' is not a valid Unicode character name}} \ - // expected-note 5{{did you mean}} +int \N{Λ} = 0; +// expected-error@-1 {{'Λ' is not a valid Unicode character name}} +// expected-error@-2 {{expected unqualified-id}} +const char* emoji = "\N{🤡}"; +// expected-error@-1 {{'🤡' is not a valid Unicode character name}} +// expected-note@-2 {{did you mean OX ('🐂' U+1F402)?}} +// expected-note@-3 {{did you mean ANT ('🐜' U+1F41C)?}} +// expected-note@-4 {{did you mean ARC ('⌒' U+2312)?}} +// expected-note@-5 {{did you mean AXE ('🪓' U+1FA93)?}} +// expected-note@-6 {{did you mean BAT ('🦇' U+1F987)?}} #define z(x) 0 #define dr2640_a z( -int x = dr2640_a\N{abc}); // expected-error {{'abc' is not a valid Unicode character name}} -int y = dr2640_a\N{LOTUS}); // expected-error {{character not allowed in an identifier}} \ - // expected-error {{use of undeclared identifier 'dr2640_a🪷'}} \ - // expected-error {{extraneous ')' before ';'}} -} - - // dr2642: na - -namespace dr2644 { // dr2644: yes - -auto z = [a = 42](int a) { // expected-error {{a lambda parameter cannot shadow an explicitly captured entity}} \ - // expected-note {{variable 'a' is explicitly captured here}} +int x = dr2640_a\N{abc}); +// expected-error@-1 {{'abc' is not a valid Unicode character name}} +int y = dr2640_a\N{LOTUS}); +// expected-error@-1 {{character not allowed in an identifier}} +// expected-error@-2 {{use of undeclared identifier 'dr2640_a🪷'}} +// expected-error@-3 {{extraneous ')' before ';'}} +} + +// dr2642: na + +namespace dr2644 { // dr2644: 8 +#if __cplusplus >= 201103L +auto z = [a = 42](int a) { +// cxx11-warning@-1 {{initialized lambda captures are a C++14 extension}} +// since-cxx11-error@-2 {{a lambda parameter cannot shadow an explicitly captured entity}} +// since-cxx11-note@-3 {{variable 'a' is explicitly captured here}} return 1; }; - +#endif } #if __cplusplus >= 202302L -namespace dr2650 { // dr2650: yes +namespace dr2650 { // dr2650: 17 template struct S {}; -template int f(S*); // expected-note {{type 'X' of non-type template parameter is not a structural type}} +template int f(S*); // #dr2650-f class X { int m; }; -int i0 = f(0); //expected-error {{no matching function for call to 'f'}} +int i0 = f(0); +// since-cxx23-error@-1 {{no matching function for call to 'f'}} +// since-cxx23-note@#dr2650-f {{type 'X' of non-type template parameter is not a structural type}} } #endif #if __cplusplus >= 202302L namespace dr2653 { // dr2653: 18 struct Test { void f(this const auto& = Test{}); }; - // expected-error@-1 {{the explicit object parameter cannot have a default argument}} + // since-cxx23-error@-1 {{the explicit object parameter cannot have a default argument}} auto L = [](this const auto& = Test{}){}; - // expected-error@-1 {{the explicit object parameter cannot have a default argument}} + // since-cxx23-error@-1 {{the explicit object parameter cannot have a default argument}} } #endif @@ -141,6 +168,7 @@ void f() { } namespace dr2681 { // dr2681: 17 +#if __cplusplus >= 202002L using size_t = decltype(sizeof(int)); template @@ -152,7 +180,7 @@ struct I { volatile T array[N]; }; template -struct J { // expected-note 3{{candidate}} +struct J { // #dr2681-J unsigned char array[N]; }; @@ -161,15 +189,24 @@ I i = { "def" }; static_assert(__is_same(decltype(h), H)); // Not H static_assert(__is_same(decltype(i), I)); -J j = { "ghi" }; // expected-error {{no viable constructor or deduction guide}} +J j = { "ghi" }; +// since-cxx20-error@-1 {{no viable constructor or deduction guide}} +// since-cxx20-note@#dr2681-J {{candidate template ignored: could not match 'J' against 'const char *'}} +// since-cxx20-note@#dr2681-J {{candidate template ignored: could not match 'const unsigned char' against 'const char'}} +// since-cxx20-note@#dr2681-J {{candidate function template not viable: requires 0 arguments, but 1 was provided}} +#endif } namespace dr2672 { // dr2672: 18 open +#if __cplusplus >= 202002L template -void f(T) requires requires { []() { T::invalid; } (); }; // expected-error{{type 'int' cannot be used prior to '::'}} - // expected-note@-1{{while substituting into a lambda expression here}} - // expected-note@-2{{in instantiation of requirement here}} - // expected-note@-3{{while substituting template arguments into constraint expression here}} +void f(T) requires requires { []() { T::invalid; } (); }; +// since-cxx20-error@-1 {{type 'int' cannot be used prior to '::' because it has no members}} +// since-cxx20-note@-2 {{while substituting into a lambda expression here}} +// since-cxx20-note@-3 {{in instantiation of requirement here}} +// since-cxx20-note@-4 {{while substituting template arguments into constraint expression here}} +// since-cxx20-note@#dr2672-f-0 {{while checking constraint satisfaction for template 'f' required here}} +// since-cxx20-note@#dr2672-f-0 {{in instantiation of function template specialization 'dr2672::f' requested here}} void f(...); template @@ -179,11 +216,12 @@ void bar(T) requires requires { void bar(...); void m() { - f(0); // expected-note {{while checking constraint satisfaction for template 'f' required here}} - // expected-note@-1 {{in instantiation of function template specialization}} + f(0); // #dr2672-f-0 bar(0); } +#endif } + #if __cplusplus >= 202302L namespace dr2687 { // dr2687: 18 struct S{ @@ -193,7 +231,8 @@ struct S{ }; void test() { - (&S::f)(1); // expected-error {{called object type 'void (dr2687::S::*)(int)' is not a function or function pointer}} + (&S::f)(1); + // since-cxx23-error@-1 {{called object type 'void (dr2687::S::*)(int)' is not a function or function pointer}} (&S::g)(1); (&S::h)(S(), 1); } diff --git a/clang/test/CXX/drs/dr27xx.cpp b/clang/test/CXX/drs/dr27xx.cpp index 5c7ce98f878da6b3679ff0e488634abd70005f86..4f7d0d6b44a83ec7844f1ccf5221158d9f23e9e8 100644 --- a/clang/test/CXX/drs/dr27xx.cpp +++ b/clang/test/CXX/drs/dr27xx.cpp @@ -1,6 +1,17 @@ -// RUN: %clang_cc1 -std=c++2c -verify %s +// RUN: %clang_cc1 -std=c++98 -verify=expected %s +// RUN: %clang_cc1 -std=c++11 -verify=expected %s +// RUN: %clang_cc1 -std=c++14 -verify=expected %s +// RUN: %clang_cc1 -std=c++17 -verify=expected %s +// RUN: %clang_cc1 -std=c++20 -verify=expected %s +// RUN: %clang_cc1 -std=c++23 -verify=expected,since-cxx23 %s +// RUN: %clang_cc1 -std=c++2c -verify=expected,since-cxx23,since-cxx26 %s + +#if __cplusplus <= 202002L +// expected-no-diagnostics +#endif namespace dr2789 { // dr2789: 18 open +#if __cplusplus >= 202302L template struct Base { constexpr void g(); // #dr2789-g1 @@ -23,11 +34,12 @@ struct S : Base, Base2 { void test() { S<> s; s.f(); - s.g(); // expected-error {{call to member function 'g' is ambiguous}} - // expected-note@#dr2789-g1 {{candidate function}} - // expected-note@#dr2789-g2 {{candidate function}} + s.g(); + // since-cxx23-error@-1 {{call to member function 'g' is ambiguous}} + // since-cxx23-note@#dr2789-g1 {{candidate function}} + // since-cxx23-note@#dr2789-g2 {{candidate function}} } - +#endif } namespace dr2798 { // dr2798: 17 drafting @@ -49,7 +61,8 @@ struct X { }; consteval X f() { return {}; } -static_assert(false, f().s); // expected-error {{static assertion failed: Hello}} +static_assert(false, f().s); +// since-cxx26-error@-1 {{static assertion failed: Hello}} #endif } // namespace dr2798 diff --git a/clang/test/CXX/drs/dr412.cpp b/clang/test/CXX/drs/dr412.cpp index 27bc7e5cf94e0cfe86a79b666a6fec5d223e7432..8ea29135d1df825481817858bf7f87cb3df6f8d7 100644 --- a/clang/test/CXX/drs/dr412.cpp +++ b/clang/test/CXX/drs/dr412.cpp @@ -1,9 +1,12 @@ // RUN: %clang_cc1 -std=c++98 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -DNOEXCEPT="throw()" -DBAD_ALLOC="throw(std::bad_alloc)" // RUN: %clang_cc1 -std=c++11 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -DNOEXCEPT=noexcept -DBAD_ALLOC= // RUN: %clang_cc1 -std=c++14 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -DNOEXCEPT=noexcept -DBAD_ALLOC= -// RUN: %clang_cc1 -std=c++1z %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -DNOEXCEPT=noexcept -DBAD_ALLOC= +// RUN: %clang_cc1 -std=c++17 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -DNOEXCEPT=noexcept -DBAD_ALLOC= +// RUN: %clang_cc1 -std=c++20 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -DNOEXCEPT=noexcept -DBAD_ALLOC= +// RUN: %clang_cc1 -std=c++23 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -DNOEXCEPT=noexcept -DBAD_ALLOC= +// RUN: %clang_cc1 -std=c++2c %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -DNOEXCEPT=noexcept -DBAD_ALLOC= -// dr412: yes +// dr412: 3.4 // lwg404: yes // lwg2340: yes @@ -11,11 +14,17 @@ __extension__ typedef __SIZE_TYPE__ size_t; namespace std { struct bad_alloc {}; } -inline void* operator new(size_t) BAD_ALLOC; // expected-error {{cannot be declared 'inline'}} -inline void* operator new[](size_t) BAD_ALLOC; // expected-error {{cannot be declared 'inline'}} -inline void operator delete(void*) NOEXCEPT; // expected-error {{cannot be declared 'inline'}} -inline void operator delete[](void*) NOEXCEPT; // expected-error {{cannot be declared 'inline'}} +inline void* operator new(size_t) BAD_ALLOC; +// expected-error@-1 {{replacement function 'operator new' cannot be declared 'inline'}} +inline void* operator new[](size_t) BAD_ALLOC; +// expected-error@-1 {{replacement function 'operator new[]' cannot be declared 'inline'}} +inline void operator delete(void*) NOEXCEPT; +// expected-error@-1 {{replacement function 'operator delete' cannot be declared 'inline'}} +inline void operator delete[](void*) NOEXCEPT; +// expected-error@-1 {{replacement function 'operator delete[]' cannot be declared 'inline'}} #ifdef __cpp_sized_deallocation -inline void operator delete(void*, size_t) NOEXCEPT; // expected-error {{cannot be declared 'inline'}} -inline void operator delete[](void*, size_t) NOEXCEPT; // expected-error {{cannot be declared 'inline'}} +inline void operator delete(void*, size_t) NOEXCEPT; +// expected-error@-1 {{replacement function 'operator delete' cannot be declared 'inline'}} +inline void operator delete[](void*, size_t) NOEXCEPT; +// expected-error@-1 {{replacement function 'operator delete[]' cannot be declared 'inline'}} #endif diff --git a/clang/test/CXX/drs/dr5xx.cpp b/clang/test/CXX/drs/dr5xx.cpp index a3563481eac68e81f8e6e16d8cfafe03aa149708..21a6646d4abcf17ce00ce6a8ed86fc26247a9349 100644 --- a/clang/test/CXX/drs/dr5xx.cpp +++ b/clang/test/CXX/drs/dr5xx.cpp @@ -1,20 +1,21 @@ -// RUN: %clang_cc1 -std=c++98 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++11 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++14 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++17 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++20 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++23 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++98 %s -verify=expected,cxx98-11,cxx98-14,cxx98-17,cxx98 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++11 %s -verify=expected,cxx98-11,cxx98-14,cxx98-17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++14 %s -verify=expected,cxx98-14,cxx98-17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++17 %s -verify=expected,since-cxx17,cxx98-17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++20 %s -verify=expected,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++23 %s -verify=expected,since-cxx23,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors // FIXME: This is included to avoid a diagnostic with no source location // pointing at the implicit operator new. We can't match such a diagnostic // with -verify. __extension__ typedef __SIZE_TYPE__ size_t; -void *operator new(size_t); // expected-error 0-1{{missing exception spec}} expected-note{{candidate}} +void *operator new(size_t); // #dr5xx-global-operator-new +// cxx98-error@-1 {{'operator new' is missing exception specification 'throw(std::bad_alloc)'}} #if __cplusplus > 201402L namespace std { enum class align_val_t : size_t {}; } -void *operator new(size_t, std::align_val_t); // expected-note{{candidate}} +void *operator new(size_t, std::align_val_t); // #dr5xx-global-operator-new-aligned #endif namespace dr500 { // dr500: dup 372 @@ -33,7 +34,8 @@ namespace dr501 { // dr501: yes struct A { friend void f() {} void g() { - void (*p)() = &f; // expected-error {{undeclared identifier}} + void (*p)() = &f; + // expected-error@-1 {{use of undeclared identifier 'f'}} } }; } @@ -45,7 +47,8 @@ namespace dr502 { // dr502: yes void q1() { f(e); } void q2() { Q arr[sizeof(E)]; f(arr); } void q3() { Q arr[e]; f(arr); } - void sanity() { Q arr[1]; f(arr); } // expected-error {{undeclared identifier 'f'}} + void sanity() { Q arr[1]; f(arr); } + // expected-error@-1 {{use of undeclared identifier 'f'}} }; int f(A::E); template int f(Q (&)[N]); @@ -53,14 +56,22 @@ namespace dr502 { // dr502: yes } namespace dr505 { // dr505: yes - const char *exts = "\e\(\{\[\%"; // expected-error 5{{use of non-standard escape}} - const char *unknown = "\Q"; // expected-error {{unknown escape sequence}} + const char *exts = "\e\(\{\[\%"; + // expected-error@-1 {{use of non-standard escape character '\e'}} + // expected-error@-2 {{use of non-standard escape character '\('}} + // expected-error@-3 {{use of non-standard escape character '\{'}} + // expected-error@-4 {{use of non-standard escape character '\['}} + // expected-error@-5 {{use of non-standard escape character '\%'}} + const char *unknown = "\Q"; + // expected-error@-1 {{unknown escape sequence '\Q'}} } namespace dr506 { // dr506: yes struct NonPod { ~NonPod(); }; void f(...); - void g(NonPod np) { f(np); } // expected-error {{cannot pass}} + void g(NonPod np) { f(np); } + // cxx98-error@-1 {{cannot pass object of non-POD type 'NonPod' through variadic function; call will abort at runtime}} + // since-cxx11-error@-2 {{cannot pass object of non-trivial type 'NonPod' through variadic function; call will abort at runtime}} } // FIXME: Add tests here once DR260 is resolved. @@ -71,15 +82,13 @@ namespace dr506 { // dr506: yes // dr510: na namespace dr512 { // dr512: yes - struct A { - A(int); + struct A { // #dr512-A + A(int); // #dr512-A-ctor }; union U { A a; }; -#if __cplusplus < 201103L - // expected-error@-2 {{has a non-trivial default constructor}} - // expected-note@-6 {{no default constructor}} - // expected-note@-6 {{suppressed by user-declared constructor}} -#endif + // cxx98-error@-1 {{union member 'a' has a non-trivial default constructor}} + // cxx98-note@#dr512-A {{because type 'dr512::A' has no default constructor}} + // cxx98-note@#dr512-A-ctor {{implicit default constructor suppressed by user-declared constructor}} } // dr513: na @@ -101,9 +110,7 @@ namespace dr515 { // dr515: sup 1017 struct A { int a; }; struct B { void f() { int k = sizeof(A::a); } }; -#if __cplusplus < 201103L - // expected-error@-2 {{invalid use of non-static data member}} -#endif + // cxx98-error@-1 {{invalid use of non-static data member 'a'}} } // dr516: na @@ -111,7 +118,8 @@ namespace dr515 { // dr515: sup 1017 namespace dr517 { // dr517: no // This is NDR, but we should diagnose it anyway. template struct S {}; - template int v = 0; // expected-error 0-1{{extension}} + template int v = 0; + // cxx98-11-error@-1 {{variable templates are a C++14 extension}} template struct S; template int v; @@ -121,18 +129,16 @@ namespace dr517 { // dr517: no // FIXME: These are both ill-formed. template struct S {}; - template int v = 0; // expected-error 0-1{{extension}} + template int v = 0; // FIXME: These are both ill-formed. template struct S {}; - template int v = 0; // expected-error 0-1{{extension}} + template int v = 0; } namespace dr518 { // dr518: yes c++11 enum E { e, }; -#if __cplusplus < 201103L - // expected-error@-2 {{C++11 extension}} -#endif + // cxx98-error@-1 {{commas at the end of enumerator lists are a C++11 extension}} } namespace dr519 { // dr519: yes @@ -156,7 +162,7 @@ namespace dr522 { // dr522: yes template void b2(volatile T * const *); template void b2(volatile T * const S::*); template void b2(volatile T * const S::* const *); - template void b2a(volatile T *S::* const *); // expected-note {{candidate template ignored: deduced type 'volatile int *dr522::S::*const *' of 1st parameter does not match adjusted type 'int *dr522::S::**' of argument}} + template void b2a(volatile T *S::* const *); // #dr522-b2a template struct Base {}; struct Derived : Base {}; @@ -174,22 +180,27 @@ namespace dr522 { // dr522: yes b2(pm); b2(a); b2(am); - b2a(am); // expected-error {{no matching function}} + b2a(am); + // expected-error@-1 {{no matching function for call to 'b2a'}} + // expected-note@#dr522-b2a {{candidate template ignored: deduced type 'volatile int *dr522::S::*const *' of 1st parameter does not match adjusted type 'int *dr522::S::**' of argument}} b3(d); b3(cd); } } namespace dr524 { // dr524: yes - template void f(T a, T b) { operator+(a, b); } // expected-error {{call}} + template void f(T a, T b) { operator+(a, b); } + // expected-error@-1 {{call to function 'operator+' that is neither visible in the template definition nor found by argument-dependent lookup}} + // expected-note@#dr524-f-N-S {{in instantiation of function template specialization 'dr524::f' requested here}} + // expected-note@#dr524-operator-plus {{'operator+' should be declared prior to the call site or in namespace 'dr524::N'}} struct S {}; void operator+(S, S); template void f(S, S); namespace N { struct S {}; } - void operator+(N::S, N::S); // expected-note {{should be declared}} - template void f(N::S, N::S); // expected-note {{instantiation}} + void operator+(N::S, N::S); // #dr524-operator-plus + template void f(N::S, N::S); // #dr524-f-N-S } namespace dr525 { // dr525: yes @@ -202,9 +213,11 @@ namespace dr525 { // dr525: yes } } namespace after { - template struct D { typename T::error e; }; // expected-error {{prior to '::'}} + template struct D { typename T::error e; }; + // expected-error@-1 {{type 'double' cannot be used prior to '::' because it has no members}} + // expected-note@#dr525-ppp {{in instantiation of template class 'dr525::after::D' requested here}} void g(D *ppp) { - delete ppp; // expected-note {{instantiation of}} + delete ppp; // #dr525-ppp } } } @@ -212,30 +225,36 @@ namespace dr525 { // dr525: yes namespace dr526 { // dr526: yes template struct S {}; template void f1(S s); - template void f2(S<(N)> s); // expected-note {{couldn't infer}} - template void f3(S<+N> s); // expected-note {{couldn't infer}} + template void f2(S<(N)> s); // #dr526-f2 + template void f3(S<+N> s); // #dr526-f3 template void g1(int (&)[N]); - template void g2(int (&)[(N)]); // expected-note {{couldn't infer}} - template void g3(int (&)[+N]); // expected-note {{couldn't infer}} + template void g2(int (&)[(N)]); // #dr526-g2 + template void g3(int (&)[+N]); // #dr526-g3 void test(int (&a)[3], S<3> s) { f1(s); - f2(s); // expected-error {{no matching}} - f3(s); // expected-error {{no matching}} + f2(s); + // expected-error@-1 {{no matching function for call to 'f2'}} + // expected-note@#dr526-f2 {{candidate template ignored: couldn't infer template argument 'N'}} + f3(s); + // expected-error@-1 {{no matching function for call to 'f3'}} + // expected-note@#dr526-f3 {{candidate template ignored: couldn't infer template argument 'N'}} g1(a); - g2(a); // expected-error {{no matching}} - g3(a); // expected-error {{no matching}} + g2(a); + // expected-error@-1 {{no matching function for call to 'g2'}} + // expected-note@#dr526-g2 {{candidate template ignored: couldn't infer template argument 'N'}} + g3(a); + // expected-error@-1 {{no matching function for call to 'g3'}} + // expected-note@#dr526-g3 {{candidate template ignored: couldn't infer template argument 'N'}} } template struct X { typedef int type; X::type v1; X<(N)>::type v2; + // cxx98-17-error@-1 {{missing 'typename' prior to dependent type name X<(N)>::type; implicit 'typename' is a C++20 extension}} X<+N>::type v3; -#if __cplusplus <= 201703L - // expected-error@-3 {{implicit 'typename' is a C++20 extension}} - // expected-error@-3 {{implicit 'typename' is a C++20 extension}} -#endif + // cxx98-17-error@-1 {{missing 'typename' prior to dependent type name X<+N>::type; implicit 'typename' is a C++20 extension}} }; } @@ -307,32 +326,48 @@ namespace dr531 { // dr531: partial void f(T) { T::error; } template void g(T, U) { T::error; } struct B { typename T::error error; }; - template struct C { typename T::error error; }; // expected-note {{here}} + template struct C { typename T::error error; }; // #dr531-C static T n; }; template T A::n = T::error; - void A::f(int) {} // expected-error {{requires 'template<>'}} - template void A::g(int, U) {} // expected-error {{should be empty}} - struct A::B {}; // expected-error {{requires 'template<>'}} - template struct A::C {}; // expected-error {{should be empty}} expected-error {{different kind of symbol}} - int A::n = 0; // expected-error {{requires 'template<>'}} - - template<> struct A { // expected-note 2{{here}} + void A::f(int) {} + // expected-error@-1 {{template specialization requires 'template<>'}} + template void A::g(int, U) {} + // expected-error@-1 {{template parameter list matching the non-templated nested type 'dr531::bad::A' should be empty}} + struct A::B {}; + // expected-error@-1 {{template specialization requires 'template<>'}} + template struct A::C {}; + // expected-error@-1 {{template parameter list matching the non-templated nested type 'dr531::bad::A' should be empty}} + // expected-error@-2 {{redefinition of 'C' as different kind of symbol}} + // expected-note@#dr531-C {{previous definition is here}} + int A::n = 0; + // expected-error@-1 {{template specialization requires 'template<>'}} + + template<> struct A { // #dr531-A-char void f(char); template void g(char, U); - struct B; // expected-note {{here}} + struct B; // #dr531-B template struct C; static char n; }; - template<> void A::f(char) {} // expected-error {{no function template matches}} + template<> void A::f(char) {} + // expected-error@-1 {{no function template matches function template specialization 'f'}} // FIXME: This is ill-formed; -pedantic-errors should reject. - template<> template void A::g(char, U) {} // expected-warning {{extraneous template parameter list}} - template<> struct A::B {}; // expected-error {{extraneous 'template<>'}} expected-error {{does not specialize}} + template<> template void A::g(char, U) {} + // expected-warning@-1 {{extraneous template parameter list in template specialization}} + // expected-note@#dr531-A-char {{'template<>' header not required for explicitly-specialized class 'dr531::bad::A' declared here}} + template<> struct A::B {}; + // expected-error@-1 {{extraneous 'template<>' in declaration of struct 'B'}} + // expected-error@-2 {{specialization of member 'dr531::bad::A::B' does not specialize an instantiated member}} + // expected-note@#dr531-B {{attempt to specialize declaration here}} // FIXME: This is ill-formed; -pedantic-errors should reject. - template<> template struct A::C {}; // expected-warning {{extraneous template parameter list}} - template<> char A::n = 0; // expected-error {{extraneous 'template<>'}} + template<> template struct A::C {}; + // expected-warning@-1 {{extraneous template parameter list in template specialization}} + // expected-note@#dr531-A-char {{'template<>' header not required for explicitly-specialized class 'dr531::bad::A' declared here}} + template<> char A::n = 0; + // expected-error@-1 {{extraneous 'template<>' in declaration of variable 'n'}} } namespace nested { @@ -346,10 +381,12 @@ namespace dr531 { // dr531: partial template void i(); }; template<> template void A::B::f() {} - template void A::B::g() {} // expected-error {{should be empty}} + template void A::B::g() {} + // expected-error@-1 {{template parameter list matching the non-templated nested type 'dr531::nested::A' should be empty ('template<>')}} template<> template template void A::B::h() {} - template template void A::B::i() {} // expected-error {{should be empty}} + template template void A::B::i() {} + // expected-error@-1 {{template parameter list matching the non-templated nested type 'dr531::nested::A' should be empty ('template<>')}} #if __cplusplus <= 201703L // FIXME: All of those declarations shouldn't crash in C++20 mode. @@ -357,8 +394,10 @@ namespace dr531 { // dr531: partial template<> template<> template void A::B::h() {} template<> template<> template<> void A::B::h() {} - template<> void A::B::f() {} // expected-error {{requires 'template<>'}} - template<> template void A::B::h() {} // expected-error {{should be empty}} + template<> void A::B::f() {} + // cxx98-17-error@-1 {{template specialization requires 'template<>'}} + template<> template void A::B::h() {} + // cxx98-17-error@-1 {{template parameter list matching the non-templated nested type 'dr531::nested::A::B' should be empty ('template<>')}} #endif } } @@ -381,10 +420,11 @@ namespace dr532 { // dr532: 3.5 // dr533: na -namespace dr534 { // dr534: yes +namespace dr534 { // dr534: 2.9 struct S {}; template void operator+(S, T); - template void operator+(S, T*) {} // expected-error {{function template partial spec}} + template void operator+(S, T*) {} + // expected-error@-1 {{function template partial specialization is not allowed}} } namespace dr535 { // dr535: yes @@ -423,43 +463,70 @@ namespace dr535 { // dr535: yes // dr538: na // dr539: yes -const dr539( // expected-error {{a type specifier is required}} - const a) { // expected-error {{unknown type name 'a'}} - const b; // expected-error {{a type specifier is required}} - new const; // expected-error {{expected a type}} - try {} catch (const n) {} // expected-error {{unknown type name 'n'}} - try {} catch (const) {} // expected-error {{expected a type}} - if (const n = 0) {} // expected-error {{a type specifier is required}} - switch (const n = 0) {} // expected-error {{a type specifier is required}} - while (const n = 0) {} // expected-error {{a type specifier is required}} - for (const n = 0; // expected-error {{a type specifier is required}} - const m = 0; ) {} // expected-error {{a type specifier is required}} - sizeof(const); // expected-error {{a type specifier is required}} +const dr539( +// expected-error@-1 {{a type specifier is required for all declarations}} + const a) { + // expected-error@-1 {{unknown type name 'a'}} + const b; + // expected-error@-1 {{a type specifier is required for all declarations}} + new const; + // expected-error@-1 {{expected a type}} + try {} catch (const n) {} + // expected-error@-1 {{unknown type name 'n'}} + try {} catch (const) {} + // expected-error@-1 {{expected a type}} + if (const n = 0) {} + // expected-error@-1 {{a type specifier is required for all declarations}} + switch (const n = 0) {} + // expected-error@-1 {{a type specifier is required for all declarations}} + while (const n = 0) {} + // expected-error@-1 {{a type specifier is required for all declarations}} + for (const n = 0; + // expected-error@-1 {{a type specifier is required for all declarations}} + const m = 0; ) {} + // expected-error@-1 {{a type specifier is required for all declarations}} + sizeof(const); + // expected-error@-1 {{a type specifier is required for all declarations}} struct S { - const n; // expected-error {{a type specifier is required}} - operator const(); // expected-error {{expected a type}} + const n; + // expected-error@-1 {{a type specifier is required for all declarations}} + operator const(); + // expected-error@-1 {{expected a type}} }; #if __cplusplus >= 201103L int arr[3]; // FIXME: The extra braces here are to avoid the parser getting too // badly confused when recovering here. We should fix this recovery. - { for (const n // expected-error {{unknown type name 'n'}} expected-note {{}} - : arr) ; {} } // expected-error +{{}} - (void) [](const) {}; // expected-error {{a type specifier is required}} - (void) [](const n) {}; // expected-error {{unknown type name 'n'}} - enum E : const {}; // expected-error {{expected a type}} - using T = const; // expected-error {{expected a type}} - auto f() -> const; // expected-error {{expected a type}} + { for (const n + // since-cxx11-error@-1 {{unknown type name 'n'}} + // since-cxx11-note@-2 {{}} + : arr) ; {} } + // since-cxx11-error@-1 +{{}} + (void) [](const) {}; + // since-cxx11-error@-1 {{a type specifier is required for all declarations}} + (void) [](const n) {}; + // since-cxx11-error@-1 {{unknown type name 'n'}} + enum E : const {}; + // since-cxx11-error@-1 {{expected a type}} + using T = const; + // since-cxx11-error@-1 {{expected a type}} + auto f() -> const; + // since-cxx11-error@-1 {{expected a type}} #endif } namespace dr540 { // dr540: yes typedef int &a; - typedef const a &a; // expected-warning {{has no effect}} + typedef const a &a; + // expected-warning@-1 {{'const' qualifier on reference type 'a' (aka 'int &') has no effect}} typedef const int &b; typedef b &b; - typedef const a &c; // expected-note {{previous}} expected-warning {{has no effect}} - typedef const b &c; // expected-error {{different}} expected-warning {{has no effect}} + typedef const a &c; // #dr540-typedef-a-c + // expected-warning@-1 {{'const' qualifier on reference type 'a' (aka 'int &') has no effect}} + typedef const b &c; // #dr540-typedef-b-c + // expected-error@#dr540-typedef-b-c {{typedef redefinition with different types ('const int &' vs 'int &')}} + // expected-note@#dr540-typedef-a-c {{previous definition is here}} + // expected-warning@#dr540-typedef-b-c {{'const' qualifier on reference type 'b' (aka 'const int &') has no effect}} } namespace dr541 { // dr541: yes @@ -476,9 +543,15 @@ namespace dr541 { // dr541: yes void x() { // These are type-dependent expressions, even though we could // determine that all calls have type 'int'. - X::type a; // expected-error +{{}} - X::type b; // expected-error +{{}} - X::type b; // expected-error +{{}} + X::type a; + // expected-error@-1 {{expected ';' after expression}} + // expected-error@-2 {{use of undeclared identifier 'a'}} + X::type b; + // expected-error@-1 {{expected ';' after expression}} + // expected-error@-2 {{use of undeclared identifier 'b'}} + X::type b; + // expected-error@-1 {{expected ';' after expression}} + // expected-error@-2 {{use of undeclared identifier 'b'}} typename X::type a; typename X::type b; @@ -490,28 +563,25 @@ namespace dr542 { // dr542: yes #if __cplusplus >= 201103L // In C++20 A and B are no longer aggregates and thus the constructor is // called, which fails. - struct A { A() = delete; int n; }; - A a[32] = {}; // ok, constructor not called -#if __cplusplus > 201703L - // expected-error@-2 {{call to deleted constructor}} - // expected-note@-3 {{in implicit initialization}} - // expected-note@-5 {{marked deleted here}} -#endif + struct A { A() = delete; int n; }; // #dr542-A + // ok, constructor not called + A a[32] = {}; // #dr542-a + // since-cxx20-error@-1 {{call to deleted constructor of 'A'}} + // since-cxx20-note@#dr542-A {{'A' has been explicitly marked deleted here}} + // since-cxx20-note@#dr542-a {{in implicit initialization of array element 0 with omitted initializer}} struct B { int n; private: - B() = default; + B() = default; // #dr542-B-ctor }; B b[32] = {}; // ok, constructor not called -#if __cplusplus > 201703L - // expected-error@-2 {{calling a private constructor}} - // expected-note@-5 {{declared private here}} -#endif + // since-cxx20-error@-1 {{calling a private constructor of class 'dr542::B'}} + // since-cxx20-note@#dr542-B-ctor {{declared private here}} #endif } -namespace dr543 { // dr543: yes +namespace dr543 { // dr543: 3.0 // In C++98+DR543, this is valid because value-initialization doesn't call a // trivial default constructor, so we never notice that defining the // constructor would be ill-formed. @@ -520,13 +590,11 @@ namespace dr543 { // dr543: yes // deleted, and value-initialization *does* call a deleted default // constructor, even if it is trivial. struct A { - const int n; + const int n; // #dr543-A-n }; A a = A(); -#if __cplusplus >= 201103L - // expected-error@-2 {{deleted}} - // expected-note@-5 {{would not be initialized}} -#endif + // since-cxx11-error@-1 {{call to implicitly-deleted default constructor of 'A'}} + // since-cxx11-note@#dr543-A-n {{default constructor of 'A' is implicitly deleted because field 'n' of const-qualified type 'const int' would not be initialized}} } namespace dr544 { // dr544: yes @@ -544,7 +612,7 @@ namespace dr546 { // dr546: yes template void A::f() { T::error; } } -namespace dr547 { // dr547: yes +namespace dr547 { // dr547: 3.2 template struct X; template struct X {}; template X f(T C::*) { return X(); } @@ -564,23 +632,17 @@ namespace dr551 { // dr551: yes c++11 // FIXME: This obviously should apply in C++98 mode too. template void f() {} template inline void f(); -#if __cplusplus >= 201103L - // expected-error@-2 {{cannot be 'inline'}} -#endif + // since-cxx11-error@-1 {{explicit instantiation cannot be 'inline'}} template inline void g() {} template inline void g(); -#if __cplusplus >= 201103L - // expected-error@-2 {{cannot be 'inline'}} -#endif + // since-cxx11-error@-1 {{explicit instantiation cannot be 'inline'}} template struct X { void f() {} }; template inline void X::f(); -#if __cplusplus >= 201103L - // expected-error@-2 {{cannot be 'inline'}} -#endif + // since-cxx11-error@-1 {{explicit instantiation cannot be 'inline'}} } namespace dr552 { // dr552: yes @@ -597,17 +659,21 @@ namespace dr553 { // Contrary to the apparent intention of the DR, operator new is not actually // looked up with a lookup mechanism that performs ADL; the standard says it // "is looked up in global scope", where it is not visible. - void *p = new (c) int; // expected-error {{no matching function}} + void *p = new (c) int; + // expected-error@-1 {{no matching function for call to 'operator new'}} + // since-cxx17-note@#dr5xx-global-operator-new-aligned {{candidate function not viable: no known conversion from 'dr553_class' to 'std::align_val_t' for 2nd argument}} + // expected-note@#dr5xx-global-operator-new {{candidate function not viable: requires 1 argument, but 2 were provided}} struct namespace_scope { - friend void *operator new(size_t, namespace_scope); // expected-error {{cannot be declared inside a namespace}} + friend void *operator new(size_t, namespace_scope); + // expected-error@-1 {{'operator new' cannot be declared inside a namespace}} }; } // dr554: na // dr556: na -namespace dr557 { // dr557: yes +namespace dr557 { // dr557: 3.1 template struct S { friend void f(S *); friend void g(S > *); @@ -618,12 +684,14 @@ namespace dr557 { // dr557: yes } } -namespace dr558 { // dr558: yes +namespace dr558 { // dr558: 2.9 wchar_t a = L'\uD7FF'; wchar_t b = L'\xD7FF'; - wchar_t c = L'\uD800'; // expected-error {{invalid universal character}} + wchar_t c = L'\uD800'; + // expected-error@-1 {{invalid universal character}} wchar_t d = L'\xD800'; - wchar_t e = L'\uDFFF'; // expected-error {{invalid universal character}} + wchar_t e = L'\uDFFF'; + // expected-error@-1 {{invalid universal character}} wchar_t f = L'\xDFFF'; wchar_t g = L'\uE000'; wchar_t h = L'\xE000'; @@ -656,14 +724,18 @@ namespace dr564 { // dr564: yes namespace dr565 { // dr565: yes namespace N { - template int f(T); // expected-note {{target}} + template int f(T); // #dr565-f } - using N::f; // expected-note {{using}} + using N::f; // #dr565-using template int f(T*); template void f(T); - template int f(T); // expected-error 0-1{{extension}} + template int f(T); + // cxx98-error@-1 {{default template arguments for a function template are a C++11 extension}} template int f(T, int = 0); - template int f(T); // expected-error {{conflicts with}} + template int f(T); + // expected-error@-1 {{declaration conflicts with target of using declaration already in scope}} + // expected-note@#dr565-f {{target of using declaration}} + // expected-note@#dr565-using {{using declaration}} } namespace dr566 { // dr566: yes @@ -674,7 +746,7 @@ namespace dr566 { // dr566: yes // dr567: na -namespace dr568 { // dr568: yes c++11 +namespace dr568 { // dr568: 3.0 c++11 // FIXME: This is a DR issue against C++98, so should probably apply there // too. struct x { int y; }; @@ -704,17 +776,13 @@ namespace dr568 { // dr568: yes c++11 void f(...); void g(trivial t) { f(t); } -#if __cplusplus < 201103L - // expected-error@-2 {{non-POD}} -#endif + // cxx98-error@-1 {{cannot pass object of non-POD type 'trivial' through variadic function; call will abort at runtime}} void jump() { goto x; -#if __cplusplus < 201103L - // expected-error@-2 {{cannot jump}} - // expected-note@+2 {{non-POD}} -#endif - trivial t; + // cxx98-error@-1 {{cannot jump from this goto statement to its label}} + // cxx98-note@#dr568-t {{jump bypasses initialization of non-POD variable}} + trivial t; // #dr568-t x: ; } } @@ -723,22 +791,24 @@ namespace dr569 { // dr569: yes c++11 // FIXME: This is a DR issue against C++98, so should probably apply there // too. ;;;;; -#if __cplusplus < 201103L - // expected-error@-2 {{C++11 extension}} -#endif + // cxx98-error@-1 {{C++11 extension}} } namespace dr570 { // dr570: dup 633 int n; - int &r = n; // expected-note {{previous}} - int &r = n; // expected-error {{redefinition}} + int &r = n; // #dr570-r + int &r = n; + // expected-error@-1 {{redefinition of 'r'}} + // expected-note@#dr570-r {{previous definition is here}} } namespace dr571 { // dr571 unknown // FIXME: Add a codegen test. typedef int &ir; int n; - const ir r = n; // expected-warning {{has no effect}} FIXME: Test if this has internal linkage. + // FIXME: Test if this has internal linkage. + const ir r = n; + // expected-warning@-1 {{'const' qualifier on reference type 'ir' (aka 'int &') has no effect}} } namespace dr572 { // dr572: yes @@ -750,76 +820,94 @@ namespace dr573 { // dr573: no void *a; int *b = reinterpret_cast(a); void (*c)() = reinterpret_cast(a); + // cxx98-error@-1 {{cast between pointer-to-function and pointer-to-object is an extension}} void *d = reinterpret_cast(c); -#if __cplusplus < 201103L - // expected-error@-3 {{extension}} - // expected-error@-3 {{extension}} -#endif - void f() { delete a; } // expected-error {{cannot delete}} - int n = d - a; // expected-error {{arithmetic on pointers to void}} + // cxx98-error@-1 {{cast between pointer-to-function and pointer-to-object is an extension}} + void f() { delete a; } + // expected-error@-1 {{cannot delete expression with pointer-to-'void' type 'void *'}} + int n = d - a; + // expected-error@-1 {{arithmetic on pointers to void}} // FIXME: This is ill-formed. template struct S; template struct T; } -namespace dr574 { // dr574: yes +namespace dr574 { // dr574: 3.0 struct A { - A &operator=(const A&) const; // expected-note {{different qualifiers}} + A &operator=(const A&) const; // #dr574-A-copy-assign }; struct B { - B &operator=(const B&) volatile; // expected-note {{different qualifiers}} + B &operator=(const B&) volatile; // #dr574-B-copy-assign }; #if __cplusplus >= 201103L struct C { - C &operator=(const C&) &; // #574-overload1 \ - // expected-note {{not viable}} \ - // expected-note {{here}} - + C &operator=(const C&) &; // #dr574-C-copy-assign }; struct D { - D &operator=(const D&) &&; // #574-overload2 \ - // expected-note {{not viable}} \ - // expected-note {{here}} + D &operator=(const D&) &&; // #dr574-D-copy-assign }; void test(C c, D d) { c = c; - C() = c; // expected-error {{no viable}} - d = d; // expected-error {{no viable}} + C() = c; + // since-cxx11-error@-1 {{no viable overloaded '='}} + // since-cxx11-note@#dr574-C-copy-assign {{candidate function not viable: expects an lvalue for object argument}} + d = d; + // since-cxx11-error@-1 {{no viable overloaded '='}} + // since-cxx11-note@#dr574-D-copy-assign {{candidate function not viable: expects an rvalue for object argument}} D() = d; } #endif struct Test { - friend A &A::operator=(const A&); // expected-error {{does not match}} - friend B &B::operator=(const B&); // expected-error {{does not match}} + friend A &A::operator=(const A&); + // expected-error@-1 {{friend declaration of 'operator=' does not match any declaration in 'dr574::A'}} + // expected-note@#dr574-A-copy-assign {{candidate function has different qualifiers (expected unqualified but found 'const')}} + friend B &B::operator=(const B&); + // expected-error@-1 {{friend declaration of 'operator=' does not match any declaration in 'dr574::B'}} + // expected-note@#dr574-B-copy-assign {{candidate function has different qualifiers (expected unqualified but found 'volatile')}} #if __cplusplus >= 202302L - friend C &C::operator=(const C&); // expected-error {{conflicting types for 'operator='}} - friend D &D::operator=(const D&); // expected-error {{conflicting types for 'operator='}} __cplusplus >= 201103L + friend C &C::operator=(const C&); + // since-cxx23-error@-1 {{conflicting types for 'operator='}} + // since-cxx23-note@#dr574-C-copy-assign {{previous declaration is here}} + friend D &D::operator=(const D&); + // since-cxx23-error@-1 {{conflicting types for 'operator='}} + // since-cxx23-note@#dr574-D-copy-assign {{previous declaration is here}} #elif __cplusplus >= 201103L // FIXME: We shouldn't produce the 'cannot overload' diagnostics here. - friend C &C::operator=(const C&); // expected-error {{does not match}} \ - // expected-error {{cannot overload}} \ - // expected-note@#574-overload1 {{candidate}} - friend D &D::operator=(const D&); // expected-error {{does not match}} \ - // expected-error {{cannot overload}} \ - // expected-note@#574-overload2 {{candidate}} + friend C &C::operator=(const C&); // #dr574-test-C + // since-cxx11-error@#dr574-test-C {{cannot overload}} + // since-cxx11-note@#dr574-C-copy-assign {{previous declaration is here}} + // since-cxx11-error@#dr574-test-C {{friend declaration of 'operator=' does not match any declaration in 'dr574::C'}} + // since-cxx11-note@#dr574-C-copy-assign {{candidate function}} + friend D &D::operator=(const D&); // #dr574-test-D + // since-cxx11-error@#dr574-test-D {{cannot overload a member function without a ref-qualifier with a member function with ref-qualifier '&&'}} + // since-cxx11-note@#dr574-D-copy-assign {{previous declaration is here}} + // since-cxx11-error@#dr574-test-D {{friend declaration of 'operator=' does not match any declaration in 'dr574::D'}} + // since-cxx11-note@#dr574-D-copy-assign {{candidate function}} #endif }; } namespace dr575 { // dr575: yes - template void a(T); void a(...); // expected-error 0-1{{extension}} - template void b(T); void b(...); // expected-error 0-1{{extension}} - template void c(T); void c(...); // expected-error 0-1{{extension}} - template void d(T, int = T::value); void d(...); // expected-error {{cannot be used prior to '::'}} + template void a(T); void a(...); + // cxx98-error@-1 {{default template arguments for a function template are a C++11 extension}} + template void b(T); void b(...); + // cxx98-error@-1 {{default template arguments for a function template are a C++11 extension}} + template void c(T); void c(...); + // cxx98-error@-1 {{default template arguments for a function template are a C++11 extension}} + template void d(T, int = T::value); void d(...); + // expected-error@-1 {{type 'int' cannot be used prior to '::' because it has no members}} + // expected-note@#dr575-d {{in instantiation of default function argument expression for 'd' required here}} void x() { a(0); b(0); c(0); - d(0); // expected-note {{in instantiation of default function argument}} + d(0); // #dr575-d } - template void f(T* = 0); // expected-error 0-1{{extension}} - template void f(T = 0); // expected-error 0-1{{extension}} + template void f(T* = 0); + // cxx98-error@-1 {{default template arguments for a function template are a C++11 extension}} + template void f(T = 0); + // cxx98-error@-1 {{default template arguments for a function template are a C++11 extension}} void g() { f<>(); } template T &h(T *); @@ -827,32 +915,46 @@ namespace dr575 { // dr575: yes void *p = h((void*)0); } -namespace dr576 { // dr576: yes - typedef void f() {} // expected-error {{function definition declared 'typedef'}} - void f(typedef int n); // expected-error {{invalid storage class}} +namespace dr576 { // dr576: 3.5 + typedef void f() {} + // expected-error@-1 {{function definition declared 'typedef'}} + void f(typedef int n); + // expected-error@-1 {{invalid storage class specifier in function declarator}} void f(char c) { typedef int n; } } -namespace dr577 { // dr577: yes +namespace dr577 { // dr577: 3.5 typedef void V; typedef const void CV; void a(void); - void b(const void); // expected-error {{qualifiers}} + void b(const void); + // expected-error@-1 {{'void' as parameter must not have type qualifiers}} void c(V); - void d(CV); // expected-error {{qualifiers}} + void d(CV); + // expected-error@-1 {{'void' as parameter must not have type qualifiers}} void (*e)(void) = c; - void (*f)(const void); // expected-error {{qualifiers}} + void (*f)(const void); + // expected-error@-1 {{'void' as parameter must not have type qualifiers}} void (*g)(V) = a; - void (*h)(CV); // expected-error {{qualifiers}} - template void i(T); // expected-note 2{{requires 1 arg}} - template void j(void (*)(T)); // expected-note 2{{argument may not have 'void' type}} + void (*h)(CV); + // expected-error@-1 {{'void' as parameter must not have type qualifiers}} + template void i(T); // #dr577-i + template void j(void (*)(T)); // #dr577-j void k() { a(); c(); - i(); // expected-error {{no match}} - i(); // expected-error {{no match}} - j(0); // expected-error {{no match}} - j(0); // expected-error {{no match}} + i(); + // expected-error@-1 {{no matching function for call to 'i'}} + // expected-note@#dr577-i {{candidate function template not viable: requires 1 argument, but 0 were provided}} + i(); + // expected-error@-1 {{no matching function for call to 'i'}} + // expected-note@#dr577-i {{candidate function template not viable: requires 1 argument, but 0 were provided}} + j(0); + // expected-error@-1 {{no matching function for call to 'j'}} + // expected-note@#dr577-j {{candidate template ignored: substitution failure [with T = void]: argument may not have 'void' type}} + j(0); + // expected-error@-1 {{no matching function for call to 'j'}} + // expected-note@#dr577-j {{candidate template ignored: substitution failure [with T = const void]: argument may not have 'void' type}} } } @@ -861,10 +963,10 @@ namespace dr580 { // dr580: partial struct A { static C c; }; struct B { static C c; }; class C { - C(); // expected-note {{here}} - ~C(); // expected-note {{here}} + C(); // #dr580-C-ctor + ~C(); // #dr580-C-dtor - typedef int I; // expected-note 2{{here}} + typedef int I; // #dr580-I template struct X; template friend struct Y; template void f(); @@ -874,7 +976,9 @@ namespace dr580 { // dr580: partial template struct C::X {}; template struct Y {}; - template struct Z {}; // expected-error {{private}} + template struct Z {}; + // expected-error@-1 {{'I' is a private member of 'dr580::C'}} + // expected-note@#dr580-I {{implicitly declared private here}} struct C2 { class X { @@ -883,18 +987,25 @@ namespace dr580 { // dr580: partial friend struct A; }; class Y { - template struct A {}; // FIXME: We incorrectly accept this - // because we think C2::Y::A<...> might - // instantiate to C2::X::A + // FIXME: We incorrectly accept this + // because we think C2::Y::A<...> might + // instantiate to C2::X::A + template struct A {}; }; }; template void C::f() {} template void g() {} - template void h() {} // expected-error {{private}} + template void h() {} + // expected-error@-1 {{'I' is a private member of 'dr580::C'}} + // expected-note@#dr580-I {{implicitly declared private here}} C A::c; - C B::c; // expected-error 2{{private}} + C B::c; // #dr580-c + // expected-error@#dr580-c {{calling a private constructor of class 'dr580::C'}} + // expected-note@#dr580-C-ctor {{implicitly declared private here}} + // expected-error@#dr580-c {{variable of type 'C' has private destructor}} + // expected-note@#dr580-C-dtor {{implicitly declared private here}} } // dr582: na @@ -902,43 +1013,45 @@ namespace dr580 { // dr580: partial namespace dr583 { // dr583: 4 // see n3624 int *p; - bool b1 = p < 0; // expected-error {{ordered comparison between pointer and zero}} - bool b2 = p > 0; // expected-error {{ordered comparison between pointer and zero}} - bool b3 = p <= 0; // expected-error {{ordered comparison between pointer and zero}} - bool b4 = p >= 0; // expected-error {{ordered comparison between pointer and zero}} + bool b1 = p < 0; + // expected-error@-1 {{ordered comparison between pointer and zero ('int *' and 'int')}} + bool b2 = p > 0; + // expected-error@-1 {{ordered comparison between pointer and zero ('int *' and 'int')}} + bool b3 = p <= 0; + // expected-error@-1 {{ordered comparison between pointer and zero ('int *' and 'int')}} + bool b4 = p >= 0; + // expected-error@-1 {{ordered comparison between pointer and zero ('int *' and 'int')}} } // dr584: na -namespace dr585 { // dr585: yes - template struct T; +namespace dr585 { // dr585: 3.0 + template struct T; // #dr585-struct-T struct A { friend T; -#if __cplusplus <= 201402L - // expected-error@-2 {{a type specifier is required}} expected-error@-2 {{can only be classes or functions}} -#else - // expected-error@-4 {{use of class template 'T' requires template arguments; argument deduction not allowed in friend declaration}} - // expected-note@-7 {{here}} -#endif + // cxx98-14-error@-1 {{a type specifier is required for all declarations}} + // cxx98-14-error@-2 {{friends can only be classes or functions}} + // since-cxx17-error@-3 {{use of class template 'T' requires template arguments; argument deduction not allowed in friend declaration}} + // since-cxx17-note@#dr585-struct-T {{template is declared here}} // FIXME: It's not clear whether the standard allows this or what it means, // but the DR585 writeup suggests it as an alternative. - template friend T; // expected-error {{must use an elaborated type}} + template friend T; + // expected-error@-1 {{friend type templates must use an elaborated type}} }; - template class T> struct B { + template class T> struct B { // #dr585-template-T friend T; -#if __cplusplus <= 201402L - // expected-error@-2 {{a type specifier is required}} expected-error@-2 {{can only be classes or functions}} -#else - // expected-error@-4 {{use of template template parameter 'T' requires template arguments; argument deduction not allowed in friend declaration}} - // expected-note@-6 {{here}} -#endif - template friend T; // expected-error {{must use an elaborated type}} + // cxx98-14-error@-1 {{a type specifier is required for all declarations}} + // cxx98-14-error@-2 {{friends can only be classes or functions}} + // since-cxx17-error@-3 {{use of template template parameter 'T' requires template arguments; argument deduction not allowed in friend declaration}} + // since-cxx17-note@#dr585-template-T {{template is declared here}} + template friend T; + // expected-error@-1 {{friend type templates must use an elaborated type}} }; } // dr586: na -namespace dr587 { // dr587: yes +namespace dr587 { // dr587: 3.2 template void f(bool b, const T x, T y) { const T *p = &(b ? x : y); } @@ -948,14 +1061,18 @@ namespace dr587 { // dr587: yes } namespace dr588 { // dr588: yes - struct A { int n; }; // expected-note {{ambiguous}} + struct A { int n; }; // #dr588-A template int f() { struct S : A, T { int f() { return n; } } s; int a = s.f(); - int b = s.n; // expected-error {{found in multiple}} + int b = s.n; + // expected-error@-1 {{member 'n' found in multiple base classes of different types}} + // expected-note@#dr588-k {{in instantiation of function template specialization 'dr588::f' requested here}} + // expected-note@#dr588-A {{member found by ambiguous name lookup}} + // expected-note@#dr588-B {{member found by ambiguous name lookup}} } - struct B { int n; }; // expected-note {{ambiguous}} - int k = f(); // expected-note {{here}} + struct B { int n; }; // #dr588-B + int k = f(); // #dr588-k } namespace dr589 { // dr589: yes @@ -964,8 +1081,10 @@ namespace dr589 { // dr589: yes D f(); extern const B &b; bool a; - const B *p = &(a ? f() : b); // expected-error {{temporary}} - const B *q = &(a ? D() : b); // expected-error {{temporary}} + const B *p = &(a ? f() : b); + // expected-error@-1 {{taking the address of a temporary object of type 'const B'}} + const B *q = &(a ? D() : b); + // expected-error@-1 {{taking the address of a temporary object of type 'const B'}} } namespace dr590 { // dr590: yes @@ -990,7 +1109,8 @@ namespace dr591 { // dr591: no template struct A::B::C : A { // FIXME: Should find member of non-dependent base class A. - M m; // expected-error {{incomplete type 'M' (aka 'void'}} + M m; + // expected-error@-1 {{field has incomplete type 'M' (aka 'void'}} }; } @@ -1001,9 +1121,8 @@ namespace dr591 { // dr591: no namespace dr595 { // dr595: dup 1330 template struct X { void f() throw(T) {} -#if __cplusplus > 201402L - // expected-error@-2 {{ISO C++17 does not allow}} expected-note@-2 {{use 'noexcept}} -#endif + // since-cxx17-error@-1 {{ISO C++17 does not allow dynamic exception specifications}} + // since-cxx17-note@-2 {{use 'noexcept(false)' instead}} }; struct S { X xs; @@ -1029,7 +1148,8 @@ namespace dr598 { // dr598: yes } int &g(void(*)(char)); int &r = g(N::f); - int &s = h(N::f); // expected-error {{undeclared}} + int &s = h(N::f); + // expected-error@-1 {{use of undeclared identifier 'h'}} int &t = h(N::i); } @@ -1037,16 +1157,23 @@ namespace dr599 { // dr599: partial typedef int Fn(); struct S { operator void*(); }; struct T { operator Fn*(); }; - struct U { operator int*(); operator void*(); }; // expected-note 2{{conversion}} + struct U { operator int*(); operator void*(); }; // #dr599-U struct V { operator int*(); operator Fn*(); }; void f(void *p, void (*q)(), S s, T t, U u, V v) { - delete p; // expected-error {{cannot delete}} - delete q; // expected-error {{cannot delete}} - delete s; // expected-error {{cannot delete}} - delete t; // expected-error {{cannot delete}} + delete p; + // expected-error@-1 {{cannot delete expression with pointer-to-'void' type 'void *'}} + delete q; + // expected-error@-1 {{cannot delete expression of type 'void (*)()'}} + delete s; + // expected-error@-1 {{cannot delete expression with pointer-to-'void' type 'void *'}} + delete t; + // expected-error@-1 {{cannot delete expression of type 'T'}} // FIXME: This is valid, but is rejected due to a non-conforming GNU // extension allowing deletion of pointers to void. - delete u; // expected-error {{ambiguous}} + delete u; + // expected-error@-1 {{ambiguous conversion of delete expression of type 'U' to a pointer}} + // expected-note@#dr599-U {{conversion to pointer type 'int *'}} + // expected-note@#dr599-U {{conversion to pointer type 'void *'}} delete v; } } diff --git a/clang/test/CXX/drs/dr6xx.cpp b/clang/test/CXX/drs/dr6xx.cpp index c5cd478c5e331948d36d88a279322c2edde5331b..78604d480aa1cadfb16d654d8151d40808cd0876 100644 --- a/clang/test/CXX/drs/dr6xx.cpp +++ b/clang/test/CXX/drs/dr6xx.cpp @@ -1,22 +1,24 @@ -// RUN: %clang_cc1 -std=c++98 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking -// RUN: %clang_cc1 -std=c++11 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking -// RUN: %clang_cc1 -std=c++14 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking -// RUN: %clang_cc1 -std=c++17 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking -// RUN: %clang_cc1 -std=c++20 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking -// RUN: %clang_cc1 -std=c++23 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking - -namespace dr600 { // dr600: yes +// RUN: %clang_cc1 -std=c++98 %s -verify=expected,cxx98-17,cxx98-14,cxx98 -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking +// RUN: %clang_cc1 -std=c++11 %s -verify=expected,cxx98-17,cxx11-17,cxx98-14,since-cxx11,cxx11 -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking +// RUN: %clang_cc1 -std=c++14 %s -verify=expected,cxx98-17,cxx11-17,cxx98-14,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking +// RUN: %clang_cc1 -std=c++17 %s -verify=expected,cxx98-17,cxx11-17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking +// RUN: %clang_cc1 -std=c++20 %s -verify=expected,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking +// RUN: %clang_cc1 -std=c++23 %s -verify=expected,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking + +namespace dr600 { // dr600: 2.8 struct S { void f(int); private: - void f(double); // expected-note {{declared private here}} + void f(double); // #dr600-f-double }; void g(S *sp) { sp->f(2); // access control is applied after overload resolution - sp->f(2.2); // expected-error {{is a private member}} + sp->f(2.2); + // expected-error@-1 {{'f' is a private member of 'dr600::S'}} + // expected-note@#dr600-f-double {{declared private here}} } } // namespace dr600 @@ -41,7 +43,8 @@ namespace dr601 { // dr601: yes #endif #if __INT_MAX__ == 0x7FFFFFFF -_Static_assert(0x80000000 < -1, "0x80000000 should be unsigned"); // expected-error {{C11}} +_Static_assert(0x80000000 < -1, "0x80000000 should be unsigned"); +// expected-error@-1 {{'_Static_assert' is a C11 extension}} #endif #if MAX > 0xFFFFFFFFFFFFFFFF && 0x8000000000000000 < -1 @@ -49,7 +52,7 @@ _Static_assert(0x80000000 < -1, "0x80000000 should be unsigned"); // expected-er #endif #if __cplusplus >= 201103L && __LLONG_MAX__ == 0x7FFFFFFFFFFFFFFF -static_assert(0x8000000000000000 < -1, "0x8000000000000000 should be unsigned"); // expected-error {{C11}} +static_assert(0x8000000000000000 < -1, "0x8000000000000000 should be unsigned"); #endif #undef MAX @@ -74,25 +77,27 @@ namespace dr603 { // dr603: yes template struct S {}; typedef S<'\001'> S1; typedef S<(1ul << __CHAR_BIT__) + 1> S1; -#if __cplusplus >= 201103L - // expected-error@-2 {{cannot be narrowed}} -#endif + // since-cxx11-error@-1 {{cannot be narrowed}} } // dr604: na // dr605 needs IRGen test -namespace dr606 { // dr606: yes +namespace dr606 { // dr606: 3.0 #if __cplusplus >= 201103L template struct S {}; - template void f(S &&); // expected-note {{expects an rvalue}} + template void f(S &&); // #dr606-f template void g(T &&); - template void h(const T &&); // expected-note {{expects an rvalue}} + template void h(const T &&); // #dr606-h void test(S s) { - f(s); // expected-error {{no match}} + f(s); + // since-cxx11-error@-1 {{no matching function for call to 'f'}} + // since-cxx11-note@#dr606-f {{candidate function [with T = int] not viable: expects an rvalue for 1st argument}} g(s); - h(s); // expected-error {{no match}} + h(s); + // since-cxx11-error@-1 {{no matching function for call to 'h'}} + // since-cxx11-note@#dr606-h {{candidate function [with T = dr606::S] not viable: expects an rvalue for 1st argument}} g(test); h(test); // ok, an rvalue reference can bind to a function lvalue @@ -152,33 +157,32 @@ namespace dr613 { // dr613: yes c++11 B &g(int); int an1 = sizeof(A::n); + // cxx98-error@-1 {{invalid use of non-static data member 'n'}} int an2 = sizeof(A::n + 1); // valid per dr850 + // cxx98-error@-1 {{invalid use of non-static data member 'n'}} int an3 = sizeof A::n; + // cxx98-error@-1 {{invalid use of non-static data member 'n'}} int an4 = sizeof(f(A::n)); + // cxx98-error@-1 {{invalid use of non-static data member 'n'}} int an5 = sizeof(g(A::n)); + // cxx98-error@-1 {{invalid use of non-static data member 'n'}} const std::type_info &an6 = typeid(A::n); + // cxx98-error@-1 {{invalid use of non-static data member 'n'}} const std::type_info &an7 = typeid(A::n + 1); + // cxx98-error@-1 {{invalid use of non-static data member 'n'}} const std::type_info &an8 = typeid(f(A::n)); - const std::type_info &an9 = typeid(g(A::n)); // expected-error {{non-static}} -#if __cplusplus < 201103L - // expected-error@-10 {{non-static}} - // expected-error@-10 {{non-static}} - // expected-error@-10 {{non-static}} - // expected-error@-10 {{non-static}} - // expected-error@-10 {{non-static}} - // expected-error@-10 {{non-static}} - // expected-error@-10 {{non-static}} - // expected-error@-10 {{non-static}} -#endif + // cxx98-error@-1 {{invalid use of non-static data member 'n'}} + const std::type_info &an9 = typeid(g(A::n)); + // expected-error@-1 {{invalid use of non-static data member 'n'}} void A::f() { int an1 = sizeof n; + // cxx98-error@-1 {{invalid use of member 'n' in static member function}} const std::type_info &an2 = typeid(n + 1); -#if __cplusplus < 201103L - // expected-error@-3 {{static}} - // expected-error@-3 {{static}} -#endif - const std::type_info &an3 = typeid(g(n)); // expected-error {{static}} + // cxx98-error@-1 {{invalid use of member 'n' in static member function}} + const std::type_info &an3 = typeid(g(n)); + // cxx98-error@-1 {{invalid use of member 'n' in static member function}} + // since-cxx11-error@-2 {{invalid use of non-static data member 'n'}} } } @@ -219,16 +223,20 @@ namespace dr619 { // dr619: yes struct S { static int x[10]; }; int x[]; - _Static_assert(sizeof(x) == sizeof(int) * 10, ""); // expected-error {{C11}} + _Static_assert(sizeof(x) == sizeof(int) * 10, ""); + // expected-error@-1 {{'_Static_assert' is a C11 extension}} extern int x[]; - _Static_assert(sizeof(x) == sizeof(int) * 10, ""); // expected-error {{C11}} + _Static_assert(sizeof(x) == sizeof(int) * 10, ""); + // expected-error@-1 {{'_Static_assert' is a C11 extension}} int S::x[]; - _Static_assert(sizeof(S::x) == sizeof(int) * 10, ""); // expected-error {{C11}} + _Static_assert(sizeof(S::x) == sizeof(int) * 10, ""); + // expected-error@-1 {{'_Static_assert' is a C11 extension}} void f() { extern int x[]; - sizeof(x); // expected-error {{incomplete}} + sizeof(x); + // expected-error@-1 {{invalid application of 'sizeof' to an incomplete type 'int[]'}} } } @@ -236,8 +244,10 @@ namespace dr619 { // dr619: yes namespace dr621 { // dr621: yes template T f(); - template<> int f() {} // expected-note {{previous}} - template<> int f() {} // expected-error {{redefinition}} + template<> int f() {} // #dr621-f + template<> int f() {} + // expected-error@-1 {{redefinition of 'f'}} + // expected-note@#dr621-f {{previous definition is here}} } // dr623: na @@ -247,40 +257,44 @@ namespace dr621 { // dr621: yes namespace dr625 { // dr625: yes template struct A {}; - A x = A(); // expected-error {{'auto' not allowed in template argument}} expected-error 0-1{{extension}} + A x = A(); + // cxx98-error@-1 {{'auto' type specifier is a C++11 extension}} + // expected-error@-2 {{'auto' not allowed in template argument}} void f(int); - void (*p)(auto) = f; // expected-error {{'auto' not allowed in function prototype}} expected-error 0-1{{extension}} + void (*p)(auto) = f; + // cxx98-error@-1 {{'auto' type specifier is a C++11 extension}} + // expected-error@-2 {{'auto' not allowed in function prototype}} } namespace dr626 { // dr626: yes #define STR(x) #x char c[2] = STR(c); // ok, type matches - wchar_t w[2] = STR(w); // expected-error {{initializing wide char array with non-wide string literal}} + wchar_t w[2] = STR(w); + // expected-error@-1 {{initializing wide char array with non-wide string literal}} } namespace dr627 { // dr627: yes void f() { - true a = 0; // expected-error +{{}} expected-warning {{unused}} + // FIXME: emitted diagnostic have a room for improvement + true a = 0; + // expected-error@-1 {{expected ';' after expression}} + // expected-error@-2 {{use of undeclared identifier 'a'}} + // expected-warning@-3 {{expression result unused}} } } // dr628: na -namespace dr629 { // dr629: yes +namespace dr629 { // dr629: 2.9 typedef int T; int n = 1; void f() { - auto T = 2; -#if __cplusplus < 201103L - // expected-error@-2 {{expected unqualified-id}} -#else - // expected-note@-4 {{previous}} -#endif + auto T = 2; // #dr629-T + // cxx98-error@-1 {{expected unqualified-id}} auto T(n); -#if __cplusplus >= 201103L - // expected-error@-2 {{redefinition of 'T'}} -#endif + // since-cxx11-error@-1 {{redefinition of 'T'}} + // since-cxx11-note@#dr629-T {{previous definition is here}} } } @@ -311,17 +325,20 @@ const bool MB_EQ_WC = ',' == L',' && '\\' == L'\\' && '"' == L'"' && '\'' == L'\''; #if __STDC_MB_MIGHT_NEQ_WC__ #ifndef __FreeBSD__ // PR22208, FreeBSD expects us to give a bad (but conforming) answer here. -_Static_assert(!MB_EQ_WC, "__STDC_MB_MIGHT_NEQ_WC__ but all basic source characters have same representation"); // expected-error {{C11}} +_Static_assert(!MB_EQ_WC, "__STDC_MB_MIGHT_NEQ_WC__ but all basic source characters have same representation"); +// expected-error@-1 {{'_Static_assert' is a C11 extension}} #endif #else -_Static_assert(MB_EQ_WC, "!__STDC_MB_MIGHT_NEQ_WC__ but some character differs"); // expected-error {{C11}} +_Static_assert(MB_EQ_WC, "!__STDC_MB_MIGHT_NEQ_WC__ but some character differs"); +// expected-error@-1 {{'_Static_assert' is a C11 extension}} #endif } // dr631: na namespace dr632 { // dr632: yes - struct S { int n; } s = {{5}}; // expected-warning {{braces}} + struct S { int n; } s = {{5}}; + // expected-warning@-1 {{braces around scalar initializer}} } // dr633: na @@ -334,12 +351,15 @@ namespace dr634 { // dr634: yes template int (&g(T))[sizeof f(T())]; int (&a)[sizeof(int)] = g(S()); int (&b)[1] = g(0); - int k = f(S()); // expected-error {{cannot pass}} + int k = f(S()); + // cxx98-error@-1 {{cannot pass object of non-POD type 'S' through variadic function; call will abort at runtime}} + // since-cxx11-error@-2 {{cannot pass object of non-trivial type 'S' through variadic function; call will abort at runtime}} } namespace dr635 { // dr635: yes template struct A { A(); ~A(); }; - template A::A() {} // expected-error {{cannot have template arguments}} + template A::A() {} + // expected-error@-1 {{out-of-line constructor for 'A' cannot have template arguments}} template A::~A() {} template struct B { B(); ~B(); }; @@ -349,22 +369,25 @@ namespace dr635 { // dr635: yes struct C { template C(); C(); }; template C::C() {} C::C() {} - template<> C::C() {} // expected-error {{constructor name}} expected-error {{unqualified-id}} + template<> C::C() {} + // expected-error@-1 {{qualified reference to 'C' is a constructor name rather than a type in this context}} + // expected-error@-2 {{expected unqualified-id}} /*FIXME: needed for error recovery:*/; template struct D { template D(); D(); }; - template D::D() {} // expected-note {{previous}} + template D::D() {} // #dr635-D template template D::D() {} - template D::D() {} // expected-error {{redefinition}} expected-error {{cannot have template arg}} + template D::D() {} // #dr635-D-T + // expected-error@#dr635-D-T {{out-of-line constructor for 'D' cannot have template arguments}} + // expected-error@#dr635-D-T {{redefinition of 'D'}} + // expected-note@#dr635-D {{previous definition is here}} } namespace dr637 { // dr637: yes void f(int i) { i = ++i + 1; i = i++ + 1; -#if __cplusplus < 201703L - // expected-warning@-2 {{unsequenced}} -#endif + // cxx98-14-warning@-1 {{multiple unsequenced modifications to 'i'}} } } @@ -380,10 +403,14 @@ namespace dr638 { // dr638: no class X { typedef int type; - template friend struct A::B; // expected-warning {{not supported}} - template friend void A::f(); // expected-warning {{not supported}} - template friend void A::g(); // expected-warning {{not supported}} - template friend void A::C::h(); // expected-warning {{not supported}} + template friend struct A::B; + // expected-warning@-1 {{dependent nested name specifier 'A::' for friend class declaration is not supported; turning off access control for 'X'}} + template friend void A::f(); + // expected-warning@-1 {{dependent nested name specifier 'A::' for friend class declaration is not supported; turning off access control for 'X'}} + template friend void A::g(); + // expected-warning@-1 {{dependent nested name specifier 'A::' for friend class declaration is not supported; turning off access control for 'X'}} + template friend void A::C::h(); + // expected-warning@-1 {{dependent nested name specifier 'A::C::' for friend class declaration is not supported; turning off access control for 'X'}} }; template<> struct A { @@ -399,9 +426,10 @@ namespace dr638 { // dr638: no }; } -namespace dr639 { // dr639: yes +namespace dr639 { // dr639: 3.3 void f(int i) { - void((i = 0) + (i = 0)); // expected-warning {{unsequenced}} + void((i = 0) + (i = 0)); + // expected-warning@-1 {{multiple unsequenced modifications to 'i'}} } } @@ -410,36 +438,46 @@ namespace dr641 { // dr641: yes struct abc; struct xyz { - xyz(); // expected-note 0-1{{candidate}} - xyz(xyz &); // expected-note 0-1{{candidate}} - - operator xyz &() = delete; // expected-error 0-1{{extension}} expected-warning {{will never be used}} - operator abc &() = delete; // expected-error 0-1{{extension}} + xyz(); // #dr641-xyz-ctor + xyz(xyz &); // #dr641-xyz-copy-ctor + + operator xyz &() = delete; + // expected-warning@-1 {{conversion function converting 'dr641::std_example::xyz' to itself will never be used}} + // cxx98-error@-2 {{deleted function definitions are a C++11 extension}} + operator abc &() = delete; + // cxx98-error@-1 {{deleted function definitions are a C++11 extension}} }; struct abc : xyz {}; template - void use(T &); // expected-note {{expects an lvalue}} + void use(T &); // #dr641-use void test() { - use(xyz()); // expected-error {{no match}} + use(xyz()); + // expected-error@-1 {{no matching function for call to 'use'}} + // expected-note@#dr641-use {{candidate function template not viable: expects an lvalue for 1st argument}} use(xyz()); -#if __cplusplus < 201103L - // expected-error-re@-2 {{no viable constructor copying parameter of type '{{.*}}xyz'}} -#endif + // cxx98-error@-1 {{no viable constructor copying parameter of type 'xyz'; C++98 requires a copy constructor when binding a reference to a temporary}} + // cxx98-note@#dr641-xyz-copy-ctor {{candidate constructor not viable: expects an lvalue for 1st argument}} + // cxx98-note@#dr641-xyz-ctor {{candidate constructor not viable: requires 0 arguments, but 1 was provided}} } } template struct error { typedef typename T::error type; }; struct A { - template::type = 0> operator T() const; // expected-error 0-1{{extension}} + template::type = 0> operator T() const; + // cxx98-error@-1 {{default template arguments for a function template are a C++11 extension}} }; A a; - void f(A&); // expected-note 2{{candidate}} + void f(A&); // #dr641-f void g(const A ca) { - f(A()); // expected-error {{no match}} - f(ca); // expected-error {{no match}} + f(A()); + // expected-error@-1 {{no matching function for call to 'f'}} + // expected-note@#dr641-f {{candidate function not viable: expects an lvalue for 1st argument}} + f(ca); + // expected-error@-1 {{no matching function for call to 'f'}} + // expected-note@#dr641-f {{candidate function not viable: 1st argument ('const A') would lose const qualifier}} (void)A(); (void)ca; } @@ -450,7 +488,8 @@ namespace dr642 { // dr642: yes const int i = 2; { char i[i]; - _Static_assert(sizeof(i) == 2, ""); // expected-error {{C11}} + _Static_assert(sizeof(i) == 2, ""); + // expected-error@-1 {{'_Static_assert' is a C11 extension}} } } @@ -462,15 +501,18 @@ namespace dr642 { // dr642: yes } #if __cplusplus >= 201103L -namespace dr643 { // dr643: yes +namespace dr643 { // dr643: 3.2 struct A { int x; auto f() -> decltype(this->x); auto f(A &a) -> decltype(a.x); auto g() -> decltype(x); - auto h() -> decltype(this->y); // expected-error {{no member named 'y'}} - auto h(A &a) -> decltype(a.y); // expected-error {{no member named 'y'}} - auto i() -> decltype(y); // expected-error {{undeclared identifier 'y'}} + auto h() -> decltype(this->y); + // since-cxx11-error@-1 {{no member named 'y' in 'dr643::A'}} + auto h(A &a) -> decltype(a.y); + // since-cxx11-error@-1 {{no member named 'y' in 'dr643::A'}} + auto i() -> decltype(y); + // since-cxx11-error@-1 {{use of undeclared identifier 'y'}} int y; }; } @@ -522,45 +564,37 @@ namespace dr646 { // dr646: sup 981 #endif #if __cplusplus >= 201103L -namespace dr647 { // dr647: yes +namespace dr647 { // dr647: 3.1 // This is partially superseded by dr1358. struct A { constexpr virtual void f() const; constexpr virtual void g() const {} -#if __cplusplus <= 201703L - // expected-error@-2 {{virtual function cannot be constexpr}} -#endif + // cxx11-17-error@-1 {{virtual function cannot be constexpr}} }; - struct X { virtual void f() const; }; -#if __cplusplus <= 201703L - // expected-note@-2 {{overridden}} -#endif + struct X { virtual void f() const; }; // #dr647-f struct B : X { constexpr void f() const {} -#if __cplusplus <= 201703L - // expected-error@-2 {{virtual function cannot be constexpr}} -#endif + // cxx11-17-error@-1 {{virtual function cannot be constexpr}} + // cxx11-17-note@#dr647-f {{overridden virtual function is here}} }; - struct NonLiteral { NonLiteral() {} }; // expected-note {{not an aggregate and has no constexpr constructors}} + struct NonLiteral { NonLiteral() {} }; // #dr647-NonLiteral struct C { constexpr C(NonLiteral); - constexpr C(NonLiteral, int) {} // expected-error {{not a literal type}} + constexpr C(NonLiteral, int) {} + // since-cxx11-error@-1 {{constexpr constructor's 1st parameter type 'NonLiteral' is not a literal type}} + // since-cxx11-note@#dr647-NonLiteral {{'NonLiteral' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}} constexpr C() try {} catch (...) {} -#if __cplusplus <= 201703L - // expected-error@-2 {{function try block in constexpr constructor is a C++20 extension}} -#endif -#if __cplusplus < 201402L - // expected-error@-5 {{use of this statement in a constexpr constructor is a C++14 extension}} -#endif + // cxx11-17-error@-1 {{function try block in constexpr constructor is a C++20 extension}} + // cxx11-error@-2 {{use of this statement in a constexpr constructor is a C++14 extension}} }; struct D { operator int() const; constexpr D(int) {} - D(float); // expected-note 2{{declared here}} + D(float); // #dr647-D-float-ctor }; constexpr int get(); struct E { @@ -574,12 +608,18 @@ namespace dr647 { // dr647: yes : n(D(0)), d(0) {} - constexpr E(int) // expected-error {{never produces a constant expression}} + constexpr E(int) + // since-cxx11-error@-1 {{constexpr constructor never produces a constant expression}} + // since-cxx11-note@#dr647-int-d {{non-constexpr constructor 'D' cannot be used in a constant expression}} + // since-cxx11-note@#dr647-D-float-ctor {{declared here}} : n(0), - d(0.0f) {} // expected-note {{non-constexpr constructor}} - constexpr E(float f) // expected-error {{never produces a constant expression}} + d(0.0f) {} // #dr647-int-d + constexpr E(float f) + // since-cxx11-error@-1 {{never produces a constant expression}} + // since-cxx11-note@#dr647-float-d {{non-constexpr constructor}} + // since-cxx11-note@#dr647-D-float-ctor {{declared here}} : n(get()), - d(D(0) + f) {} // expected-note {{non-constexpr constructor}} + d(D(0) + f) {} // #dr647-float-d }; } #endif @@ -594,11 +634,15 @@ namespace dr648 { // dr648: yes #endif #if __cplusplus >= 201103L -namespace dr649 { // dr649: yes -alignas(0x200000000) int n; // expected-error {{requested alignment}}1 -struct alignas(0x200000000) X {}; // expected-error {{requested alignment}} +namespace dr649 { // dr649: 3.5 +// Maximum alignment is 8192 bytes for Windows, and 4 GB for Linux +alignas(0x200000000) int n; +// since-cxx11-error-re@-1 {{{{requested alignment must be (8192|4294967296) bytes or smaller}}}} +struct alignas(0x200000000) X {}; +// since-cxx11-error-re@-1 {{{{requested alignment must be (8192|4294967296) bytes or smaller}}}} struct Y { - int n alignas(0x200000000); // expected-error {{requested alignment}} + int n alignas(0x200000000); + // since-cxx11-error-re@-1 {{{{requested alignment must be (8192|4294967296) bytes or smaller}}}} }; struct alignas(256) Z {}; // This part is superseded by dr2130 and eventually by aligned allocation support. @@ -633,17 +677,24 @@ namespace dr652 { // dr652: yes #if __cplusplus >= 201103L namespace dr654 { // dr654: sup 1423 void f() { - if (nullptr) {} // expected-warning {{implicit conversion of nullptr constant to 'bool'}} - bool b = nullptr; // expected-error {{cannot initialize a variable of type 'bool' with an rvalue of type 'std::nullptr_t'}} + if (nullptr) {} + // since-cxx11-warning@-1 {{implicit conversion of nullptr constant to 'bool'}} + bool b = nullptr; + // since-cxx11-error@-1 {{cannot initialize a variable of type 'bool' with an rvalue of type 'std::nullptr_t'}} if (nullptr == 0) {} if (nullptr != 0) {} - if (nullptr <= 0) {} // expected-error {{invalid operands}} - if (nullptr == 1) {} // expected-error {{invalid operands}} - if (!nullptr) {} // expected-warning {{implicit conversion of nullptr constant to 'bool'}} + if (nullptr <= 0) {} + // since-cxx11-error@-1 {{invalid operands to binary expression ('std::nullptr_t' and 'int')}} + if (nullptr == 1) {} + // since-cxx11-error@-1 {{invalid operands to binary expression ('std::nullptr_t' and 'int')}} + if (!nullptr) {} + // since-cxx11-warning@-1 {{implicit conversion of nullptr constant to 'bool'}} decltype(nullptr) n = 0; - static_cast(nullptr); // expected-error {{not allowed}} + static_cast(nullptr); + // since-cxx11-error@-1 {{static_cast from 'std::nullptr_t' to 'int' is not allowed}} (void)static_cast(0); - static_cast(1); // expected-error {{not allowed}} + static_cast(1); + // since-cxx11-error@-1 {{static_cast from 'int' to 'decltype(nullptr)' (aka 'std::nullptr_t') is not allowed}} void(true ? nullptr : 0); void(true ? 0 : nullptr); } @@ -651,47 +702,66 @@ namespace dr654 { // dr654: sup 1423 #endif namespace dr655 { // dr655: yes - struct A { A(int); }; // expected-note 2-3{{not viable}} - // expected-note@-1 {{'dr655::A' declared here}} + struct A { A(int); }; // #dr655-A struct B : A { - A a; // expected-note {{member is declared here}} + A a; // #dr655-a B(); - B(int) : B() {} // expected-error 0-1 {{C++11}} - B(int*) : A() {} // expected-error {{no matching constructor}} - // expected-error@-1 {{must explicitly initialize the member 'a'}} + B(int) : B() {} + // cxx98-error@-1 {{delegating constructors are permitted only in C++11}} + B(int*) : A() {} // #dr655-delegating-to-A + // expected-error@-1 {{no matching constructor for initialization of 'A'}} + // expected-note@#dr655-A {{candidate constructor not viable: requires 1 argument, but 0 were provided}} + // expected-note@#dr655-A {{candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 0 were provided}} + // since-cxx11-note@#dr655-A {{candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 0 were provided}} + // expected-error@#dr655-delegating-to-A {{constructor for 'dr655::B' must explicitly initialize the member 'a' which does not have a default constructor}} + // expected-note@#dr655-a {{member is declared here}} + // expected-note@#dr655-A {{'dr655::A' declared here}} }; } namespace dr656 { // dr656: yes - struct A { A(const A&) = delete; }; // expected-error 0-1 {{C++11}} + struct A { A(const A&) = delete; }; + // cxx98-error@-1 {{deleted function definitions are a C++11 extension}} struct B : A {}; struct X { operator B(); } x; const A &r = x; - struct Y : private A { // expected-note 2{{here}} expected-note 2{{candidate}} + struct Y : private A { // #dr656-Y operator B() volatile; }; extern Y y; extern volatile Y vy; // Conversion not considered due to reference-related types. - const A &s = y; // expected-error {{private base class}} - const A &t = vy; // expected-error {{drops 'volatile'}} + const A &s = y; + // expected-error@-1 {{cannot cast 'const Y' to its private base class 'const A'}} + // expected-note@#dr656-Y {{declared private here}} + const A &t = vy; + // expected-error@-1 {{binding reference of type 'const A' to value of type 'volatile Y' drops 'volatile' qualifier}} struct C { operator struct D(); } c; struct D : C {}; const D &d = c; // ok, D not reference-related to C - template void accept(T); // expected-note {{candidate}} - template void accept(...) = delete; // expected-error 0-1 {{C++11}} expected-note {{candidate}} + template void accept(T); // #dr656-accept-T + template void accept(...) = delete; // #dr656-accept-var + // cxx98-error@-1 {{deleted function definitions are a C++11 extension}} void f() { accept(x); - accept(y); // expected-error {{private base class}} - accept(vy); // expected-error {{call to deleted}} expected-error {{no matching constructor}} + accept(y); + // expected-error@-1 {{cannot cast 'const Y' to its private base class 'const dr656::A'}} + // expected-note@#dr656-Y {{declared private here}} + accept(vy); // #dr656-vy + // expected-error@-1 {{call to deleted function 'accept'}} + // expected-note@#dr656-accept-var {{candidate function [with T = const dr656::A &] has been explicitly deleted}} + // expected-note@#dr656-accept-T {{candidate function template not viable: no known conversion from 'volatile Y' to 'const A &' for 1st argument}} + // expected-error@#dr656-vy {{no matching constructor for initialization of 'volatile Y'}} + // expected-note@#dr656-Y {{candidate constructor (the implicit copy constructor) not viable: 1st argument ('volatile Y') would lose volatile qualifier}} + // expected-note@#dr656-Y {{candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 1 was provided}} accept(c); } } namespace dr657 { // dr657: partial - struct Abs { virtual void x() = 0; }; // expected-note {{unimplemented pure virtual method 'x' in 'Abs'}} + struct Abs { virtual void x() = 0; }; // #dr657-Abs struct Der : public Abs { virtual void x(); }; struct Cnvt { template Cnvt(F); }; @@ -707,8 +777,11 @@ namespace dr657 { // dr657: partial // FIXME: The following examples demonstrate that we might be accepting the // above cases for the wrong reason. - struct C { C(Abs) {} }; // expected-error {{parameter type 'Abs' is an abstract class}} - struct Q { operator Abs() { __builtin_unreachable(); } } q; // expected-error {{return type 'Abs' is an abstract class}} + struct C { C(Abs) {} }; + // expected-error@-1 {{parameter type 'Abs' is an abstract class}} + // expected-note@#dr657-Abs {{unimplemented pure virtual method 'x' in 'Abs'}} + struct Q { operator Abs() { __builtin_unreachable(); } } q; + // expected-error@-1 {{return type 'Abs' is an abstract class}} #if __cplusplus >= 201703L // FIXME: We should *definitely* reject this. C c = Q().operator Abs(); @@ -728,24 +801,29 @@ namespace dr657 { // dr657: partial // dr658 FIXME: add codegen test #if __cplusplus >= 201103L -namespace dr659 { // dr659: yes +namespace dr659 { // dr659: 3.0 static_assert(alignof(char) == alignof(char&), ""); static_assert(alignof(int) == alignof(int&), ""); - int n = alignof(int(&)()); // expected-error {{application of 'alignof' to a function type}} - struct A; // expected-note {{forward}} - int m = alignof(A&); // expected-error {{application of 'alignof' to an incomplete type}} + int n = alignof(int(&)()); + // since-cxx11-error@-1 {{invalid application of 'alignof' to a function type}} + struct A; // #dr659-A + int m = alignof(A&); + // since-cxx11-error@-1 {{invalid application of 'alignof' to an incomplete type 'A'}} + // since-cxx11-note@#dr659-A {{forward declaration of 'dr659::A'}} } #endif #if __cplusplus >= 201103L -namespace dr660 { // dr660: yes +namespace dr660 { // dr660: 3.0 enum : int { a }; - enum class { b }; // expected-error {{requires a name}} + enum class { b }; + // since-cxx11-error@-1 {{scoped enumeration requires a name}} auto x = a; struct X { enum : int { a }; - enum class { b }; // expected-error {{requires a name}} + enum class { b }; + // since-cxx11-error@-1 {{scoped enumeration requires a name}} }; auto y = X::a; } @@ -756,12 +834,14 @@ namespace dr660 { // dr660: yes namespace dr662 { // dr662: yes template void f(T t) { T &tr = t; - T *tp = &t; // expected-error {{pointer to a reference}} + T *tp = &t; + // expected-error@-1 {{'tp' declared as a pointer to a reference of type 'int &'}} + // expected-note@#dr662-f-call {{in instantiation of function template specialization 'dr662::f' requested here}} #if __cplusplus >= 201103L auto *ap = &t; #endif } - void g(int n) { f(n); } // expected-note {{instantiation of}} + void g(int n) { f(n); } // #dr662-f-call } namespace dr663 { // dr663: sup P1949 @@ -779,47 +859,61 @@ namespace dr664 { // dr664: yes } #endif -namespace dr665 { // dr665: yes +namespace dr665 { // dr665: 2.8 struct A { virtual ~A(); }; struct B : A {} *b; - struct C : private A {} *c; // expected-note {{here}} + struct C : private A {} *c; // #dr665-C struct D : B, C {} *d; struct VB : virtual A {} *vb; - struct VC : private virtual A {} *vc; // expected-note {{here}} + struct VC : private virtual A {} *vc; // #dr665-VC struct VD : VB, VC {} *vd; void f() { (void)dynamic_cast(b); - (void)dynamic_cast(c); // expected-error {{private}} - (void)dynamic_cast(d); // expected-error {{ambiguous}} + (void)dynamic_cast(c); + // expected-error@-1 {{cannot cast 'dr665::C' to its private base class 'dr665::A'}} + // expected-note@#dr665-C {{declared private here}} + (void)dynamic_cast(d); + /* expected-error@-1 {{ambiguous conversion from derived class 'dr665::D' to base class 'dr665::A': + struct dr665::D -> B -> A + struct dr665::D -> C -> A}} */ (void)dynamic_cast(vb); - (void)dynamic_cast(vc); // expected-error {{private}}, even though it could be valid at runtime + (void)dynamic_cast(vc); // emitting diagnostic, even though it could be valid at runtime + // expected-error@-1 {{cannot cast 'dr665::VC' to its private base class 'dr665::A'}} + // expected-note@#dr665-VC {{declared private here}} (void)dynamic_cast(vd); } } -namespace dr666 { // dr666: yes +namespace dr666 { // dr666: 2.8 struct P { friend P operator*(P, P); P(int); } p(0); template int f(); template int f() { - T::type *p = 0; // expected-error {{missing 'typename'}} - int a(T::type); // expected-error {{missing 'typename'}} - return f(); // expected-error {{missing 'typename'}} + T::type *p = 0; + // expected-error@-1 {{missing 'typename' prior to dependent type name 'Y::type'}} + // expected-note@#dr666-f-Y {{in instantiation of function template specialization 'dr666::f' requested here}} + int a(T::type); + // expected-error@-1 {{missing 'typename' prior to dependent type name 'Y::type'}} + return f(); + // expected-error@-1 {{missing 'typename' prior to dependent type name 'Y::type'}} } struct X { static const int type = 0; }; struct Y { typedef int type; }; int a = f(); - int b = f(); // expected-note {{instantiation of}} + int b = f(); // #dr666-f-Y } // Triviality is entirely different in C++98. #if __cplusplus >= 201103L -namespace dr667 { // dr667: yes +namespace dr667 { // dr667: 8 struct A { - A() = default; // expected-warning {{explicitly defaulted default constructor is implicitly deleted}} expected-note{{replace 'default'}} - int &r; // expected-note {{because field 'r' of reference type 'int &' would not be initialized}} + A() = default; // #dr667-A-ctor + // since-cxx11-warning@-1 {{explicitly defaulted default constructor is implicitly deleted}} + // since-cxx11-note@#dr667-r {{default constructor of 'A' is implicitly deleted because field 'r' of reference type 'int &' would not be initialized}} + // since-cxx11-note@#dr667-A-ctor {{replace 'default' with 'delete'}} + int &r; // #dr667-r }; static_assert(!__is_trivially_constructible(A), ""); @@ -868,11 +962,13 @@ namespace dr669 { // dr669: yes } #endif -namespace dr671 { // dr671: yes - enum class E { e }; // expected-error 0-1 {{C++11}} +namespace dr671 { // dr671: 2.9 + enum class E { e }; + // cxx98-error@-1 {{scoped enumerations are a C++11 extension}} E e = static_cast(0); - int n = static_cast(E::e); // expected-error 0-1 {{C++11}} - int m = static_cast(e); // expected-error 0-1 {{C++11}} + int n = static_cast(E::e); + // cxx98-error@-1 {{use of enumeration in a nested name specifier is a C++11 extension}} + int m = static_cast(e); } // dr672 FIXME: add codegen test @@ -891,7 +987,8 @@ namespace dr673 { // dr673: yes C *c; D *d; E *e; - F *f; // expected-error {{unknown type name}} + F *f; + // expected-error@-1 {{unknown type name 'F'}} } namespace dr674 { // dr674: 8 @@ -907,17 +1004,22 @@ namespace dr674 { // dr674: 8 friend int dr674::f(int); friend int dr674::g(int); friend int dr674::h<>(int); - int n; // expected-note 2{{private}} + int n; // #dr674-X-n }; template int f(T) { return X().n; } int g(int) { return X().n; } - template int g(T) { return X().n; } // expected-error {{private}} - int h(int) { return X().n; } // expected-error {{private}} + template int g(T) { return X().n; } + // expected-error@-1 {{'n' is a private member of 'dr674::X'}} + // expected-note@#dr674-g-int {{in instantiation of function template specialization 'dr674::g' requested here}} + // expected-note@#dr674-X-n {{implicitly declared private here}} + int h(int) { return X().n; } + // expected-error@-1 {{'n' is a private member of 'dr674::X'}} + // expected-note@#dr674-X-n {{implicitly declared private here}} template int h(T) { return X().n; } template int f(int); - template int g(int); // expected-note {{in instantiation of}} + template int g(int); // #dr674-g-int template int h(int); @@ -935,27 +1037,35 @@ namespace dr674 { // dr674: 8 friend int Y::f(int); friend int Y::g(int); friend int Y::h<>(int); - int n; // expected-note 2{{private}} + int n; // #dr674-Z-n }; template int Y::f(T) { return Z().n; } int Y::g(int) { return Z().n; } - template int Y::g(T) { return Z().n; } // expected-error {{private}} - int Y::h(int) { return Z().n; } // expected-error {{private}} + template int Y::g(T) { return Z().n; } + // expected-error@-1 {{'n' is a private member of 'dr674::Z'}} + // expected-note@#dr674-Y-g-int {{in instantiation of function template specialization 'dr674::Y::g' requested here}} + // expected-note@#dr674-Z-n {{implicitly declared private here}} + int Y::h(int) { return Z().n; } + // expected-error@-1 {{'n' is a private member of 'dr674::Z'}} + // expected-note@#dr674-Z-n {{implicitly declared private here}} template int Y::h(T) { return Z().n; } // FIXME: Should the <> be required here? template int Y::f<>(int); - template int Y::g<>(int); // expected-note {{in instantiation of}} + template int Y::g<>(int); // #dr674-Y-g-int template int Y::h<>(int); } namespace dr675 { // dr675: dup 739 template struct A { T n : 1; }; #if __cplusplus >= 201103L - static_assert(A{1}.n < 0, ""); // expected-warning {{implicit truncation from 'int' to a one-bit wide bit-field changes value from 1 to -1}} - static_assert(A{1}.n < 0, ""); // expected-warning {{implicit truncation from 'int' to a one-bit wide bit-field changes value from 1 to -1}} - static_assert(A{1}.n < 0, ""); // expected-warning {{implicit truncation from 'int' to a one-bit wide bit-field changes value from 1 to -1}} + static_assert(A{1}.n < 0, ""); + // since-cxx11-warning@-1 {{implicit truncation from 'int' to a one-bit wide bit-field changes value from 1 to -1}} + static_assert(A{1}.n < 0, ""); + // since-cxx11-warning@-1 {{implicit truncation from 'int' to a one-bit wide bit-field changes value from 1 to -1}} + static_assert(A{1}.n < 0, ""); + // since-cxx11-warning@-1 {{implicit truncation from 'int' to a one-bit wide bit-field changes value from 1 to -1}} #endif } @@ -964,17 +1074,25 @@ namespace dr675 { // dr675: dup 739 namespace dr677 { // dr677: no struct A { void *operator new(std::size_t); - void operator delete(void*) = delete; // expected-error 0-1{{C++11}} expected-note {{deleted}} + void operator delete(void*) = delete; // #dr677-A-delete + // cxx98-error@-1 {{deleted function definitions are a C++11 extension}} }; struct B { void *operator new(std::size_t); - void operator delete(void*) = delete; // expected-error 0-1{{C++11}} expected-note 2{{deleted}} + void operator delete(void*) = delete; // #dr677-B-delete + // cxx98-error@-1 {{deleted function definitions are a C++11 extension}} virtual ~B(); }; - void f(A *p) { delete p; } // expected-error {{deleted}} + void f(A *p) { delete p; } + // expected-error@-1 {{attempt to use a deleted function}} + // expected-note@#dr677-A-delete {{'operator delete' has been explicitly marked deleted here}} // FIXME: This appears to be valid; we shouldn't even be looking up the 'operator delete' here. - void f(B *p) { delete p; } // expected-error {{deleted}} - B::~B() {} // expected-error {{deleted}} + void f(B *p) { delete p; } + // expected-error@-1 {{attempt to use a deleted function}} + // expected-note@#dr677-B-delete {{'operator delete' has been explicitly marked deleted here}} + B::~B() {} + // expected-error@-1 {{attempt to use a deleted function}} + // expected-note@#dr677-B-delete {{'operator delete' has been explicitly marked deleted here}} } // dr678 FIXME: check that the modules ODR check catches this @@ -982,24 +1100,31 @@ namespace dr677 { // dr677: no namespace dr679 { // dr679: yes struct X {}; template void operator+(X, X); - template<> void operator+<0>(X, X) {} // expected-note {{previous}} - template<> void operator+<0>(X, X) {} // expected-error {{redefinition}} + template<> void operator+<0>(X, X) {} // #dr679-def + template<> void operator+<0>(X, X) {} + // expected-error@-1 {{redefinition of 'operator+<0>'}} + // expected-note@#dr679-def {{previous definition is here}} } // dr680: na #if __cplusplus >= 201103L namespace dr681 { // dr681: partial - auto *a() -> int; // expected-error {{must specify return type 'auto', not 'auto *'}} + auto *a() -> int; + // since-cxx11-error@-1 {{function with trailing return type must specify return type 'auto', not 'auto *'}} auto (*b)() -> int; // FIXME: The errors here aren't great. - auto (*c()) -> int; // expected-error {{expected function body}} - auto ((*d)()) -> int; // expected-error {{expected ';'}} expected-error {{requires an initializer}} + auto (*c()) -> int; + // since-cxx11-error@-1 {{expected function body after function declarator}} + auto ((*d)()) -> int; + // since-cxx11-error@-1 {{declaration of variable 'd' with deduced type 'auto ((*)())' requires an initializer}} + // since-cxx11-error@-2 {{expected ';' after top level declarator}} // FIXME: This is definitely wrong. This should be // "function of () returning pointer to function of () returning int" // not a function with a deduced return type. - auto (*e())() -> int; // expected-error 0-1{{C++14}} + auto (*e())() -> int; + // cxx11-error@-1 {{'auto' return without trailing return type; deduced return types are a C++14 extension}} auto f() -> int (*)(); auto g() -> auto (*)() -> int; @@ -1027,25 +1152,24 @@ namespace dr683 { // dr683: yes #if __cplusplus >= 201103L namespace dr684 { // dr684: sup 1454 void f() { - int a; // expected-note {{here}} - constexpr int *p = &a; // expected-error {{constant expression}} expected-note {{pointer to 'a'}} + int a; // #dr684-a + constexpr int *p = &a; + // expected-error@-1 {{constexpr variable 'p' must be initialized by a constant expression}} + // expected-note@-2 {{pointer to 'a' is not a constant expression}} + // expected-note@#dr684-a {{here}} } } #endif namespace dr685 { // dr685: yes enum E : long { e }; -#if __cplusplus < 201103L - // expected-error@-2 {{enumeration types with a fixed underlying type are a C++11 extension}} -#endif + // cxx98-error@-1 {{enumeration types with a fixed underlying type are a C++11 extension}} void f(int); int f(long); int a = f(e); enum G : short { g }; -#if __cplusplus < 201103L - // expected-error@-2 {{enumeration types with a fixed underlying type are a C++11 extension}} -#endif + // cxx98-error@-1 {{enumeration types with a fixed underlying type are a C++11 extension}} int h(short); void h(long); int b = h(g); @@ -1054,9 +1178,12 @@ namespace dr685 { // dr685: yes void i(long); int c = i(g); - int j(unsigned int); // expected-note {{candidate}} - void j(long); // expected-note {{candidate}} - int d = j(g); // expected-error {{ambiguous}} + int j(unsigned int); // #dr685-j-uint + void j(long); // #dr685-j-long + int d = j(g); + // expected-error@-1 {{call to 'j' is ambiguous}} + // expected-note@#dr685-j-uint {{candidate function}} + // expected-note@#dr685-j-long {{candidate function}} // Valid per dr1601 int k(short); @@ -1064,61 +1191,83 @@ namespace dr685 { // dr685: yes int x = k(g); } -namespace dr686 { // dr686: yes +namespace dr686 { // dr686: 3.0 void f() { - (void)dynamic_cast(0); // expected-error {{incomplete}} expected-note {{forward}} - (void)dynamic_cast(0); // expected-error {{cannot be defined in a type specifier}} + (void)dynamic_cast(0); + // expected-error@-1 {{'A' is an incomplete type}} + // expected-note@-2 {{forward declaration of 'A'}} + (void)dynamic_cast(0); + // expected-error@-1 {{'A' cannot be defined in a type specifier}} (void)typeid(struct B*); - (void)typeid(struct B{}*); // expected-error {{cannot be defined in a type specifier}} + (void)typeid(struct B{}*); + // expected-error@-1 {{'B' cannot be defined in a type specifier}} (void)static_cast(0); - (void)static_cast(0); // expected-error {{cannot be defined in a type specifier}} + (void)static_cast(0); + // expected-error@-1 {{'C' cannot be defined in a type specifier}} (void)reinterpret_cast(0); - (void)reinterpret_cast(0); // expected-error {{cannot be defined in a type specifier}} - (void)const_cast(0); // expected-error {{not allowed}} - (void)const_cast(0); // expected-error {{cannot be defined in a type specifier}} + (void)reinterpret_cast(0); + // expected-error@-1 {{'D' cannot be defined in a type specifier}} + (void)const_cast(0); + // expected-error@-1 {{const_cast from 'int' to 'struct E *' is not allowed}} + (void)const_cast(0); + // expected-error@-1 {{'E' cannot be defined in a type specifier}} (void)sizeof(struct F*); - (void)sizeof(struct F{}*); // expected-error {{cannot be defined in a type specifier}} - (void)new struct G*; // expected-note {{forward}} - (void)new struct G{}*; // expected-error {{incomplete}} + (void)sizeof(struct F{}*); + // expected-error@-1 {{'F' cannot be defined in a type specifier}} + (void)new struct G*; // #dr686-G + (void)new struct G{}*; // #dr686-G-def + // expected-error@-1 {{allocation of incomplete type 'struct G'}} + // expected-note@#dr686-G {{forward declaration of 'G'}} + // since-cxx11-error@#dr686-G-def {{expected expression}} #if __cplusplus >= 201103L - // expected-error@-2 {{expected expression}} (void)alignof(struct H*); - (void)alignof(struct H{}*); // expected-error {{cannot be defined in a type specifier}} + (void)alignof(struct H{}*); + // since-cxx11-error@-1 {{'H' cannot be defined in a type specifier}} #endif (void)(struct I*)0; - (void)(struct I{}*)0; // expected-error {{cannot be defined in a type specifier}} + (void)(struct I{}*)0; + // expected-error@-1 {{'I' cannot be defined in a type specifier}} if (struct J *p = 0) {} - if (struct J {} *p = 0) {} // expected-error {{cannot be defined in a condition}} + if (struct J {} *p = 0) {} + // expected-error@-1 {{'J' cannot be defined in a condition}} for (struct K *p = 0; struct L *q = 0; ) {} - for (struct K {} *p = 0; struct L {} *q = 0; ) {} // expected-error {{'L' cannot be defined in a condition}} + for (struct K {} *p = 0; struct L {} *q = 0; ) {} + // expected-error@-1 {{'L' cannot be defined in a condition}} #if __cplusplus >= 201103L using M = struct {}; #endif struct N { - operator struct O{}(){}; // expected-error {{cannot be defined in a type specifier}} + operator struct O{}(){}; + // expected-error@-1 {{'N::O' cannot be defined in a type specifier}} }; try {} - catch (struct P *) {} // expected-error {{incomplete}} expected-note {{forward}} - catch (struct P {} *) {} // expected-error {{cannot be defined in a type specifier}} + catch (struct P *) {} + // expected-error@-1 {{cannot catch pointer to incomplete type 'struct P'}} + // expected-note@-2 {{forward declaration of 'P'}} + catch (struct P {} *) {} + // expected-error@-1 {{'P' cannot be defined in a type specifier}} #if __cplusplus < 201703L - void g() throw(struct Q); // expected-error {{incomplete}} expected-note {{forward}} - void h() throw(struct Q {}); // expected-error {{cannot be defined in a type specifier}} + void g() throw(struct Q); + // cxx98-17-error@-1 {{incomplete type 'struct Q' is not allowed in exception specification}} + // cxx98-17-note@-2 {{forward declaration of 'Q'}} + void h() throw(struct Q {}); + // cxx98-17-error@-1 {{'Q' cannot be defined in a type specifier}} #endif } template struct X; - template struct Y; // expected-error {{cannot be defined in a type specifier}} + template struct Y; + // expected-error@-1 {{'dr686::R' cannot be defined in a type specifier}} } namespace dr687 { // dr687 (9 c++20, but the issue is still considered open) template void f(T a) { // This is valid in C++20. g(a); -#if __cplusplus <= 201703L - // expected-error@-2 {{C++20 extension}} -#endif + // cxx98-17-error@-1 {{use of function template name with no prior declaration in function call with explicit template arguments is a C++20 extension}} // This is not. - template g(a); // expected-error {{expected expression}} + template g(a); + // expected-error@-1 {{expected expression}} } } @@ -1126,16 +1275,24 @@ namespace dr692 { // dr692: 16 // Also see dr1395. namespace temp_func_order_example2 { - template struct A1 {}; // expected-error 0-1{{C++11}} - template struct A2 {}; // expected-error 0-1{{C++11}} - template void e1(A1) = delete; // expected-error 0-2{{C++11}} + template struct A1 {}; + // cxx98-error@-1 {{variadic templates are a C++11 extension}} + template struct A2 {}; + // cxx98-error@-1 {{variadic templates are a C++11 extension}} + template void e1(A1) = delete; + // cxx98-error@-1 {{variadic templates are a C++11 extension}} + // cxx98-error@-2 {{deleted function definitions are a C++11 extension}} template void e1(A1); - template void e2(A2) = delete; // expected-error 0-2{{C++11}} + template void e2(A2) = delete; + // cxx98-error@-1 {{variadic templates are a C++11 extension}} + // cxx98-error@-2 {{deleted function definitions are a C++11 extension}} template void e2(A2); - template void f(U, A1 *p = 0) = delete; // expected-note {{candidate}} expected-error 0-1{{C++11}} - template int &f(U, A1 *p = 0); // expected-note {{candidate}} - template void g(T, T = T()); // expected-note {{candidate}} - template void g(T, U...); // expected-note {{candidate}} expected-error 0-1{{C++11}} + template void f(U, A1 *p = 0) = delete; // #dr692-f-deleted + // cxx98-error@-1 {{deleted function definitions are a C++11 extension}} + template int &f(U, A1 *p = 0); // #dr692-f + template void g(T, T = T()); // #dr692-g + template void g(T, U...); // #dr692-g-variadic + // cxx98-error@-1 {{variadic templates are a C++11 extension}} void h() { A1 a; int &r = f(42, &a); @@ -1143,15 +1300,23 @@ namespace dr692 { // dr692: 16 e1(b1); A2 b2; e2(b2); - f(42); // expected-error {{ambiguous}} - g(42); // expected-error {{ambiguous}} + f(42); + // expected-error@-1 {{call to 'f' is ambiguous}} + // expected-note@#dr692-f-deleted {{candidate function [with T = int, U = int] has been explicitly deleted}} + // expected-note@#dr692-f {{candidate function [with U = int]}} + g(42); + // expected-error@-1 {{ambiguous}} + // expected-note@#dr692-g {{candidate function [with T = int]}} + // expected-note@#dr692-g-variadic {{candidate function [with T = int, U = <>]}} } } namespace temp_func_order_example3 { - template void f(T, U...); // expected-error 0-1{{C++11}} + template void f(T, U...); + // cxx98-error@-1 {{variadic templates are a C++11 extension}} template void f(T); - template int &g(T *, U...); // expected-error 0-1{{C++11}} + template int &g(T *, U...); + // cxx98-error@-1 {{variadic templates are a C++11 extension}} template void g(T); void h(int i) { // This is made ambiguous by dr692, but made valid again by dr1395. @@ -1161,8 +1326,10 @@ namespace dr692 { // dr692: 16 } namespace temp_deduct_partial_example { - template char &f(Args... args); // expected-error 0-1{{C++11}} - template short &f(T1 a1, Args... args); // expected-error 0-1{{C++11}} + template char &f(Args... args); + // cxx98-error@-1 {{variadic templates are a C++11 extension}} + template short &f(T1 a1, Args... args); + // cxx98-error@-1 {{variadic templates are a C++11 extension}} template int &f(T1 a1, T2 a2); void g() { char &a = f(); @@ -1172,37 +1339,51 @@ namespace dr692 { // dr692: 16 } namespace temp_deduct_type_example1 { - template class S; // expected-error 0-1{{C++11}} - template class S; // expected-error 0-1{{C++11}} + template class S; + // cxx98-error@-1 {{variadic templates are a C++11 extension}} + template class S; + // cxx98-error@-1 {{variadic templates are a C++11 extension}} template class S {}; S s; - template struct A; // expected-error 0-1{{C++11}} - template struct A {}; // expected-error 0-1{{C++11}} + template struct A; + // cxx98-error@-1 {{variadic templates are a C++11 extension}} + template struct A {}; + // cxx98-error@-1 {{variadic templates are a C++11 extension}} template struct A; template struct A; } namespace temp_deduct_type_example3 { - template void f(T*, U...){} // expected-error 0-1{{C++11}} + template void f(T*, U...){} + // cxx98-error@-1 {{variadic templates are a C++11 extension}} template void f(T){} template void f(int*); } } -namespace dr696 { // dr696: yes +namespace dr696 { // dr696: 3.1 void f(const int*); void g() { - const int N = 10; // expected-note 1+{{here}} + const int N = 10; // #dr696-N struct A { void h() { int arr[N]; (void)arr; - f(&N); // expected-error {{declared in enclosing}} + f(&N); + // expected-error@-1 {{reference to local variable 'N' declared in enclosing function 'dr696::g'}} + // expected-note@#dr696-N {{'N' declared here}} } }; #if __cplusplus >= 201103L (void) [] { int arr[N]; (void)arr; }; - (void)[] { f(&N); }; // expected-error {{cannot be implicitly captured}} expected-note {{here}} expected-note 2 {{capture 'N' by}} expected-note 2 {{default capture by}} + (void)[] { f(&N); }; + // since-cxx11-error@-1 {{variable 'N' cannot be implicitly captured in a lambda with no capture-default specified}} + // since-cxx11-note@#dr696-N {{'N' declared here}} + // since-cxx11-note@-3 {{lambda expression begins here}} + // since-cxx11-note@-4 {{capture 'N' by value}} + // since-cxx11-note@-5 {{capture 'N' by reference}} + // since-cxx11-note@-6 {{default capture by value}} + // since-cxx11-note@-7 {{default capture by reference}} #endif } } diff --git a/clang/test/CXX/drs/dr7xx.cpp b/clang/test/CXX/drs/dr7xx.cpp index 11901b80d64622555649076cfb665de4842f48e8..926bff1cc479c5c7d0f9ce7597dd318b7b145422 100644 --- a/clang/test/CXX/drs/dr7xx.cpp +++ b/clang/test/CXX/drs/dr7xx.cpp @@ -1,37 +1,53 @@ -// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++98 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++11 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++14 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++17 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++2a %s -verify -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++98 %s -verify=expected,cxx98-14,cxx98-11 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++11 %s -verify=expected,cxx98-14,cxx98-11,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++14 %s -verify=expected,cxx98-14,since-cxx14,since-cxx11,cxx14 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++17 %s -verify=expected,since-cxx14,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++2a %s -verify=expected,since-cxx14,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors namespace dr705 { // dr705: yes namespace N { struct S {}; - void f(S); // expected-note {{declared here}} + void f(S); // #dr705-f } void g() { N::S s; f(s); // ok - (f)(s); // expected-error {{use of undeclared}} + (f)(s); + // expected-error@-1 {{use of undeclared identifier 'f'}} + // expected-note@#dr705-f {{'N::f' declared here}} } } namespace dr712 { // dr712: partial void use(int); void f() { - const int a = 0; // expected-note 5{{here}} + const int a = 0; // #dr712-f-a struct X { void g(bool cond) { use(a); use((a)); use(cond ? a : a); - use((cond, a)); // expected-warning 2{{left operand of comma operator has no effect}} FIXME: should only warn once - - (void)a; // FIXME: expected-error {{declared in enclosing}} - (void)(a); // FIXME: expected-error {{declared in enclosing}} - (void)(cond ? a : a); // FIXME: expected-error 2{{declared in enclosing}} - (void)(cond, a); // FIXME: expected-error {{declared in enclosing}} expected-warning {{left operand of comma operator has no effect}} + // FIXME: should only warn once + use((cond, a)); + // expected-warning@-1 {{left operand of comma operator has no effect}} + // expected-warning@-2 {{left operand of comma operator has no effect}} + + (void)a; + // expected-error@-1 {{reference to local variable 'a' declared in enclosing function 'dr712::f'}} FIXME + // expected-note@#dr712-f-a {{'a' declared here}} + (void)(a); + // expected-error@-1 {{reference to local variable 'a' declared in enclosing function 'dr712::f'}} FIXME + // expected-note@#dr712-f-a {{'a' declared here}} + (void)(cond ? a : a); // #dr712-ternary + // expected-error@#dr712-ternary {{reference to local variable 'a' declared in enclosing function 'dr712::f'}} FIXME + // expected-note@#dr712-f-a {{'a' declared here}} + // expected-error@#dr712-ternary {{reference to local variable 'a' declared in enclosing function 'dr712::f'}} FIXME + // expected-note@#dr712-f-a {{'a' declared here}} + (void)(cond, a); // #dr712-comma + // expected-error@-1 {{reference to local variable 'a' declared in enclosing function 'dr712::f'}} FIXME + // expected-note@#dr712-f-a {{'a' declared here}} + // expected-warning@#dr712-comma {{left operand of comma operator has no effect}} } }; } @@ -39,14 +55,18 @@ namespace dr712 { // dr712: partial #if __cplusplus >= 201103L void g() { struct A { int n; }; - constexpr A a = {0}; // expected-note 2{{here}} + constexpr A a = {0}; // #dr712-g-a struct X { void g(bool cond) { use(a.n); use(a.*&A::n); - (void)a.n; // FIXME: expected-error {{declared in enclosing}} - (void)(a.*&A::n); // FIXME: expected-error {{declared in enclosing}} + (void)a.n; + // since-cxx11-error@-1 {{reference to local variable 'a' declared in enclosing function 'dr712::g'}} FIXME + // since-cxx11-note@#dr712-g-a {{'a' declared here}} + (void)(a.*&A::n); + // since-cxx11-error@-1 {{reference to local variable 'a' declared in enclosing function 'dr712::g'}} FIXME + // since-cxx11-note@#dr712-g-a {{'a' declared here}} } }; } @@ -55,9 +75,10 @@ namespace dr712 { // dr712: partial namespace dr727 { // dr727: partial struct A { - template struct C; // expected-note 6{{here}} - template void f(); // expected-note {{here}} - template static int N; // expected-error 0-1{{C++14}} expected-note 6{{here}} + template struct C; // #dr727-C + template void f(); // #dr727-f + template static int N; // #dr727-N + // cxx98-11-error@-1 {{variable templates are a C++14 extension}} template<> struct C; template<> void f(); @@ -67,19 +88,40 @@ namespace dr727 { // dr727: partial template static int N; struct B { - template<> struct C; // expected-error {{not in class 'A' or an enclosing namespace}} - template<> void f(); // expected-error {{no function template matches}} - template<> static int N; // expected-error {{not in class 'A' or an enclosing namespace}} - - template struct C; // expected-error {{not in class 'A' or an enclosing namespace}} - template static int N; // expected-error {{not in class 'A' or an enclosing namespace}} - - template<> struct A::C; // expected-error {{not in class 'A' or an enclosing namespace}} - template<> void A::f(); // expected-error {{no function template matches}} expected-error {{cannot have a qualified name}} - template<> static int A::N; // expected-error {{not in class 'A' or an enclosing namespace}} expected-error {{cannot have a qualified name}} - - template struct A::C; // expected-error {{not in class 'A' or an enclosing namespace}} - template static int A::N; // expected-error {{not in class 'A' or an enclosing namespace}} expected-error {{cannot have a qualified name}} + template<> struct C; + // expected-error@-1 {{class template specialization of 'C' not in class 'A' or an enclosing namespace}} + // expected-note@#dr727-C {{explicitly specialized declaration is here}} + template<> void f(); + // expected-error@-1 {{no function template matches function template specialization 'f'}} + template<> static int N; + // expected-error@-1 {{variable template specialization of 'N' not in class 'A' or an enclosing namespace}} + // expected-note@#dr727-N {{explicitly specialized declaration is here}} + + template struct C; + // expected-error@-1 {{class template partial specialization of 'C' not in class 'A' or an enclosing namespace}} + // expected-note@#dr727-C {{explicitly specialized declaration is here}} + template static int N; + // expected-error@-1 {{variable template partial specialization of 'N' not in class 'A' or an enclosing namespace}} + // expected-note@#dr727-N {{explicitly specialized declaration is here}} + + template<> struct A::C; + // expected-error@-1 {{class template specialization of 'C' not in class 'A' or an enclosing namespace}} + // expected-note@#dr727-C {{explicitly specialized declaration is here}} + template<> void A::f(); + // expected-error@-1 {{o function template matches function template specialization 'f'}} + // expected-error@-2 {{non-friend class member 'f' cannot have a qualified name}} + template<> static int A::N; + // expected-error@-1 {{non-friend class member 'N' cannot have a qualified name}} + // expected-error@-2 {{variable template specialization of 'N' not in class 'A' or an enclosing namespace}} + // expected-note@#dr727-N {{explicitly specialized declaration is here}} + + template struct A::C; + // expected-error@-1 {{class template partial specialization of 'C' not in class 'A' or an enclosing namespace}} + // expected-note@#dr727-C {{explicitly specialized declaration is here}} + template static int A::N; + // expected-error@-1 {{non-friend class member 'N' cannot have a qualified name}} + // expected-error@-2 {{variable template partial specialization of 'N' not in class 'A' or an enclosing namespace}} + // expected-note@#dr727-N {{explicitly specialized declaration is here}} }; }; @@ -91,19 +133,36 @@ namespace dr727 { // dr727: partial template int A::N; namespace C { - template<> struct A::C; // expected-error {{not in class 'A' or an enclosing namespace}} - template<> void A::f(); // expected-error {{not in class 'A' or an enclosing namespace}} - template<> int A::N; // expected-error {{not in class 'A' or an enclosing namespace}} - - template struct A::C; // expected-error {{not in class 'A' or an enclosing namespace}} - template int A::N; // expected-error {{not in class 'A' or an enclosing namespace}} + template<> struct A::C; + // expected-error@-1 {{class template specialization of 'C' not in class 'A' or an enclosing namespace}} + // expected-note@#dr727-C {{explicitly specialized declaration is here}} + template<> void A::f(); + // expected-error@-1 {{function template specialization of 'f' not in class 'A' or an enclosing namespace}} + // expected-note@#dr727-f {{explicitly specialized declaration is here}} + template<> int A::N; + // expected-error@-1 {{variable template specialization of 'N' not in class 'A' or an enclosing namespace}} + // expected-note@#dr727-N {{explicitly specialized declaration is here}} + + template struct A::C; + // expected-error@-1 {{class template partial specialization of 'C' not in class 'A' or an enclosing namespace}} + // expected-note@#dr727-C {{explicitly specialized declaration is here}} + template int A::N; + // expected-error@-1 {{variable template partial specialization of 'N' not in class 'A' or an enclosing namespace}} + // expected-note@#dr727-N {{explicitly specialized declaration is here}} } template struct D { - template struct C { typename T::error e; }; // expected-error {{no members}} - template void f() { T::error; } // expected-error {{no members}} - template static const int N = T::error; // expected-error {{no members}} expected-error 0-1{{C++14}} + template struct C { typename T::error e; }; + // expected-error@-1 {{type 'float' cannot be used prior to '::' because it has no members}} + // expected-note@#dr727-C-float {{in instantiation of template class 'dr727::D::C' requested here}} + template void f() { T::error; } + // expected-error@-1 {{type 'float' cannot be used prior to '::' because it has no members}} + // expected-note@#dr727-f-float {{in instantiation of function template specialization 'dr727::D::f' requested here}} + template static const int N = T::error; + // cxx98-11-error@-1 {{variable templates are a C++14 extension}} + // expected-error@-2 {{type 'float' cannot be used prior to '::' because it has no members}} + // expected-note@#dr727-N-float {{in instantiation of static data member 'dr727::D::N' requested here}} template<> struct C {}; template<> void f() {} @@ -114,7 +173,8 @@ namespace dr727 { // dr727: partial template struct E { - template<> void f() {} // expected-error {{no candidate function template}} + template<> void f() {} + // expected-error@-1 {{no candidate function template was found for dependent member function template specialization}} }; }; @@ -126,9 +186,9 @@ namespace dr727 { // dr727: partial D::C(); int b = D::N; - D::C(); // expected-note {{instantiation of}} - di.f(); // expected-note {{instantiation of}} - int c = D::N; // expected-note {{instantiation of}} + D::C(); // #dr727-C-float + di.f(); // #dr727-f-float + int c = D::N; // #dr727-N-float } namespace mixed_inner_outer_specialization { @@ -148,28 +208,30 @@ namespace dr727 { // dr727: partial #if __cplusplus >= 201402L template struct B { template static const int u = 1; - template<> static const int u<0> = 2; // expected-note {{here}} + template<> static const int u<0> = 2; // #dr727-u0 // Note that in C++17 onwards, these are implicitly inline, and so the // initializer of v<0> is not instantiated with the declaration. In // C++14, v<0> is a non-defining declaration and its initializer is // instantiated with the class. template static constexpr int v = 1; - template<> static constexpr int v<0> = 2; // #v0 + template<> static constexpr int v<0> = 2; // #dr727-v0 - template static const inline int w = 1; // expected-error 0-1{{C++17 extension}} - template<> static const inline int w<0> = 2; // expected-error 0-1{{C++17 extension}} + template static const inline int w = 1; + // cxx14-error@-1 {{inline variables are a C++17 extension}} + template<> static const inline int w<0> = 2; + // cxx14-error@-1 {{inline variables are a C++17 extension}} }; template<> template constexpr int B<0>::u = 3; - template<> template<> constexpr int B<0>::u<0> = 4; // expected-error {{already has an initializer}} + template<> template<> constexpr int B<0>::u<0> = 4; + // since-cxx14-error@-1 {{static data member 'u' already has an initializer}} + // since-cxx14-note@#dr727-u0 {{previous initialization is here}} template<> template constexpr int B<0>::v = 3; template<> template<> constexpr int B<0>::v<0> = 4; -#if __cplusplus < 201702L - // expected-error@-2 {{already has an initializer}} - // expected-note@#v0 {{here}} -#endif + // cxx14-error@-1 {{static data member 'v' already has an initializer}} + // cxx14-note@#dr727-v0 {{previous initialization is here}} template<> template constexpr int B<0>::w = 3; template<> template<> constexpr int B<0>::w<0> = 4; @@ -182,10 +244,8 @@ namespace dr727 { // dr727: partial static_assert(B<1>().v<0> == 2, ""); static_assert(B<0>().v<1> == 3, ""); static_assert(B<0>().v<0> == 4, ""); -#if __cplusplus < 201702L - // expected-error@-2 {{failed}} \ - // expected-note@-2 {{evaluates to '2 == 4'}} -#endif + // cxx14-error@-1 {{static assertion failed due to requirement 'dr727::mixed_inner_outer_specialization::B<0>().v<0> == 4'}} + // cxx14-note@-2 {{expression evaluates to '2 == 4'}} static_assert(B<1>().w<1> == 1, ""); static_assert(B<1>().w<0> == 2, ""); @@ -205,13 +265,23 @@ namespace dr727 { // dr727: partial template<> int f2() {} template<> int f2() {} - template static int v1; // expected-error 0-1{{C++14 extension}} - template<> static int v1; // expected-note {{previous}} - template<> static int v1; // expected-error {{duplicate member}} - - template static inline int v2; // expected-error 0-1{{C++17 extension}} expected-error 0-1{{C++14 extension}} - template<> static inline int v2; // expected-error 0-1{{C++17 extension}} expected-note {{previous}} - template<> static inline int v2; // expected-error 0-1{{C++17 extension}} expected-error {{duplicate member}} + template static int v1; + // cxx98-11-error@-1 {{variable templates are a C++14 extension}} + template<> static int v1; // #dr727-v1-T + template<> static int v1; + // expected-error@-1 {{duplicate member 'v1'}} + // expected-note@#dr727-Collision-int-int {{in instantiation of template class 'dr727::Collision' requested here}} + // expected-note@#dr727-v1-T {{previous}} + + template static inline int v2; + // cxx98-11-error@-1 {{variable templates are a C++14 extension}} + // cxx98-14-error@-2 {{inline variables are a C++17 extension}} + template<> static inline int v2; // #dr727-v2-T + // cxx98-14-error@-1 {{inline variables are a C++17 extension}} + template<> static inline int v2; + // cxx98-14-error@-1 {{inline variables are a C++17 extension}} + // expected-error@-2 {{duplicate member 'v2'}} + // expected-note@#dr727-v2-T {{previous declaration is here}} // FIXME: Missing diagnostic for duplicate class explicit specialization. template struct S1; @@ -219,10 +289,12 @@ namespace dr727 { // dr727: partial template<> struct S1; template struct S2; - template<> struct S2 {}; // expected-note {{previous}} - template<> struct S2 {}; // expected-error {{redefinition}} + template<> struct S2 {}; // #dr727-S2-T + template<> struct S2 {}; + // expected-error@-1 {{redefinition of 'S2'}} + // expected-note@#dr727-S2-T {{previous}} }; - Collision c; // expected-note {{in instantiation of}} + Collision c; // #dr727-Collision-int-int } namespace dr777 { // dr777: 3.7 diff --git a/clang/test/CXX/drs/dr8xx.cpp b/clang/test/CXX/drs/dr8xx.cpp index d79430f9e03cae2d94914fea6614a05a178b2c80..b031e65095cdb03c1895e8e23978f5897a620fa4 100644 --- a/clang/test/CXX/drs/dr8xx.cpp +++ b/clang/test/CXX/drs/dr8xx.cpp @@ -1,30 +1,27 @@ -// RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s -// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s -// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s -// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s -// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s -// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s +// RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -verify=expected -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors +#if __cplusplus == 199711L // expected-no-diagnostics +#endif -namespace dr873 { // dr873: yes +namespace dr873 { // dr873: 3.0 #if __cplusplus >= 201103L template void f(T &&); -template <> void f(int &) {} // #1 -template <> void f(int &&) {} // #2 +template <> void f(int &) = delete; // #dr873-lvalue-ref +template <> void f(int &&) = delete; // #dr873-rvalue-ref void g(int i) { - f(i); // calls f(int&), i.e., #1 -#pragma clang __debug dump f(i) - // CHECK: CallExpr {{.*}} - // CHECK-NEXT: |-ImplicitCastExpr {{.*}} - // CHECK-NEXT: | `-DeclRefExpr {{.*}} 'f' 'void (int &)' {{.*}} - - f(0); // calls f(int&&), i.e., #2 -#pragma clang __debug dump f(0) - // CHECK: CallExpr {{.*}} - // CHECK-NEXT: |-ImplicitCastExpr {{.*}} - // CHECK-NEXT: | `-DeclRefExpr {{.*}} 'f' 'void (int &&)' {{.*}} + f(i); // calls f(int&) + // since-cxx11-error@-1 {{call to deleted function 'f'}} + // since-cxx11-note@#dr873-lvalue-ref {{candidate function [with T = int &] has been implicitly deleted}} + f(0); // calls f(int&&) + // since-cxx11-error@-1 {{call to deleted function 'f'}} + // since-cxx11-note@#dr873-rvalue-ref {{candidate function [with T = int] has been implicitly deleted}} } #endif } // namespace dr873 diff --git a/clang/test/CXX/drs/dr9xx.cpp b/clang/test/CXX/drs/dr9xx.cpp index fb13ef2967f8804c6b49d8ce3995f1e860a2f607..7ea295a684b7a299a192305614da4d27affe0ef5 100644 --- a/clang/test/CXX/drs/dr9xx.cpp +++ b/clang/test/CXX/drs/dr9xx.cpp @@ -1,9 +1,9 @@ -// RUN: %clang_cc1 -std=c++98 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++11 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++14 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++17 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++20 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++23 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++98 %s -verify=expected -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++11 %s -verify=expected,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++14 %s -verify=expected,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++17 %s -verify=expected,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++20 %s -verify=expected,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++23 %s -verify=expected,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors namespace std { __extension__ typedef __SIZE_TYPE__ size_t; @@ -43,30 +43,34 @@ namespace dr948 { // dr948: 3.7 #endif } -namespace dr952 { // dr952: yes +namespace dr952 { // dr952: 2.8 namespace example1 { struct A { - typedef int I; // #dr952-typedef-decl + typedef int I; // #dr952-I }; -struct B : private A { // #dr952-inheritance +struct B : private A { // #dr952-B }; struct C : B { void f() { - I i1; // expected-error {{private member}} - // expected-note@#dr952-inheritance {{constrained by private inheritance}} - // expected-note@#dr952-typedef-decl {{declared here}} + I i1; + // expected-error@-1 {{'I' is a private member of 'dr952::example1::A'}} + // expected-note@#dr952-B {{constrained by private inheritance here}} + // expected-note@#dr952-I {{member is declared here}} } - I i2; // expected-error {{private member}} - // expected-note@#dr952-inheritance {{constrained by private inheritance}} - // expected-note@#dr952-typedef-decl {{declared here}} + I i2; + // expected-error@-1 {{'I' is a private member of 'dr952::example1::A'}} + // expected-note@#dr952-B {{constrained by private inheritance here}} + // expected-note@#dr952-I {{member is declared here}} struct D { - I i3; // expected-error {{private member}} - // expected-note@#dr952-inheritance {{constrained by private inheritance}} - // expected-note@#dr952-typedef-decl {{declared here}} + I i3; + // expected-error@-1 {{'I' is a private member of 'dr952::example1::A'}} + // expected-note@#dr952-B {{constrained by private inheritance here}} + // expected-note@#dr952-I {{member is declared here}} void g() { - I i4; // expected-error {{private member}} - // expected-note@#dr952-inheritance {{constrained by private inheritance}} - // expected-note@#dr952-typedef-decl {{declared here}} + I i4; + // expected-error@-1 {{'I' is a private member of 'dr952::example1::A'}} + // expected-note@#dr952-B {{constrained by private inheritance here}} + // expected-note@#dr952-I {{member is declared here}} } }; }; @@ -91,10 +95,10 @@ namespace dr974 { // dr974: yes } namespace dr977 { // dr977: yes -enum E { e = E() }; +enum E { e = E() }; // #dr977-E #if !defined(_WIN32) || defined(__MINGW32__) -// expected-error@-2 {{invalid use of incomplete type 'E'}} -// expected-note@-3 {{definition of 'dr977::E' is not complete until the closing '}'}} +// expected-error@#dr977-E {{invalid use of incomplete type 'E'}} +// expected-note@#dr977-E {{definition of 'dr977::E' is not complete until the closing '}'}} #endif #if __cplusplus >= 201103L enum E2 : int { e2 = E2() }; @@ -105,23 +109,29 @@ enum struct E4 : int { e = static_cast(E4()) }; namespace dr990 { // dr990: 3.5 #if __cplusplus >= 201103L - struct A { // expected-note 2{{candidate}} - A(std::initializer_list); // expected-note {{candidate}} + struct A { // #dr990-A + A(std::initializer_list); // #dr990-A-init-list }; struct B { A a; }; B b1 { }; - B b2 { 1 }; // expected-error {{no viable conversion from 'int' to 'A'}} + B b2 { 1 }; + // since-cxx11-error@-1 {{no viable conversion from 'int' to 'A'}} + // since-cxx11-note@#dr990-A {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'int' to 'const A &' for 1st argument}} + // since-cxx11-note@#dr990-A {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'int' to 'A &&' for 1st argument}} + // since-cxx11-note@#dr990-A-init-list {{candidate constructor not viable: no known conversion from 'int' to 'std::initializer_list' for 1st argument}} B b3 { { 1 } }; struct C { C(); C(int); - C(std::initializer_list) = delete; // expected-note {{here}} + C(std::initializer_list) = delete; // #dr990-deleted }; C c1[3] { 1 }; // ok - C c2[3] { 1, {2} }; // expected-error {{call to deleted}} + C c2[3] { 1, {2} }; + // since-cxx11-error@-1 {{call to deleted constructor of 'C'}} + // since-cxx11-note@#dr990-deleted {{'C' has been explicitly marked deleted here}} struct D { D(); diff --git a/clang/test/CXX/temp/temp.decls/temp.friend/p1.cpp b/clang/test/CXX/temp/temp.decls/temp.friend/p1.cpp index ab1b9f7a73eec8912173d953fc5756473bc47e8a..1cf9e1c9f9c0fa39caf6c1d326e68519cee41a62 100644 --- a/clang/test/CXX/temp/temp.decls/temp.friend/p1.cpp +++ b/clang/test/CXX/temp/temp.decls/temp.friend/p1.cpp @@ -17,7 +17,7 @@ public: for (U count = n.count_; count; --count) x += a; return x; - } + } }; friend Num operator+(const Num &a, const Num &b) { @@ -145,7 +145,7 @@ namespace test5 { namespace Dependent { template class X; - template + template X operator+(const X&, const T*); template class X { @@ -249,7 +249,7 @@ namespace test11 { }; template struct Foo::IteratorImpl; - template struct Foo::IteratorImpl; + template struct Foo::IteratorImpl; } // PR6827 diff --git a/clang/test/ClangScanDeps/strip-codegen-args.m b/clang/test/ClangScanDeps/strip-codegen-args.m new file mode 100644 index 0000000000000000000000000000000000000000..bb7e76e86aa2f92bef06b44fb07e581b2d6bd3ab --- /dev/null +++ b/clang/test/ClangScanDeps/strip-codegen-args.m @@ -0,0 +1,58 @@ +// RUN: rm -rf %t +// RUN: split-file %s %t +// RUN: sed -e "s|DIR|%/t|g" %t/cdb1.json.template > %t/cdb1.json + +// RUN: clang-scan-deps -compilation-database %t/cdb1.json -format experimental-full > %t/result1.txt +// RUN: FileCheck %s -input-file %t/result1.txt + +// This tests that codegen option that do not affect the AST or generation of a module are removed. + +// CHECK: "modules": [ +// CHECK-NEXT: { +// CHECK: "command-line": [ +// CHECK-NOT: "-flto" +// CHECK-NOT: "-fno-autolink" +// CHECK-NOT: "-mrelax-relocations=no" +// CHECK: ] +// CHECK: "name": "A" +// CHECK: } +// CHECK-NOT: "name": "A" +// CHECK: "translation-units" + +//--- cdb1.json.template +[ + { + "directory": "DIR", + "command": "clang -Imodules/A -fmodules -fmodules-cache-path=DIR/module-cache -fimplicit-modules -flto -fno-autolink -Xclang -mrelax-relocations=no -fsyntax-only DIR/t1.m", + "file": "DIR/t1.m" + }, + { + "directory": "DIR", + "command": "clang -Imodules/A -fmodules -fmodules-cache-path=DIR/module-cache -fimplicit-modules -flto=thin -fautolink -fsyntax-only DIR/t2.m", + "file": "DIR/t2.m" + }, + { + "directory": "DIR", + "command": "clang -Imodules/A -fmodules -fmodules-cache-path=DIR/module-cache -fimplicit-modules -flto=full -fsyntax-only DIR/t3.m", + "file": "DIR/t2.m" + } +] + +//--- modules/A/module.modulemap + +module A { + umbrella header "A.h" +} + +//--- modules/A/A.h + +typedef int A_t; + +//--- t1.m +@import A; + +//--- t2.m +@import A; + +//--- t3.m +@import A; diff --git a/clang/test/CodeGen/RISCV/riscv-func-attr-target.c b/clang/test/CodeGen/RISCV/riscv-func-attr-target.c index 74bc5f2ac70492ed13fe7861a03d01d572f02002..506acaba687417ab475ec748b6bfcdb6764e26a0 100644 --- a/clang/test/CodeGen/RISCV/riscv-func-attr-target.c +++ b/clang/test/CodeGen/RISCV/riscv-func-attr-target.c @@ -1,6 +1,7 @@ // REQUIRES: riscv-registered-target // RUN: %clang_cc1 -triple riscv64 -target-feature +zifencei -target-feature +m \ -// RUN: -target-feature +a -target-feature +save-restore \ +// RUN: -target-feature +a -target-feature +save-restore -target-feature -zbb \ +// RUN: -target-feature -relax -target-feature -zfa \ // RUN: -emit-llvm %s -o - | FileCheck %s // CHECK-LABEL: define dso_local void @testDefault @@ -35,12 +36,12 @@ testAttrFullArchAndAttrCpu() {} __attribute__((target("cpu=sifive-u54"))) void testAttrCpuOnly() {} //. -// CHECK: attributes #0 = { {{.*}}"target-features"="+64bit,+a,+m,+save-restore,+zifencei" } -// CHECK: attributes #1 = { {{.*}}"target-cpu"="rocket-rv64" "target-features"="+64bit,+a,+d,+f,+m,+save-restore,+v,+zicsr,+zifencei,+zve32f,+zve32x,+zve64d,+zve64f,+zve64x,+zvl128b,+zvl32b,+zvl64b" "tune-cpu"="generic-rv64" } -// CHECK: attributes #2 = { {{.*}}"target-features"="+64bit,+a,+m,+save-restore,+zbb,+zifencei" } -// CHECK: attributes #3 = { {{.*}}"target-features"="+64bit,+a,+d,+experimental-zicond,+f,+m,+save-restore,+v,+zbb,+zicsr,+zifencei,+zve32f,+zve32x,+zve64d,+zve64f,+zve64x,+zvl128b,+zvl32b,+zvl64b" } -// CHECK: attributes #4 = { {{.*}}"target-features"="+64bit,+a,+c,+d,+f,+m,+save-restore,+zbb,+zicsr,+zifencei" } -// CHECK: attributes #5 = { {{.*}}"target-features"="+64bit,+m,+save-restore" } -// CHECK: attributes #6 = { {{.*}}"target-cpu"="sifive-u54" "target-features"="+64bit,+a,+m,+save-restore,+zbb,+zifencei" } -// CHECK: attributes #7 = { {{.*}}"target-cpu"="sifive-u54" "target-features"="+64bit,+m,+save-restore" } -// CHECK: attributes #8 = { {{.*}}"target-cpu"="sifive-u54" "target-features"="+64bit,+a,+c,+d,+f,+m,+save-restore,+zicsr,+zifencei" } +// CHECK: attributes #0 = { {{.*}}"target-features"="+64bit,+a,+m,+save-restore,+zifencei,-relax,-zbb,-zfa" } +// CHECK: attributes #1 = { {{.*}}"target-cpu"="rocket-rv64" "target-features"="+64bit,+a,+d,+f,+m,+save-restore,+v,+zicsr,+zifencei,+zve32f,+zve32x,+zve64d,+zve64f,+zve64x,+zvl128b,+zvl32b,+zvl64b,-relax,-zbb,-zfa" "tune-cpu"="generic-rv64" } +// CHECK: attributes #2 = { {{.*}}"target-features"="+64bit,+a,+m,+save-restore,+zbb,+zifencei,-relax,-zfa" } +// CHECK: attributes #3 = { {{.*}}"target-features"="+64bit,+a,+d,+experimental-zicond,+f,+m,+save-restore,+v,+zbb,+zicsr,+zifencei,+zve32f,+zve32x,+zve64d,+zve64f,+zve64x,+zvl128b,+zvl32b,+zvl64b,-relax,-zfa" } +// CHECK: attributes #4 = { {{.*}}"target-features"="+64bit,+a,+c,+d,+f,+m,+save-restore,+zbb,+zicsr,+zifencei,-relax,-zfa" } +// CHECK: attributes #5 = { {{.*}}"target-features"="+64bit,+m,+save-restore,-relax,-zbb,-zfa" } +// CHECK: attributes #6 = { {{.*}}"target-cpu"="sifive-u54" "target-features"="+64bit,+a,+m,+save-restore,+zbb,+zifencei,-relax,-zfa" } +// CHECK: attributes #7 = { {{.*}}"target-cpu"="sifive-u54" "target-features"="+64bit,+m,+save-restore,-relax,-zbb,-zfa" } +// CHECK: attributes #8 = { {{.*}}"target-cpu"="sifive-u54" "target-features"="+64bit,+a,+c,+d,+f,+m,+save-restore,+zicsr,+zifencei,-relax,-zbb,-zfa" } diff --git a/clang/test/CodeGen/RISCV/rvv-intrinsics-handcrafted/rvv-error.c b/clang/test/CodeGen/RISCV/rvv-intrinsics-handcrafted/rvv-error.c index 1a29acbf3ba92d027e40c43f8c14b6d5618126da..6ec9b057997690a919a39da38a85e31372af0ffe 100644 --- a/clang/test/CodeGen/RISCV/rvv-intrinsics-handcrafted/rvv-error.c +++ b/clang/test/CodeGen/RISCV/rvv-intrinsics-handcrafted/rvv-error.c @@ -11,7 +11,7 @@ // CHECK-RV64V-NEXT: ret i32 [[CONV]] // -// CHECK-RV64-ERR: error: builtin requires at least one of the following extensions to be enabled: 'Zve32x' +// CHECK-RV64-ERR: error: builtin requires at least one of the following extensions: 'Zve32x' int test() { return __builtin_rvv_vsetvli(1, 0, 0); diff --git a/clang/test/CodeGen/SystemZ/atomic_is_lock_free.c b/clang/test/CodeGen/SystemZ/atomic_is_lock_free.c new file mode 100644 index 0000000000000000000000000000000000000000..32c436eaf36ddad617b8ccbeb42ca6b522940be2 --- /dev/null +++ b/clang/test/CodeGen/SystemZ/atomic_is_lock_free.c @@ -0,0 +1,98 @@ +// RUN: %clang_cc1 -triple s390x-linux-gnu -O1 -emit-llvm %s -o - | FileCheck %s +// +// Test __atomic_is_lock_free() and friends. + +#include +#include + +typedef __attribute__((aligned(16))) __int128 __int128_Al16; + +_Atomic __int128 Int128_Atomic; +__int128_Al16 Int128_Al16; +__int128 Int128; +struct { int I[3]; } _Atomic AtomicStruct; +_Atomic long double Atomic_fp128; // Also check the alignment of this. + +// Check alignments of the variables. @AtomicStruct gets padded and its size +// and alignment becomes 16. Only a power-of-2 size is considered, so 16 (not +// 12) needs to be specified with the intrinsics below. +// +// CHECK: %struct.anon = type { [3 x i32] } +// CHECK: @Int128 = {{.*}} i128 0, align 8 +// CHECK: @Int128_Atomic = {{.*}} i128 0, align 16 +// CHECK: @Int128_Al16 = {{.*}} i128 0, align 16 +// CHECK: @AtomicStruct = {{.*}} { %struct.anon, [4 x i8] } zeroinitializer, align 16 +// CHECK: @Atomic_fp128 = {{.*}} fp128 0xL00000000000000000000000000000000, align 16 + + +// CHECK-LABEL: @fun0 +// CHECK: ret i1 true +_Bool fun0() { + return __atomic_is_lock_free(16, &Int128_Atomic); +} + +// CHECK-LABEL: @fun1 +// CHECK: ret i1 true +_Bool fun1() { + return __atomic_always_lock_free(16, &Int128_Atomic); +} + +// CHECK-LABEL: @fun2 +// CHECK: ret i1 true +_Bool fun2() { + return __atomic_is_lock_free(16, &Int128_Al16); +} + +// CHECK-LABEL: @fun3 +// CHECK: ret i1 true +_Bool fun3() { + return __atomic_always_lock_free(16, &Int128_Al16); +} + +// CHECK-LABEL: @fun4 +// CHECK: call zeroext i1 @__atomic_is_lock_free +_Bool fun4() { + return __atomic_is_lock_free(16, &Int128); +} + +// CHECK-LABEL: @fun5 +// CHECK: ret i1 false +_Bool fun5() { + return __atomic_always_lock_free(16, &Int128); +} + +// CHECK-LABEL: @fun6 +// CHECK: ret i1 true +_Bool fun6() { + return __atomic_is_lock_free(16, 0); +} + +// CHECK-LABEL: @fun7 +// CHECK: ret i1 true +_Bool fun7() { + return __atomic_always_lock_free(16, 0); +} + +// CHECK-LABEL: @fun8 +// CHECK: ret i1 true +_Bool fun8() { + return __atomic_is_lock_free(16, &AtomicStruct); +} + +// CHECK-LABEL: @fun9 +// CHECK: ret i1 true +_Bool fun9() { + return __atomic_always_lock_free(16, &AtomicStruct); +} + +// CHECK-LABEL: @fun10 +// CHECK: ret i1 true +_Bool fun10() { + return atomic_is_lock_free(&Int128_Atomic); +} + +// CHECK-LABEL: @fun11 +// CHECK: ret i1 true +_Bool fun11() { + return __c11_atomic_is_lock_free(16); +} diff --git a/clang/test/CodeGen/SystemZ/gnu-atomic-builtins-i128-16Al.c b/clang/test/CodeGen/SystemZ/gnu-atomic-builtins-i128-16Al.c new file mode 100644 index 0000000000000000000000000000000000000000..e3db2063312d2b4ee320e48f8a32dfe061d92403 --- /dev/null +++ b/clang/test/CodeGen/SystemZ/gnu-atomic-builtins-i128-16Al.c @@ -0,0 +1,257 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// RUN: %clang_cc1 -triple s390x-linux-gnu -O1 -emit-llvm %s -o - | FileCheck %s +// +// Test GNU atomic builtins for __int128 aligned to 16 bytes, which should be +// expanded to LLVM I/R by the front end. + +#include +#include + +__int128 Ptr __attribute__((aligned(16))); +__int128 Ret __attribute__((aligned(16))); +__int128 Val __attribute__((aligned(16))); +__int128 Exp __attribute__((aligned(16))); +__int128 Des __attribute__((aligned(16))); + +// CHECK-LABEL: @f1( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = load atomic i128, ptr @Ptr seq_cst, align 16 +// CHECK-NEXT: store i128 [[TMP0]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2:![0-9]+]] +// CHECK-NEXT: ret void +// +__int128 f1() { + return __atomic_load_n(&Ptr, memory_order_seq_cst); +} + +// CHECK-LABEL: @f2( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = load atomic i128, ptr @Ptr seq_cst, align 16 +// CHECK-NEXT: store i128 [[TMP0]], ptr @Ret, align 16 +// CHECK-NEXT: store i128 [[TMP0]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: ret void +// +__int128 f2() { + __atomic_load(&Ptr, &Ret, memory_order_seq_cst); + return Ret; +} + +// CHECK-LABEL: @f3( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 16, !tbaa [[TBAA2]] +// CHECK-NEXT: store atomic i128 [[TMP0]], ptr @Ptr seq_cst, align 16 +// CHECK-NEXT: ret void +// +void f3() { + __atomic_store_n(&Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f4( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 16 +// CHECK-NEXT: store atomic i128 [[TMP0]], ptr @Ptr seq_cst, align 16 +// CHECK-NEXT: ret void +// +void f4() { + __atomic_store(&Ptr, &Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f5( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 16, !tbaa [[TBAA2]] +// CHECK-NEXT: [[TMP1:%.*]] = atomicrmw xchg ptr @Ptr, i128 [[TMP0]] seq_cst, align 16 +// CHECK-NEXT: store i128 [[TMP1]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: ret void +// +__int128 f5() { + return __atomic_exchange_n(&Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f6( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 16 +// CHECK-NEXT: [[TMP1:%.*]] = atomicrmw xchg ptr @Ptr, i128 [[TMP0]] seq_cst, align 16 +// CHECK-NEXT: store i128 [[TMP1]], ptr @Ret, align 16 +// CHECK-NEXT: store i128 [[TMP1]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: ret void +// +__int128 f6() { + __atomic_exchange(&Ptr, &Val, &Ret, memory_order_seq_cst); + return Ret; +} + +// CHECK-LABEL: @f7( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Des, align 16, !tbaa [[TBAA2]] +// CHECK-NEXT: [[TMP1:%.*]] = load i128, ptr @Exp, align 16 +// CHECK-NEXT: [[TMP2:%.*]] = cmpxchg ptr @Ptr, i128 [[TMP1]], i128 [[TMP0]] seq_cst seq_cst, align 16 +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i128, i1 } [[TMP2]], 1 +// CHECK-NEXT: br i1 [[TMP3]], label [[CMPXCHG_CONTINUE:%.*]], label [[CMPXCHG_STORE_EXPECTED:%.*]] +// CHECK: cmpxchg.store_expected: +// CHECK-NEXT: [[TMP4:%.*]] = extractvalue { i128, i1 } [[TMP2]], 0 +// CHECK-NEXT: store i128 [[TMP4]], ptr @Exp, align 16 +// CHECK-NEXT: br label [[CMPXCHG_CONTINUE]] +// CHECK: cmpxchg.continue: +// CHECK-NEXT: ret i1 [[TMP3]] +// +_Bool f7() { + return __atomic_compare_exchange_n(&Ptr, &Exp, Des, 0, + memory_order_seq_cst, memory_order_seq_cst); +} + +// CHECK-LABEL: @f8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Exp, align 16 +// CHECK-NEXT: [[TMP1:%.*]] = load i128, ptr @Des, align 16 +// CHECK-NEXT: [[TMP2:%.*]] = cmpxchg ptr @Ptr, i128 [[TMP0]], i128 [[TMP1]] seq_cst seq_cst, align 16 +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i128, i1 } [[TMP2]], 1 +// CHECK-NEXT: br i1 [[TMP3]], label [[CMPXCHG_CONTINUE:%.*]], label [[CMPXCHG_STORE_EXPECTED:%.*]] +// CHECK: cmpxchg.store_expected: +// CHECK-NEXT: [[TMP4:%.*]] = extractvalue { i128, i1 } [[TMP2]], 0 +// CHECK-NEXT: store i128 [[TMP4]], ptr @Exp, align 16 +// CHECK-NEXT: br label [[CMPXCHG_CONTINUE]] +// CHECK: cmpxchg.continue: +// CHECK-NEXT: ret i1 [[TMP3]] +// +_Bool f8() { + return __atomic_compare_exchange(&Ptr, &Exp, &Des, 0, + memory_order_seq_cst, memory_order_seq_cst); +} + +// CHECK-LABEL: @f9( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 16, !tbaa [[TBAA2]] +// CHECK-NEXT: [[TMP1:%.*]] = atomicrmw add ptr @Ptr, i128 [[TMP0]] seq_cst, align 16 +// CHECK-NEXT: [[TMP2:%.*]] = add i128 [[TMP1]], [[TMP0]] +// CHECK-NEXT: store i128 [[TMP2]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: ret void +// +__int128 f9() { + return __atomic_add_fetch(&Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f10( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 16, !tbaa [[TBAA2]] +// CHECK-NEXT: [[TMP1:%.*]] = atomicrmw sub ptr @Ptr, i128 [[TMP0]] seq_cst, align 16 +// CHECK-NEXT: [[TMP2:%.*]] = sub i128 [[TMP1]], [[TMP0]] +// CHECK-NEXT: store i128 [[TMP2]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: ret void +// +__int128 f10() { + return __atomic_sub_fetch(&Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f11( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 16, !tbaa [[TBAA2]] +// CHECK-NEXT: [[TMP1:%.*]] = atomicrmw and ptr @Ptr, i128 [[TMP0]] seq_cst, align 16 +// CHECK-NEXT: [[TMP2:%.*]] = and i128 [[TMP1]], [[TMP0]] +// CHECK-NEXT: store i128 [[TMP2]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: ret void +// +__int128 f11() { + return __atomic_and_fetch(&Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f12( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 16, !tbaa [[TBAA2]] +// CHECK-NEXT: [[TMP1:%.*]] = atomicrmw xor ptr @Ptr, i128 [[TMP0]] seq_cst, align 16 +// CHECK-NEXT: [[TMP2:%.*]] = xor i128 [[TMP1]], [[TMP0]] +// CHECK-NEXT: store i128 [[TMP2]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: ret void +// +__int128 f12() { + return __atomic_xor_fetch(&Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f13( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 16, !tbaa [[TBAA2]] +// CHECK-NEXT: [[TMP1:%.*]] = atomicrmw or ptr @Ptr, i128 [[TMP0]] seq_cst, align 16 +// CHECK-NEXT: [[TMP2:%.*]] = or i128 [[TMP1]], [[TMP0]] +// CHECK-NEXT: store i128 [[TMP2]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: ret void +// +__int128 f13() { + return __atomic_or_fetch(&Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f14( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 16, !tbaa [[TBAA2]] +// CHECK-NEXT: [[TMP1:%.*]] = atomicrmw nand ptr @Ptr, i128 [[TMP0]] seq_cst, align 16 +// CHECK-NEXT: [[TMP2:%.*]] = and i128 [[TMP1]], [[TMP0]] +// CHECK-NEXT: [[TMP3:%.*]] = xor i128 [[TMP2]], -1 +// CHECK-NEXT: store i128 [[TMP3]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: ret void +// +__int128 f14() { + return __atomic_nand_fetch(&Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f15( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 16, !tbaa [[TBAA2]] +// CHECK-NEXT: [[TMP1:%.*]] = atomicrmw add ptr @Ptr, i128 [[TMP0]] seq_cst, align 16 +// CHECK-NEXT: store i128 [[TMP1]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: ret void +// +__int128 f15() { + return __atomic_fetch_add(&Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 16, !tbaa [[TBAA2]] +// CHECK-NEXT: [[TMP1:%.*]] = atomicrmw sub ptr @Ptr, i128 [[TMP0]] seq_cst, align 16 +// CHECK-NEXT: store i128 [[TMP1]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: ret void +// +__int128 f16() { + return __atomic_fetch_sub(&Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f17( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 16, !tbaa [[TBAA2]] +// CHECK-NEXT: [[TMP1:%.*]] = atomicrmw and ptr @Ptr, i128 [[TMP0]] seq_cst, align 16 +// CHECK-NEXT: store i128 [[TMP1]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: ret void +// +__int128 f17() { + return __atomic_fetch_and(&Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f18( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 16, !tbaa [[TBAA2]] +// CHECK-NEXT: [[TMP1:%.*]] = atomicrmw xor ptr @Ptr, i128 [[TMP0]] seq_cst, align 16 +// CHECK-NEXT: store i128 [[TMP1]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: ret void +// +__int128 f18() { + return __atomic_fetch_xor(&Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f19( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 16, !tbaa [[TBAA2]] +// CHECK-NEXT: [[TMP1:%.*]] = atomicrmw or ptr @Ptr, i128 [[TMP0]] seq_cst, align 16 +// CHECK-NEXT: store i128 [[TMP1]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: ret void +// +__int128 f19() { + return __atomic_fetch_or(&Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f20( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 16, !tbaa [[TBAA2]] +// CHECK-NEXT: [[TMP1:%.*]] = atomicrmw nand ptr @Ptr, i128 [[TMP0]] seq_cst, align 16 +// CHECK-NEXT: store i128 [[TMP1]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: ret void +// +__int128 f20() { + return __atomic_fetch_nand(&Ptr, Val, memory_order_seq_cst); +} diff --git a/clang/test/CodeGen/SystemZ/gnu-atomic-builtins-i128-8Al.c b/clang/test/CodeGen/SystemZ/gnu-atomic-builtins-i128-8Al.c new file mode 100644 index 0000000000000000000000000000000000000000..e38e6572bd58f4e460d2fa92940c390464c51b13 --- /dev/null +++ b/clang/test/CodeGen/SystemZ/gnu-atomic-builtins-i128-8Al.c @@ -0,0 +1,301 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// RUN: %clang_cc1 -triple s390x-linux-gnu -O1 -emit-llvm %s -o - | FileCheck %s +// +// Test GNU atomic builtins for __int128 (with default alignment of 8 bytes +// only), resulting in libcalls. + +#include +#include + +__int128 Ptr; +__int128 Ret; +__int128 Val; +__int128 Exp; +__int128 Des; + +// TODO: This test and several more below have the unnecessary use of an alloca +// remaining. This is due to 369c9b7, which changes the behavior of the MemCpyOpt +// pass. It seems that a 'writable' attribute should now be added to the argument +// in order for this optimization to proceed. + +// CHECK-LABEL: @f1( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[ATOMIC_TEMP:%.*]] = alloca i128, align 8 +// CHECK-NEXT: call void @__atomic_load(i64 noundef 16, ptr noundef nonnull @Ptr, ptr noundef nonnull [[ATOMIC_TEMP]], i32 noundef signext 5) +// CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr [[ATOMIC_TEMP]], align 8, !tbaa [[TBAA2:![0-9]+]] +// CHECK-NEXT: store i128 [[TMP0]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: ret void +// +__int128 f1() { + return __atomic_load_n(&Ptr, memory_order_seq_cst); +} + +// CHECK-LABEL: @f2( +// CHECK-NEXT: entry: +// CHECK-NEXT: tail call void @__atomic_load(i64 noundef 16, ptr noundef nonnull @Ptr, ptr noundef nonnull @Ret, i32 noundef signext 5) +// CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Ret, align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: store i128 [[TMP0]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: ret void +// +__int128 f2() { + __atomic_load(&Ptr, &Ret, memory_order_seq_cst); + return Ret; +} + +// CHECK-LABEL: @f3( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTATOMICTMP:%.*]] = alloca i128, align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: store i128 [[TMP0]], ptr [[DOTATOMICTMP]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: call void @__atomic_store(i64 noundef 16, ptr noundef nonnull @Ptr, ptr noundef nonnull [[DOTATOMICTMP]], i32 noundef signext 5) +// CHECK-NEXT: ret void +// +void f3() { + __atomic_store_n(&Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f4( +// CHECK-NEXT: entry: +// CHECK-NEXT: tail call void @__atomic_store(i64 noundef 16, ptr noundef nonnull @Ptr, ptr noundef nonnull @Val, i32 noundef signext 5) +// CHECK-NEXT: ret void +// +void f4() { + __atomic_store(&Ptr, &Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f5( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTATOMICTMP:%.*]] = alloca i128, align 8 +// CHECK-NEXT: [[ATOMIC_TEMP:%.*]] = alloca i128, align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: store i128 [[TMP0]], ptr [[DOTATOMICTMP]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: call void @__atomic_exchange(i64 noundef 16, ptr noundef nonnull @Ptr, ptr noundef nonnull [[DOTATOMICTMP]], ptr noundef nonnull [[ATOMIC_TEMP]], i32 noundef signext 5) +// CHECK-NEXT: [[TMP1:%.*]] = load i128, ptr [[ATOMIC_TEMP]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: store i128 [[TMP1]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: ret void +// +__int128 f5() { + return __atomic_exchange_n(&Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f6( +// CHECK-NEXT: entry: +// CHECK-NEXT: tail call void @__atomic_exchange(i64 noundef 16, ptr noundef nonnull @Ptr, ptr noundef nonnull @Val, ptr noundef nonnull @Ret, i32 noundef signext 5) +// CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Ret, align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: store i128 [[TMP0]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: ret void +// +__int128 f6() { + __atomic_exchange(&Ptr, &Val, &Ret, memory_order_seq_cst); + return Ret; +} + +// CHECK-LABEL: @f7( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTATOMICTMP:%.*]] = alloca i128, align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Des, align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: store i128 [[TMP0]], ptr [[DOTATOMICTMP]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: [[CALL:%.*]] = call zeroext i1 @__atomic_compare_exchange(i64 noundef 16, ptr noundef nonnull @Ptr, ptr noundef nonnull @Exp, ptr noundef nonnull [[DOTATOMICTMP]], i32 noundef signext 5, i32 noundef signext 5) +// CHECK-NEXT: ret i1 [[CALL]] +// +_Bool f7() { + return __atomic_compare_exchange_n(&Ptr, &Exp, Des, 0, + memory_order_seq_cst, memory_order_seq_cst); +} + +// CHECK-LABEL: @f8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[CALL:%.*]] = tail call zeroext i1 @__atomic_compare_exchange(i64 noundef 16, ptr noundef nonnull @Ptr, ptr noundef nonnull @Exp, ptr noundef nonnull @Des, i32 noundef signext 5, i32 noundef signext 5) +// CHECK-NEXT: ret i1 [[CALL]] +// +_Bool f8() { + return __atomic_compare_exchange(&Ptr, &Exp, &Des, 0, + memory_order_seq_cst, memory_order_seq_cst); +} + +// CHECK-LABEL: @f9( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP:%.*]] = alloca i128, align 8 +// CHECK-NEXT: [[INDIRECT_ARG_TEMP:%.*]] = alloca i128, align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: store i128 [[TMP0]], ptr [[INDIRECT_ARG_TEMP]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: call void @__atomic_fetch_add_16(ptr nonnull sret(i128) align 8 [[TMP]], ptr noundef nonnull @Ptr, ptr noundef nonnull [[INDIRECT_ARG_TEMP]], i32 noundef signext 5) +// CHECK-NEXT: [[TMP1:%.*]] = load i128, ptr [[TMP]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: [[TMP2:%.*]] = add i128 [[TMP1]], [[TMP0]] +// CHECK-NEXT: store i128 [[TMP2]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: ret void +// +__int128 f9() { + return __atomic_add_fetch(&Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f10( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP:%.*]] = alloca i128, align 8 +// CHECK-NEXT: [[INDIRECT_ARG_TEMP:%.*]] = alloca i128, align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: store i128 [[TMP0]], ptr [[INDIRECT_ARG_TEMP]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: call void @__atomic_fetch_sub_16(ptr nonnull sret(i128) align 8 [[TMP]], ptr noundef nonnull @Ptr, ptr noundef nonnull [[INDIRECT_ARG_TEMP]], i32 noundef signext 5) +// CHECK-NEXT: [[TMP1:%.*]] = load i128, ptr [[TMP]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: [[TMP2:%.*]] = sub i128 [[TMP1]], [[TMP0]] +// CHECK-NEXT: store i128 [[TMP2]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: ret void +// +__int128 f10() { + return __atomic_sub_fetch(&Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f11( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP:%.*]] = alloca i128, align 8 +// CHECK-NEXT: [[INDIRECT_ARG_TEMP:%.*]] = alloca i128, align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: store i128 [[TMP0]], ptr [[INDIRECT_ARG_TEMP]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: call void @__atomic_fetch_and_16(ptr nonnull sret(i128) align 8 [[TMP]], ptr noundef nonnull @Ptr, ptr noundef nonnull [[INDIRECT_ARG_TEMP]], i32 noundef signext 5) +// CHECK-NEXT: [[TMP1:%.*]] = load i128, ptr [[TMP]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: [[TMP2:%.*]] = and i128 [[TMP1]], [[TMP0]] +// CHECK-NEXT: store i128 [[TMP2]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: ret void +// +__int128 f11() { + return __atomic_and_fetch(&Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f12( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP:%.*]] = alloca i128, align 8 +// CHECK-NEXT: [[INDIRECT_ARG_TEMP:%.*]] = alloca i128, align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: store i128 [[TMP0]], ptr [[INDIRECT_ARG_TEMP]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: call void @__atomic_fetch_xor_16(ptr nonnull sret(i128) align 8 [[TMP]], ptr noundef nonnull @Ptr, ptr noundef nonnull [[INDIRECT_ARG_TEMP]], i32 noundef signext 5) +// CHECK-NEXT: [[TMP1:%.*]] = load i128, ptr [[TMP]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: [[TMP2:%.*]] = xor i128 [[TMP1]], [[TMP0]] +// CHECK-NEXT: store i128 [[TMP2]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: ret void +// +__int128 f12() { + return __atomic_xor_fetch(&Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f13( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP:%.*]] = alloca i128, align 8 +// CHECK-NEXT: [[INDIRECT_ARG_TEMP:%.*]] = alloca i128, align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: store i128 [[TMP0]], ptr [[INDIRECT_ARG_TEMP]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: call void @__atomic_fetch_or_16(ptr nonnull sret(i128) align 8 [[TMP]], ptr noundef nonnull @Ptr, ptr noundef nonnull [[INDIRECT_ARG_TEMP]], i32 noundef signext 5) +// CHECK-NEXT: [[TMP1:%.*]] = load i128, ptr [[TMP]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: [[TMP2:%.*]] = or i128 [[TMP1]], [[TMP0]] +// CHECK-NEXT: store i128 [[TMP2]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: ret void +// +__int128 f13() { + return __atomic_or_fetch(&Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f14( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP:%.*]] = alloca i128, align 8 +// CHECK-NEXT: [[INDIRECT_ARG_TEMP:%.*]] = alloca i128, align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: store i128 [[TMP0]], ptr [[INDIRECT_ARG_TEMP]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: call void @__atomic_fetch_nand_16(ptr nonnull sret(i128) align 8 [[TMP]], ptr noundef nonnull @Ptr, ptr noundef nonnull [[INDIRECT_ARG_TEMP]], i32 noundef signext 5) +// CHECK-NEXT: [[TMP1:%.*]] = load i128, ptr [[TMP]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: [[TMP2:%.*]] = and i128 [[TMP1]], [[TMP0]] +// CHECK-NEXT: [[TMP3:%.*]] = xor i128 [[TMP2]], -1 +// CHECK-NEXT: store i128 [[TMP3]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: ret void +// +__int128 f14() { + return __atomic_nand_fetch(&Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f15( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP:%.*]] = alloca i128, align 8 +// CHECK-NEXT: [[INDIRECT_ARG_TEMP:%.*]] = alloca i128, align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: store i128 [[TMP0]], ptr [[INDIRECT_ARG_TEMP]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: call void @__atomic_fetch_add_16(ptr nonnull sret(i128) align 8 [[TMP]], ptr noundef nonnull @Ptr, ptr noundef nonnull [[INDIRECT_ARG_TEMP]], i32 noundef signext 5) +// CHECK-NEXT: [[TMP1:%.*]] = load i128, ptr [[TMP]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: store i128 [[TMP1]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: ret void +// +__int128 f15() { + return __atomic_fetch_add(&Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP:%.*]] = alloca i128, align 8 +// CHECK-NEXT: [[INDIRECT_ARG_TEMP:%.*]] = alloca i128, align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: store i128 [[TMP0]], ptr [[INDIRECT_ARG_TEMP]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: call void @__atomic_fetch_sub_16(ptr nonnull sret(i128) align 8 [[TMP]], ptr noundef nonnull @Ptr, ptr noundef nonnull [[INDIRECT_ARG_TEMP]], i32 noundef signext 5) +// CHECK-NEXT: [[TMP1:%.*]] = load i128, ptr [[TMP]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: store i128 [[TMP1]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: ret void +// +__int128 f16() { + return __atomic_fetch_sub(&Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f17( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP:%.*]] = alloca i128, align 8 +// CHECK-NEXT: [[INDIRECT_ARG_TEMP:%.*]] = alloca i128, align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: store i128 [[TMP0]], ptr [[INDIRECT_ARG_TEMP]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: call void @__atomic_fetch_and_16(ptr nonnull sret(i128) align 8 [[TMP]], ptr noundef nonnull @Ptr, ptr noundef nonnull [[INDIRECT_ARG_TEMP]], i32 noundef signext 5) +// CHECK-NEXT: [[TMP1:%.*]] = load i128, ptr [[TMP]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: store i128 [[TMP1]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: ret void +// +__int128 f17() { + return __atomic_fetch_and(&Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f18( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP:%.*]] = alloca i128, align 8 +// CHECK-NEXT: [[INDIRECT_ARG_TEMP:%.*]] = alloca i128, align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: store i128 [[TMP0]], ptr [[INDIRECT_ARG_TEMP]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: call void @__atomic_fetch_xor_16(ptr nonnull sret(i128) align 8 [[TMP]], ptr noundef nonnull @Ptr, ptr noundef nonnull [[INDIRECT_ARG_TEMP]], i32 noundef signext 5) +// CHECK-NEXT: [[TMP1:%.*]] = load i128, ptr [[TMP]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: store i128 [[TMP1]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: ret void +// +__int128 f18() { + return __atomic_fetch_xor(&Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f19( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP:%.*]] = alloca i128, align 8 +// CHECK-NEXT: [[INDIRECT_ARG_TEMP:%.*]] = alloca i128, align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: store i128 [[TMP0]], ptr [[INDIRECT_ARG_TEMP]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: call void @__atomic_fetch_or_16(ptr nonnull sret(i128) align 8 [[TMP]], ptr noundef nonnull @Ptr, ptr noundef nonnull [[INDIRECT_ARG_TEMP]], i32 noundef signext 5) +// CHECK-NEXT: [[TMP1:%.*]] = load i128, ptr [[TMP]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: store i128 [[TMP1]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: ret void +// +__int128 f19() { + return __atomic_fetch_or(&Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f20( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP:%.*]] = alloca i128, align 8 +// CHECK-NEXT: [[INDIRECT_ARG_TEMP:%.*]] = alloca i128, align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: store i128 [[TMP0]], ptr [[INDIRECT_ARG_TEMP]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: call void @__atomic_fetch_nand_16(ptr nonnull sret(i128) align 8 [[TMP]], ptr noundef nonnull @Ptr, ptr noundef nonnull [[INDIRECT_ARG_TEMP]], i32 noundef signext 5) +// CHECK-NEXT: [[TMP1:%.*]] = load i128, ptr [[TMP]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: store i128 [[TMP1]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: ret void +// +__int128 f20() { + return __atomic_fetch_nand(&Ptr, Val, memory_order_seq_cst); +} diff --git a/clang/test/CodeGen/SystemZ/gnu-atomic-builtins-i16.c b/clang/test/CodeGen/SystemZ/gnu-atomic-builtins-i16.c new file mode 100644 index 0000000000000000000000000000000000000000..7c6a82f14197a15275307e7f830d40ca7632b7f3 --- /dev/null +++ b/clang/test/CodeGen/SystemZ/gnu-atomic-builtins-i16.c @@ -0,0 +1,219 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// RUN: %clang_cc1 -triple s390x-linux-gnu -O1 -emit-llvm %s -o - | FileCheck %s +// +// Test GNU atomic builtins for int16_t. + +#include +#include + +// CHECK-LABEL: @f1( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = load atomic i16, ptr [[PTR:%.*]] seq_cst, align 2 +// CHECK-NEXT: ret i16 [[TMP0]] +// +int16_t f1(int16_t *Ptr) { + return __atomic_load_n(Ptr, memory_order_seq_cst); +} + +// CHECK-LABEL: @f2( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = load atomic i16, ptr [[PTR:%.*]] seq_cst, align 2 +// CHECK-NEXT: store i16 [[TMP0]], ptr [[RET:%.*]], align 2 +// CHECK-NEXT: ret i16 [[TMP0]] +// +int16_t f2(int16_t *Ptr, int16_t *Ret) { + __atomic_load(Ptr, Ret, memory_order_seq_cst); + return *Ret; +} + +// CHECK-LABEL: @f3( +// CHECK-NEXT: entry: +// CHECK-NEXT: store atomic i16 [[VAL:%.*]], ptr [[PTR:%.*]] seq_cst, align 2 +// CHECK-NEXT: ret void +// +void f3(int16_t *Ptr, int16_t Val) { + __atomic_store_n(Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f4( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = load i16, ptr [[VAL:%.*]], align 2 +// CHECK-NEXT: store atomic i16 [[TMP0]], ptr [[PTR:%.*]] seq_cst, align 2 +// CHECK-NEXT: ret void +// +void f4(int16_t *Ptr, int16_t *Val) { + __atomic_store(Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f5( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = atomicrmw xchg ptr [[PTR:%.*]], i16 [[VAL:%.*]] seq_cst, align 2 +// CHECK-NEXT: ret i16 [[TMP0]] +// +int16_t f5(int16_t *Ptr, int16_t Val) { + return __atomic_exchange_n(Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f6( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = load i16, ptr [[VAL:%.*]], align 2 +// CHECK-NEXT: [[TMP1:%.*]] = atomicrmw xchg ptr [[PTR:%.*]], i16 [[TMP0]] seq_cst, align 2 +// CHECK-NEXT: store i16 [[TMP1]], ptr [[RET:%.*]], align 2 +// CHECK-NEXT: ret i16 [[TMP1]] +// +int16_t f6(int16_t *Ptr, int16_t *Val, int16_t *Ret) { + __atomic_exchange(Ptr, Val, Ret, memory_order_seq_cst); + return *Ret; +} + +// CHECK-LABEL: @f7( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = load i16, ptr [[EXP:%.*]], align 2 +// CHECK-NEXT: [[TMP1:%.*]] = cmpxchg ptr [[PTR:%.*]], i16 [[TMP0]], i16 [[DES:%.*]] seq_cst seq_cst, align 2 +// CHECK-NEXT: [[TMP2:%.*]] = extractvalue { i16, i1 } [[TMP1]], 1 +// CHECK-NEXT: br i1 [[TMP2]], label [[CMPXCHG_CONTINUE:%.*]], label [[CMPXCHG_STORE_EXPECTED:%.*]] +// CHECK: cmpxchg.store_expected: +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i16, i1 } [[TMP1]], 0 +// CHECK-NEXT: store i16 [[TMP3]], ptr [[EXP]], align 2 +// CHECK-NEXT: br label [[CMPXCHG_CONTINUE]] +// CHECK: cmpxchg.continue: +// CHECK-NEXT: ret i1 [[TMP2]] +// +_Bool f7(int16_t *Ptr, int16_t *Exp, int16_t Des) { + return __atomic_compare_exchange_n(Ptr, Exp, Des, 0, + memory_order_seq_cst, memory_order_seq_cst); +} + +// CHECK-LABEL: @f8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = load i16, ptr [[EXP:%.*]], align 2 +// CHECK-NEXT: [[TMP1:%.*]] = load i16, ptr [[DES:%.*]], align 2 +// CHECK-NEXT: [[TMP2:%.*]] = cmpxchg ptr [[PTR:%.*]], i16 [[TMP0]], i16 [[TMP1]] seq_cst seq_cst, align 2 +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i16, i1 } [[TMP2]], 1 +// CHECK-NEXT: br i1 [[TMP3]], label [[CMPXCHG_CONTINUE:%.*]], label [[CMPXCHG_STORE_EXPECTED:%.*]] +// CHECK: cmpxchg.store_expected: +// CHECK-NEXT: [[TMP4:%.*]] = extractvalue { i16, i1 } [[TMP2]], 0 +// CHECK-NEXT: store i16 [[TMP4]], ptr [[EXP]], align 2 +// CHECK-NEXT: br label [[CMPXCHG_CONTINUE]] +// CHECK: cmpxchg.continue: +// CHECK-NEXT: ret i1 [[TMP3]] +// +_Bool f8(int16_t *Ptr, int16_t *Exp, int16_t *Des) { + return __atomic_compare_exchange(Ptr, Exp, Des, 0, + memory_order_seq_cst, memory_order_seq_cst); +} + +// CHECK-LABEL: @f9( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = atomicrmw add ptr [[PTR:%.*]], i16 [[VAL:%.*]] seq_cst, align 2 +// CHECK-NEXT: [[TMP1:%.*]] = add i16 [[TMP0]], [[VAL]] +// CHECK-NEXT: ret i16 [[TMP1]] +// +int16_t f9(int16_t *Ptr, int16_t Val) { + return __atomic_add_fetch(Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f10( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = atomicrmw sub ptr [[PTR:%.*]], i16 [[VAL:%.*]] seq_cst, align 2 +// CHECK-NEXT: [[TMP1:%.*]] = sub i16 [[TMP0]], [[VAL]] +// CHECK-NEXT: ret i16 [[TMP1]] +// +int16_t f10(int16_t *Ptr, int16_t Val) { + return __atomic_sub_fetch(Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f11( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = atomicrmw and ptr [[PTR:%.*]], i16 [[VAL:%.*]] seq_cst, align 2 +// CHECK-NEXT: [[TMP1:%.*]] = and i16 [[TMP0]], [[VAL]] +// CHECK-NEXT: ret i16 [[TMP1]] +// +int16_t f11(int16_t *Ptr, int16_t Val) { + return __atomic_and_fetch(Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f12( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = atomicrmw xor ptr [[PTR:%.*]], i16 [[VAL:%.*]] seq_cst, align 2 +// CHECK-NEXT: [[TMP1:%.*]] = xor i16 [[TMP0]], [[VAL]] +// CHECK-NEXT: ret i16 [[TMP1]] +// +int16_t f12(int16_t *Ptr, int16_t Val) { + return __atomic_xor_fetch(Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f13( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = atomicrmw or ptr [[PTR:%.*]], i16 [[VAL:%.*]] seq_cst, align 2 +// CHECK-NEXT: [[TMP1:%.*]] = or i16 [[TMP0]], [[VAL]] +// CHECK-NEXT: ret i16 [[TMP1]] +// +int16_t f13(int16_t *Ptr, int16_t Val) { + return __atomic_or_fetch(Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f14( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = atomicrmw nand ptr [[PTR:%.*]], i16 [[VAL:%.*]] seq_cst, align 2 +// CHECK-NEXT: [[TMP1:%.*]] = and i16 [[TMP0]], [[VAL]] +// CHECK-NEXT: [[TMP2:%.*]] = xor i16 [[TMP1]], -1 +// CHECK-NEXT: ret i16 [[TMP2]] +// +int16_t f14(int16_t *Ptr, int16_t Val) { + return __atomic_nand_fetch(Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f15( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = atomicrmw add ptr [[PTR:%.*]], i16 [[VAL:%.*]] seq_cst, align 2 +// CHECK-NEXT: ret i16 [[TMP0]] +// +int16_t f15(int16_t *Ptr, int16_t Val) { + return __atomic_fetch_add(Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = atomicrmw sub ptr [[PTR:%.*]], i16 [[VAL:%.*]] seq_cst, align 2 +// CHECK-NEXT: ret i16 [[TMP0]] +// +int16_t f16(int16_t *Ptr, int16_t Val) { + return __atomic_fetch_sub(Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f17( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = atomicrmw and ptr [[PTR:%.*]], i16 [[VAL:%.*]] seq_cst, align 2 +// CHECK-NEXT: ret i16 [[TMP0]] +// +int16_t f17(int16_t *Ptr, int16_t Val) { + return __atomic_fetch_and(Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f18( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = atomicrmw xor ptr [[PTR:%.*]], i16 [[VAL:%.*]] seq_cst, align 2 +// CHECK-NEXT: ret i16 [[TMP0]] +// +int16_t f18(int16_t *Ptr, int16_t Val) { + return __atomic_fetch_xor(Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f19( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = atomicrmw or ptr [[PTR:%.*]], i16 [[VAL:%.*]] seq_cst, align 2 +// CHECK-NEXT: ret i16 [[TMP0]] +// +int16_t f19(int16_t *Ptr, int16_t Val) { + return __atomic_fetch_or(Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f20( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = atomicrmw nand ptr [[PTR:%.*]], i16 [[VAL:%.*]] seq_cst, align 2 +// CHECK-NEXT: ret i16 [[TMP0]] +// +int16_t f20(int16_t *Ptr, int16_t Val) { + return __atomic_fetch_nand(Ptr, Val, memory_order_seq_cst); +} diff --git a/clang/test/CodeGen/SystemZ/gnu-atomic-builtins-i32.c b/clang/test/CodeGen/SystemZ/gnu-atomic-builtins-i32.c new file mode 100644 index 0000000000000000000000000000000000000000..ba630e7c952e5b2e331c402972be1794f6111376 --- /dev/null +++ b/clang/test/CodeGen/SystemZ/gnu-atomic-builtins-i32.c @@ -0,0 +1,219 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// RUN: %clang_cc1 -triple s390x-linux-gnu -O1 -emit-llvm %s -o - | FileCheck %s +// +// Test GNU atomic builtins for int32_t. + +#include +#include + +// CHECK-LABEL: @f1( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = load atomic i32, ptr [[PTR:%.*]] seq_cst, align 4 +// CHECK-NEXT: ret i32 [[TMP0]] +// +int32_t f1(int32_t *Ptr) { + return __atomic_load_n(Ptr, memory_order_seq_cst); +} + +// CHECK-LABEL: @f2( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = load atomic i32, ptr [[PTR:%.*]] seq_cst, align 4 +// CHECK-NEXT: store i32 [[TMP0]], ptr [[RET:%.*]], align 4 +// CHECK-NEXT: ret i32 [[TMP0]] +// +int32_t f2(int32_t *Ptr, int32_t *Ret) { + __atomic_load(Ptr, Ret, memory_order_seq_cst); + return *Ret; +} + +// CHECK-LABEL: @f3( +// CHECK-NEXT: entry: +// CHECK-NEXT: store atomic i32 [[VAL:%.*]], ptr [[PTR:%.*]] seq_cst, align 4 +// CHECK-NEXT: ret void +// +void f3(int32_t *Ptr, int32_t Val) { + __atomic_store_n(Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f4( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[VAL:%.*]], align 4 +// CHECK-NEXT: store atomic i32 [[TMP0]], ptr [[PTR:%.*]] seq_cst, align 4 +// CHECK-NEXT: ret void +// +void f4(int32_t *Ptr, int32_t *Val) { + __atomic_store(Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f5( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = atomicrmw xchg ptr [[PTR:%.*]], i32 [[VAL:%.*]] seq_cst, align 4 +// CHECK-NEXT: ret i32 [[TMP0]] +// +int32_t f5(int32_t *Ptr, int32_t Val) { + return __atomic_exchange_n(Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f6( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[VAL:%.*]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = atomicrmw xchg ptr [[PTR:%.*]], i32 [[TMP0]] seq_cst, align 4 +// CHECK-NEXT: store i32 [[TMP1]], ptr [[RET:%.*]], align 4 +// CHECK-NEXT: ret i32 [[TMP1]] +// +int32_t f6(int32_t *Ptr, int32_t *Val, int32_t *Ret) { + __atomic_exchange(Ptr, Val, Ret, memory_order_seq_cst); + return *Ret; +} + +// CHECK-LABEL: @f7( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[EXP:%.*]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = cmpxchg ptr [[PTR:%.*]], i32 [[TMP0]], i32 [[DES:%.*]] seq_cst seq_cst, align 4 +// CHECK-NEXT: [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1 +// CHECK-NEXT: br i1 [[TMP2]], label [[CMPXCHG_CONTINUE:%.*]], label [[CMPXCHG_STORE_EXPECTED:%.*]] +// CHECK: cmpxchg.store_expected: +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i32, i1 } [[TMP1]], 0 +// CHECK-NEXT: store i32 [[TMP3]], ptr [[EXP]], align 4 +// CHECK-NEXT: br label [[CMPXCHG_CONTINUE]] +// CHECK: cmpxchg.continue: +// CHECK-NEXT: ret i1 [[TMP2]] +// +_Bool f7(int32_t *Ptr, int32_t *Exp, int32_t Des) { + return __atomic_compare_exchange_n(Ptr, Exp, Des, 0, + memory_order_seq_cst, memory_order_seq_cst); +} + +// CHECK-LABEL: @f8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[EXP:%.*]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[DES:%.*]], align 4 +// CHECK-NEXT: [[TMP2:%.*]] = cmpxchg ptr [[PTR:%.*]], i32 [[TMP0]], i32 [[TMP1]] seq_cst seq_cst, align 4 +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i32, i1 } [[TMP2]], 1 +// CHECK-NEXT: br i1 [[TMP3]], label [[CMPXCHG_CONTINUE:%.*]], label [[CMPXCHG_STORE_EXPECTED:%.*]] +// CHECK: cmpxchg.store_expected: +// CHECK-NEXT: [[TMP4:%.*]] = extractvalue { i32, i1 } [[TMP2]], 0 +// CHECK-NEXT: store i32 [[TMP4]], ptr [[EXP]], align 4 +// CHECK-NEXT: br label [[CMPXCHG_CONTINUE]] +// CHECK: cmpxchg.continue: +// CHECK-NEXT: ret i1 [[TMP3]] +// +_Bool f8(int32_t *Ptr, int32_t *Exp, int32_t *Des) { + return __atomic_compare_exchange(Ptr, Exp, Des, 0, + memory_order_seq_cst, memory_order_seq_cst); +} + +// CHECK-LABEL: @f9( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = atomicrmw add ptr [[PTR:%.*]], i32 [[VAL:%.*]] seq_cst, align 4 +// CHECK-NEXT: [[TMP1:%.*]] = add i32 [[TMP0]], [[VAL]] +// CHECK-NEXT: ret i32 [[TMP1]] +// +int32_t f9(int32_t *Ptr, int32_t Val) { + return __atomic_add_fetch(Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f10( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = atomicrmw sub ptr [[PTR:%.*]], i32 [[VAL:%.*]] seq_cst, align 4 +// CHECK-NEXT: [[TMP1:%.*]] = sub i32 [[TMP0]], [[VAL]] +// CHECK-NEXT: ret i32 [[TMP1]] +// +int32_t f10(int32_t *Ptr, int32_t Val) { + return __atomic_sub_fetch(Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f11( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = atomicrmw and ptr [[PTR:%.*]], i32 [[VAL:%.*]] seq_cst, align 4 +// CHECK-NEXT: [[TMP1:%.*]] = and i32 [[TMP0]], [[VAL]] +// CHECK-NEXT: ret i32 [[TMP1]] +// +int32_t f11(int32_t *Ptr, int32_t Val) { + return __atomic_and_fetch(Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f12( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = atomicrmw xor ptr [[PTR:%.*]], i32 [[VAL:%.*]] seq_cst, align 4 +// CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[TMP0]], [[VAL]] +// CHECK-NEXT: ret i32 [[TMP1]] +// +int32_t f12(int32_t *Ptr, int32_t Val) { + return __atomic_xor_fetch(Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f13( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = atomicrmw or ptr [[PTR:%.*]], i32 [[VAL:%.*]] seq_cst, align 4 +// CHECK-NEXT: [[TMP1:%.*]] = or i32 [[TMP0]], [[VAL]] +// CHECK-NEXT: ret i32 [[TMP1]] +// +int32_t f13(int32_t *Ptr, int32_t Val) { + return __atomic_or_fetch(Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f14( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = atomicrmw nand ptr [[PTR:%.*]], i32 [[VAL:%.*]] seq_cst, align 4 +// CHECK-NEXT: [[TMP1:%.*]] = and i32 [[TMP0]], [[VAL]] +// CHECK-NEXT: [[TMP2:%.*]] = xor i32 [[TMP1]], -1 +// CHECK-NEXT: ret i32 [[TMP2]] +// +int32_t f14(int32_t *Ptr, int32_t Val) { + return __atomic_nand_fetch(Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f15( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = atomicrmw add ptr [[PTR:%.*]], i32 [[VAL:%.*]] seq_cst, align 4 +// CHECK-NEXT: ret i32 [[TMP0]] +// +int32_t f15(int32_t *Ptr, int32_t Val) { + return __atomic_fetch_add(Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = atomicrmw sub ptr [[PTR:%.*]], i32 [[VAL:%.*]] seq_cst, align 4 +// CHECK-NEXT: ret i32 [[TMP0]] +// +int32_t f16(int32_t *Ptr, int32_t Val) { + return __atomic_fetch_sub(Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f17( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = atomicrmw and ptr [[PTR:%.*]], i32 [[VAL:%.*]] seq_cst, align 4 +// CHECK-NEXT: ret i32 [[TMP0]] +// +int32_t f17(int32_t *Ptr, int32_t Val) { + return __atomic_fetch_and(Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f18( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = atomicrmw xor ptr [[PTR:%.*]], i32 [[VAL:%.*]] seq_cst, align 4 +// CHECK-NEXT: ret i32 [[TMP0]] +// +int32_t f18(int32_t *Ptr, int32_t Val) { + return __atomic_fetch_xor(Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f19( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = atomicrmw or ptr [[PTR:%.*]], i32 [[VAL:%.*]] seq_cst, align 4 +// CHECK-NEXT: ret i32 [[TMP0]] +// +int32_t f19(int32_t *Ptr, int32_t Val) { + return __atomic_fetch_or(Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f20( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = atomicrmw nand ptr [[PTR:%.*]], i32 [[VAL:%.*]] seq_cst, align 4 +// CHECK-NEXT: ret i32 [[TMP0]] +// +int32_t f20(int32_t *Ptr, int32_t Val) { + return __atomic_fetch_nand(Ptr, Val, memory_order_seq_cst); +} diff --git a/clang/test/CodeGen/SystemZ/gnu-atomic-builtins-i64.c b/clang/test/CodeGen/SystemZ/gnu-atomic-builtins-i64.c new file mode 100644 index 0000000000000000000000000000000000000000..25c69ee8c54bf53b19f88345e76e78788030575a --- /dev/null +++ b/clang/test/CodeGen/SystemZ/gnu-atomic-builtins-i64.c @@ -0,0 +1,219 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// RUN: %clang_cc1 -triple s390x-linux-gnu -O1 -emit-llvm %s -o - | FileCheck %s +// +// Test GNU atomic builtins for int64_t. + +#include +#include + +// CHECK-LABEL: @f1( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = load atomic i64, ptr [[PTR:%.*]] seq_cst, align 8 +// CHECK-NEXT: ret i64 [[TMP0]] +// +int64_t f1(int64_t *Ptr) { + return __atomic_load_n(Ptr, memory_order_seq_cst); +} + +// CHECK-LABEL: @f2( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = load atomic i64, ptr [[PTR:%.*]] seq_cst, align 8 +// CHECK-NEXT: store i64 [[TMP0]], ptr [[RET:%.*]], align 8 +// CHECK-NEXT: ret i64 [[TMP0]] +// +int64_t f2(int64_t *Ptr, int64_t *Ret) { + __atomic_load(Ptr, Ret, memory_order_seq_cst); + return *Ret; +} + +// CHECK-LABEL: @f3( +// CHECK-NEXT: entry: +// CHECK-NEXT: store atomic i64 [[VAL:%.*]], ptr [[PTR:%.*]] seq_cst, align 8 +// CHECK-NEXT: ret void +// +void f3(int64_t *Ptr, int64_t Val) { + __atomic_store_n(Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f4( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr [[VAL:%.*]], align 8 +// CHECK-NEXT: store atomic i64 [[TMP0]], ptr [[PTR:%.*]] seq_cst, align 8 +// CHECK-NEXT: ret void +// +void f4(int64_t *Ptr, int64_t *Val) { + __atomic_store(Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f5( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = atomicrmw xchg ptr [[PTR:%.*]], i64 [[VAL:%.*]] seq_cst, align 8 +// CHECK-NEXT: ret i64 [[TMP0]] +// +int64_t f5(int64_t *Ptr, int64_t Val) { + return __atomic_exchange_n(Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f6( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr [[VAL:%.*]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = atomicrmw xchg ptr [[PTR:%.*]], i64 [[TMP0]] seq_cst, align 8 +// CHECK-NEXT: store i64 [[TMP1]], ptr [[RET:%.*]], align 8 +// CHECK-NEXT: ret i64 [[TMP1]] +// +int64_t f6(int64_t *Ptr, int64_t *Val, int64_t *Ret) { + __atomic_exchange(Ptr, Val, Ret, memory_order_seq_cst); + return *Ret; +} + +// CHECK-LABEL: @f7( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr [[EXP:%.*]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = cmpxchg ptr [[PTR:%.*]], i64 [[TMP0]], i64 [[DES:%.*]] seq_cst seq_cst, align 8 +// CHECK-NEXT: [[TMP2:%.*]] = extractvalue { i64, i1 } [[TMP1]], 1 +// CHECK-NEXT: br i1 [[TMP2]], label [[CMPXCHG_CONTINUE:%.*]], label [[CMPXCHG_STORE_EXPECTED:%.*]] +// CHECK: cmpxchg.store_expected: +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i64, i1 } [[TMP1]], 0 +// CHECK-NEXT: store i64 [[TMP3]], ptr [[EXP]], align 8 +// CHECK-NEXT: br label [[CMPXCHG_CONTINUE]] +// CHECK: cmpxchg.continue: +// CHECK-NEXT: ret i1 [[TMP2]] +// +_Bool f7(int64_t *Ptr, int64_t *Exp, int64_t Des) { + return __atomic_compare_exchange_n(Ptr, Exp, Des, 0, + memory_order_seq_cst, memory_order_seq_cst); +} + +// CHECK-LABEL: @f8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr [[EXP:%.*]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load i64, ptr [[DES:%.*]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = cmpxchg ptr [[PTR:%.*]], i64 [[TMP0]], i64 [[TMP1]] seq_cst seq_cst, align 8 +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i64, i1 } [[TMP2]], 1 +// CHECK-NEXT: br i1 [[TMP3]], label [[CMPXCHG_CONTINUE:%.*]], label [[CMPXCHG_STORE_EXPECTED:%.*]] +// CHECK: cmpxchg.store_expected: +// CHECK-NEXT: [[TMP4:%.*]] = extractvalue { i64, i1 } [[TMP2]], 0 +// CHECK-NEXT: store i64 [[TMP4]], ptr [[EXP]], align 8 +// CHECK-NEXT: br label [[CMPXCHG_CONTINUE]] +// CHECK: cmpxchg.continue: +// CHECK-NEXT: ret i1 [[TMP3]] +// +_Bool f8(int64_t *Ptr, int64_t *Exp, int64_t *Des) { + return __atomic_compare_exchange(Ptr, Exp, Des, 0, + memory_order_seq_cst, memory_order_seq_cst); +} + +// CHECK-LABEL: @f9( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = atomicrmw add ptr [[PTR:%.*]], i64 [[VAL:%.*]] seq_cst, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = add i64 [[TMP0]], [[VAL]] +// CHECK-NEXT: ret i64 [[TMP1]] +// +int64_t f9(int64_t *Ptr, int64_t Val) { + return __atomic_add_fetch(Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f10( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = atomicrmw sub ptr [[PTR:%.*]], i64 [[VAL:%.*]] seq_cst, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = sub i64 [[TMP0]], [[VAL]] +// CHECK-NEXT: ret i64 [[TMP1]] +// +int64_t f10(int64_t *Ptr, int64_t Val) { + return __atomic_sub_fetch(Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f11( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = atomicrmw and ptr [[PTR:%.*]], i64 [[VAL:%.*]] seq_cst, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], [[VAL]] +// CHECK-NEXT: ret i64 [[TMP1]] +// +int64_t f11(int64_t *Ptr, int64_t Val) { + return __atomic_and_fetch(Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f12( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = atomicrmw xor ptr [[PTR:%.*]], i64 [[VAL:%.*]] seq_cst, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = xor i64 [[TMP0]], [[VAL]] +// CHECK-NEXT: ret i64 [[TMP1]] +// +int64_t f12(int64_t *Ptr, int64_t Val) { + return __atomic_xor_fetch(Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f13( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = atomicrmw or ptr [[PTR:%.*]], i64 [[VAL:%.*]] seq_cst, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = or i64 [[TMP0]], [[VAL]] +// CHECK-NEXT: ret i64 [[TMP1]] +// +int64_t f13(int64_t *Ptr, int64_t Val) { + return __atomic_or_fetch(Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f14( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = atomicrmw nand ptr [[PTR:%.*]], i64 [[VAL:%.*]] seq_cst, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], [[VAL]] +// CHECK-NEXT: [[TMP2:%.*]] = xor i64 [[TMP1]], -1 +// CHECK-NEXT: ret i64 [[TMP2]] +// +int64_t f14(int64_t *Ptr, int64_t Val) { + return __atomic_nand_fetch(Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f15( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = atomicrmw add ptr [[PTR:%.*]], i64 [[VAL:%.*]] seq_cst, align 8 +// CHECK-NEXT: ret i64 [[TMP0]] +// +int64_t f15(int64_t *Ptr, int64_t Val) { + return __atomic_fetch_add(Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = atomicrmw sub ptr [[PTR:%.*]], i64 [[VAL:%.*]] seq_cst, align 8 +// CHECK-NEXT: ret i64 [[TMP0]] +// +int64_t f16(int64_t *Ptr, int64_t Val) { + return __atomic_fetch_sub(Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f17( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = atomicrmw and ptr [[PTR:%.*]], i64 [[VAL:%.*]] seq_cst, align 8 +// CHECK-NEXT: ret i64 [[TMP0]] +// +int64_t f17(int64_t *Ptr, int64_t Val) { + return __atomic_fetch_and(Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f18( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = atomicrmw xor ptr [[PTR:%.*]], i64 [[VAL:%.*]] seq_cst, align 8 +// CHECK-NEXT: ret i64 [[TMP0]] +// +int64_t f18(int64_t *Ptr, int64_t Val) { + return __atomic_fetch_xor(Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f19( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = atomicrmw or ptr [[PTR:%.*]], i64 [[VAL:%.*]] seq_cst, align 8 +// CHECK-NEXT: ret i64 [[TMP0]] +// +int64_t f19(int64_t *Ptr, int64_t Val) { + return __atomic_fetch_or(Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f20( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = atomicrmw nand ptr [[PTR:%.*]], i64 [[VAL:%.*]] seq_cst, align 8 +// CHECK-NEXT: ret i64 [[TMP0]] +// +int64_t f20(int64_t *Ptr, int64_t Val) { + return __atomic_fetch_nand(Ptr, Val, memory_order_seq_cst); +} diff --git a/clang/test/CodeGen/SystemZ/gnu-atomic-builtins-i8.c b/clang/test/CodeGen/SystemZ/gnu-atomic-builtins-i8.c new file mode 100644 index 0000000000000000000000000000000000000000..1f4b455bc02610a2cc3c56ab14c677d49b61b63c --- /dev/null +++ b/clang/test/CodeGen/SystemZ/gnu-atomic-builtins-i8.c @@ -0,0 +1,219 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// RUN: %clang_cc1 -triple s390x-linux-gnu -O1 -emit-llvm %s -o - | FileCheck %s +// +// Test GNU atomic builtins for int8_t. + +#include +#include + +// CHECK-LABEL: @f1( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = load atomic i8, ptr [[PTR:%.*]] seq_cst, align 1 +// CHECK-NEXT: ret i8 [[TMP0]] +// +int8_t f1(int8_t *Ptr) { + return __atomic_load_n(Ptr, memory_order_seq_cst); +} + +// CHECK-LABEL: @f2( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = load atomic i8, ptr [[PTR:%.*]] seq_cst, align 1 +// CHECK-NEXT: store i8 [[TMP0]], ptr [[RET:%.*]], align 1 +// CHECK-NEXT: ret i8 [[TMP0]] +// +int8_t f2(int8_t *Ptr, int8_t *Ret) { + __atomic_load(Ptr, Ret, memory_order_seq_cst); + return *Ret; +} + +// CHECK-LABEL: @f3( +// CHECK-NEXT: entry: +// CHECK-NEXT: store atomic i8 [[VAL:%.*]], ptr [[PTR:%.*]] seq_cst, align 1 +// CHECK-NEXT: ret void +// +void f3(int8_t *Ptr, int8_t Val) { + __atomic_store_n(Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f4( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[VAL:%.*]], align 1 +// CHECK-NEXT: store atomic i8 [[TMP0]], ptr [[PTR:%.*]] seq_cst, align 1 +// CHECK-NEXT: ret void +// +void f4(int8_t *Ptr, int8_t *Val) { + __atomic_store(Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f5( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = atomicrmw xchg ptr [[PTR:%.*]], i8 [[VAL:%.*]] seq_cst, align 1 +// CHECK-NEXT: ret i8 [[TMP0]] +// +int8_t f5(int8_t *Ptr, int8_t Val) { + return __atomic_exchange_n(Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f6( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[VAL:%.*]], align 1 +// CHECK-NEXT: [[TMP1:%.*]] = atomicrmw xchg ptr [[PTR:%.*]], i8 [[TMP0]] seq_cst, align 1 +// CHECK-NEXT: store i8 [[TMP1]], ptr [[RET:%.*]], align 1 +// CHECK-NEXT: ret i8 [[TMP1]] +// +int8_t f6(int8_t *Ptr, int8_t *Val, int8_t *Ret) { + __atomic_exchange(Ptr, Val, Ret, memory_order_seq_cst); + return *Ret; +} + +// CHECK-LABEL: @f7( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[EXP:%.*]], align 1 +// CHECK-NEXT: [[TMP1:%.*]] = cmpxchg ptr [[PTR:%.*]], i8 [[TMP0]], i8 [[DES:%.*]] seq_cst seq_cst, align 1 +// CHECK-NEXT: [[TMP2:%.*]] = extractvalue { i8, i1 } [[TMP1]], 1 +// CHECK-NEXT: br i1 [[TMP2]], label [[CMPXCHG_CONTINUE:%.*]], label [[CMPXCHG_STORE_EXPECTED:%.*]] +// CHECK: cmpxchg.store_expected: +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i8, i1 } [[TMP1]], 0 +// CHECK-NEXT: store i8 [[TMP3]], ptr [[EXP]], align 1 +// CHECK-NEXT: br label [[CMPXCHG_CONTINUE]] +// CHECK: cmpxchg.continue: +// CHECK-NEXT: ret i1 [[TMP2]] +// +_Bool f7(int8_t *Ptr, int8_t *Exp, int8_t Des) { + return __atomic_compare_exchange_n(Ptr, Exp, Des, 0, + memory_order_seq_cst, memory_order_seq_cst); +} + +// CHECK-LABEL: @f8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[EXP:%.*]], align 1 +// CHECK-NEXT: [[TMP1:%.*]] = load i8, ptr [[DES:%.*]], align 1 +// CHECK-NEXT: [[TMP2:%.*]] = cmpxchg ptr [[PTR:%.*]], i8 [[TMP0]], i8 [[TMP1]] seq_cst seq_cst, align 1 +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i8, i1 } [[TMP2]], 1 +// CHECK-NEXT: br i1 [[TMP3]], label [[CMPXCHG_CONTINUE:%.*]], label [[CMPXCHG_STORE_EXPECTED:%.*]] +// CHECK: cmpxchg.store_expected: +// CHECK-NEXT: [[TMP4:%.*]] = extractvalue { i8, i1 } [[TMP2]], 0 +// CHECK-NEXT: store i8 [[TMP4]], ptr [[EXP]], align 1 +// CHECK-NEXT: br label [[CMPXCHG_CONTINUE]] +// CHECK: cmpxchg.continue: +// CHECK-NEXT: ret i1 [[TMP3]] +// +_Bool f8(int8_t *Ptr, int8_t *Exp, int8_t *Des) { + return __atomic_compare_exchange(Ptr, Exp, Des, 0, + memory_order_seq_cst, memory_order_seq_cst); +} + +// CHECK-LABEL: @f9( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = atomicrmw add ptr [[PTR:%.*]], i8 [[VAL:%.*]] seq_cst, align 1 +// CHECK-NEXT: [[TMP1:%.*]] = add i8 [[TMP0]], [[VAL]] +// CHECK-NEXT: ret i8 [[TMP1]] +// +int8_t f9(int8_t *Ptr, int8_t Val) { + return __atomic_add_fetch(Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f10( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = atomicrmw sub ptr [[PTR:%.*]], i8 [[VAL:%.*]] seq_cst, align 1 +// CHECK-NEXT: [[TMP1:%.*]] = sub i8 [[TMP0]], [[VAL]] +// CHECK-NEXT: ret i8 [[TMP1]] +// +int8_t f10(int8_t *Ptr, int8_t Val) { + return __atomic_sub_fetch(Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f11( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = atomicrmw and ptr [[PTR:%.*]], i8 [[VAL:%.*]] seq_cst, align 1 +// CHECK-NEXT: [[TMP1:%.*]] = and i8 [[TMP0]], [[VAL]] +// CHECK-NEXT: ret i8 [[TMP1]] +// +int8_t f11(int8_t *Ptr, int8_t Val) { + return __atomic_and_fetch(Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f12( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = atomicrmw xor ptr [[PTR:%.*]], i8 [[VAL:%.*]] seq_cst, align 1 +// CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[TMP0]], [[VAL]] +// CHECK-NEXT: ret i8 [[TMP1]] +// +int8_t f12(int8_t *Ptr, int8_t Val) { + return __atomic_xor_fetch(Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f13( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = atomicrmw or ptr [[PTR:%.*]], i8 [[VAL:%.*]] seq_cst, align 1 +// CHECK-NEXT: [[TMP1:%.*]] = or i8 [[TMP0]], [[VAL]] +// CHECK-NEXT: ret i8 [[TMP1]] +// +int8_t f13(int8_t *Ptr, int8_t Val) { + return __atomic_or_fetch(Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f14( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = atomicrmw nand ptr [[PTR:%.*]], i8 [[VAL:%.*]] seq_cst, align 1 +// CHECK-NEXT: [[TMP1:%.*]] = and i8 [[TMP0]], [[VAL]] +// CHECK-NEXT: [[TMP2:%.*]] = xor i8 [[TMP1]], -1 +// CHECK-NEXT: ret i8 [[TMP2]] +// +int8_t f14(int8_t *Ptr, int8_t Val) { + return __atomic_nand_fetch(Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f15( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = atomicrmw add ptr [[PTR:%.*]], i8 [[VAL:%.*]] seq_cst, align 1 +// CHECK-NEXT: ret i8 [[TMP0]] +// +int8_t f15(int8_t *Ptr, int8_t Val) { + return __atomic_fetch_add(Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = atomicrmw sub ptr [[PTR:%.*]], i8 [[VAL:%.*]] seq_cst, align 1 +// CHECK-NEXT: ret i8 [[TMP0]] +// +int8_t f16(int8_t *Ptr, int8_t Val) { + return __atomic_fetch_sub(Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f17( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = atomicrmw and ptr [[PTR:%.*]], i8 [[VAL:%.*]] seq_cst, align 1 +// CHECK-NEXT: ret i8 [[TMP0]] +// +int8_t f17(int8_t *Ptr, int8_t Val) { + return __atomic_fetch_and(Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f18( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = atomicrmw xor ptr [[PTR:%.*]], i8 [[VAL:%.*]] seq_cst, align 1 +// CHECK-NEXT: ret i8 [[TMP0]] +// +int8_t f18(int8_t *Ptr, int8_t Val) { + return __atomic_fetch_xor(Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f19( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = atomicrmw or ptr [[PTR:%.*]], i8 [[VAL:%.*]] seq_cst, align 1 +// CHECK-NEXT: ret i8 [[TMP0]] +// +int8_t f19(int8_t *Ptr, int8_t Val) { + return __atomic_fetch_or(Ptr, Val, memory_order_seq_cst); +} + +// CHECK-LABEL: @f20( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = atomicrmw nand ptr [[PTR:%.*]], i8 [[VAL:%.*]] seq_cst, align 1 +// CHECK-NEXT: ret i8 [[TMP0]] +// +int8_t f20(int8_t *Ptr, int8_t Val) { + return __atomic_fetch_nand(Ptr, Val, memory_order_seq_cst); +} diff --git a/clang/test/CodeGen/aarch64-sme-intrinsics/acle_sme_ld1.c b/clang/test/CodeGen/aarch64-sme-intrinsics/acle_sme_ld1.c index 72d159b19118e3adeed3fa15b947cc1b78ccd134..5622568c4cd76b6e876079dd0d69ca696df3a66f 100644 --- a/clang/test/CodeGen/aarch64-sme-intrinsics/acle_sme_ld1.c +++ b/clang/test/CodeGen/aarch64-sme-intrinsics/acle_sme_ld1.c @@ -1,17 +1,11 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 3 // REQUIRES: aarch64-registered-target -// RUN: %clang_cc1 -DDISABLE_SME_ATTRIBUTES -triple aarch64-none-linux-gnu -target-feature +sme -target-feature +sve -S -O1 -Werror -emit-llvm -o - %s | FileCheck %s -check-prefixes=CHECK,CHECK-C -// RUN: %clang_cc1 -DDISABLE_SME_ATTRIBUTES -triple aarch64-none-linux-gnu -target-feature +sme -target-feature +sve -S -O1 -Werror -emit-llvm -o - -x c++ %s | FileCheck %s -check-prefixes=CHECK,CHECK-CXX -// RUN: %clang_cc1 -DDISABLE_SME_ATTRIBUTES -triple aarch64-none-linux-gnu -target-feature +sme -target-feature +sve -S -O1 -Werror -o /dev/null %s +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme -target-feature +sve -S -O1 -Werror -emit-llvm -o - %s | FileCheck %s -check-prefixes=CHECK,CHECK-C +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme -target-feature +sve -S -O1 -Werror -emit-llvm -o - -x c++ %s | FileCheck %s -check-prefixes=CHECK,CHECK-CXX +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme -target-feature +sve -S -O1 -Werror -o /dev/null %s #include -#ifdef DISABLE_SME_ATTRIBUTES -#define ARM_STREAMING_ATTR -#else -#define ARM_STREAMING_ATTR __attribute__((arm_streaming)) -#endif - // CHECK-C-LABEL: define dso_local void @test_svld1_hor_za8( // CHECK-C-SAME: i32 noundef [[SLICE_BASE:%.*]], [[PG:%.*]], ptr noundef [[PTR:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { // CHECK-C-NEXT: entry: @@ -28,7 +22,7 @@ // CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.ld1b.horiz( [[PG]], ptr [[PTR]], i32 0, i32 [[ADD]]) // CHECK-CXX-NEXT: ret void // -ARM_STREAMING_ATTR void test_svld1_hor_za8(uint32_t slice_base, svbool_t pg, const void *ptr) { +void test_svld1_hor_za8(uint32_t slice_base, svbool_t pg, const void *ptr) __arm_streaming { svld1_hor_za8(0, slice_base, pg, ptr); svld1_hor_za8(0, slice_base + 15, pg, ptr); } @@ -51,7 +45,7 @@ ARM_STREAMING_ATTR void test_svld1_hor_za8(uint32_t slice_base, svbool_t pg, con // CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.ld1h.horiz( [[TMP0]], ptr [[PTR]], i32 1, i32 [[ADD]]) // CHECK-CXX-NEXT: ret void // -ARM_STREAMING_ATTR void test_svld1_hor_za16(uint32_t slice_base, svbool_t pg, const void *ptr) { +void test_svld1_hor_za16(uint32_t slice_base, svbool_t pg, const void *ptr) __arm_streaming { svld1_hor_za16(0, slice_base, pg, ptr); svld1_hor_za16(1, slice_base + 7, pg, ptr); } @@ -74,7 +68,7 @@ ARM_STREAMING_ATTR void test_svld1_hor_za16(uint32_t slice_base, svbool_t pg, co // CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.ld1w.horiz( [[TMP0]], ptr [[PTR]], i32 3, i32 [[ADD]]) // CHECK-CXX-NEXT: ret void // -ARM_STREAMING_ATTR void test_svld1_hor_za32(uint32_t slice_base, svbool_t pg, const void *ptr) { +void test_svld1_hor_za32(uint32_t slice_base, svbool_t pg, const void *ptr) __arm_streaming { svld1_hor_za32(0, slice_base, pg, ptr); svld1_hor_za32(3, slice_base + 3, pg, ptr); } @@ -97,7 +91,7 @@ ARM_STREAMING_ATTR void test_svld1_hor_za32(uint32_t slice_base, svbool_t pg, co // CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.ld1d.horiz( [[TMP0]], ptr [[PTR]], i32 7, i32 [[ADD]]) // CHECK-CXX-NEXT: ret void // -ARM_STREAMING_ATTR void test_svld1_hor_za64(uint32_t slice_base, svbool_t pg, const void *ptr) { +void test_svld1_hor_za64(uint32_t slice_base, svbool_t pg, const void *ptr) __arm_streaming { svld1_hor_za64(0, slice_base, pg, ptr); svld1_hor_za64(7, slice_base + 1, pg, ptr); } @@ -118,7 +112,7 @@ ARM_STREAMING_ATTR void test_svld1_hor_za64(uint32_t slice_base, svbool_t pg, co // CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.ld1q.horiz( [[TMP0]], ptr [[PTR]], i32 15, i32 [[SLICE_BASE]]) // CHECK-CXX-NEXT: ret void // -ARM_STREAMING_ATTR void test_svld1_hor_za128(uint32_t slice_base, svbool_t pg, const void *ptr) { +void test_svld1_hor_za128(uint32_t slice_base, svbool_t pg, const void *ptr) __arm_streaming { svld1_hor_za128(0, slice_base, pg, ptr); svld1_hor_za128(15, slice_base, pg, ptr); } @@ -139,7 +133,7 @@ ARM_STREAMING_ATTR void test_svld1_hor_za128(uint32_t slice_base, svbool_t pg, c // CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.ld1b.vert( [[PG]], ptr [[PTR]], i32 0, i32 [[ADD]]) // CHECK-CXX-NEXT: ret void // -ARM_STREAMING_ATTR void test_svld1_ver_za8(uint32_t slice_base, svbool_t pg, const void *ptr) { +void test_svld1_ver_za8(uint32_t slice_base, svbool_t pg, const void *ptr) __arm_streaming { svld1_ver_za8(0, slice_base, pg, ptr); svld1_ver_za8(0, slice_base + 15, pg, ptr); } @@ -162,7 +156,7 @@ ARM_STREAMING_ATTR void test_svld1_ver_za8(uint32_t slice_base, svbool_t pg, con // CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.ld1h.vert( [[TMP0]], ptr [[PTR]], i32 1, i32 [[ADD]]) // CHECK-CXX-NEXT: ret void // -ARM_STREAMING_ATTR void test_svld1_ver_za16(uint32_t slice_base, svbool_t pg, const void *ptr) { +void test_svld1_ver_za16(uint32_t slice_base, svbool_t pg, const void *ptr) __arm_streaming { svld1_ver_za16(0, slice_base, pg, ptr); svld1_ver_za16(1, slice_base + 7, pg, ptr); } @@ -185,7 +179,7 @@ ARM_STREAMING_ATTR void test_svld1_ver_za16(uint32_t slice_base, svbool_t pg, co // CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.ld1w.vert( [[TMP0]], ptr [[PTR]], i32 3, i32 [[ADD]]) // CHECK-CXX-NEXT: ret void // -ARM_STREAMING_ATTR void test_svld1_ver_za32(uint32_t slice_base, svbool_t pg, const void *ptr) { +void test_svld1_ver_za32(uint32_t slice_base, svbool_t pg, const void *ptr) __arm_streaming { svld1_ver_za32(0, slice_base, pg, ptr); svld1_ver_za32(3, slice_base + 3, pg, ptr); } @@ -208,7 +202,7 @@ ARM_STREAMING_ATTR void test_svld1_ver_za32(uint32_t slice_base, svbool_t pg, co // CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.ld1d.vert( [[TMP0]], ptr [[PTR]], i32 7, i32 [[ADD]]) // CHECK-CXX-NEXT: ret void // -ARM_STREAMING_ATTR void test_svld1_ver_za64(uint32_t slice_base, svbool_t pg, const void *ptr) { +void test_svld1_ver_za64(uint32_t slice_base, svbool_t pg, const void *ptr) __arm_streaming { svld1_ver_za64(0, slice_base, pg, ptr); svld1_ver_za64(7, slice_base + 1, pg, ptr); } @@ -229,7 +223,7 @@ ARM_STREAMING_ATTR void test_svld1_ver_za64(uint32_t slice_base, svbool_t pg, co // CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.ld1q.vert( [[TMP0]], ptr [[PTR]], i32 15, i32 [[SLICE_BASE]]) // CHECK-CXX-NEXT: ret void // -ARM_STREAMING_ATTR void test_svld1_ver_za128(uint32_t slice_base, svbool_t pg, const void *ptr) { +void test_svld1_ver_za128(uint32_t slice_base, svbool_t pg, const void *ptr) __arm_streaming { svld1_ver_za128(0, slice_base, pg, ptr); svld1_ver_za128(15, slice_base, pg, ptr); } diff --git a/clang/test/CodeGen/aarch64-sme-intrinsics/acle_sme_ld1_vnum.c b/clang/test/CodeGen/aarch64-sme-intrinsics/acle_sme_ld1_vnum.c index cf49f62664eee8c0a1aa527b9965a943ac16101a..0fe7dcfc0a79946ee8d675b6c44f57c114c5e4da 100644 --- a/clang/test/CodeGen/aarch64-sme-intrinsics/acle_sme_ld1_vnum.c +++ b/clang/test/CodeGen/aarch64-sme-intrinsics/acle_sme_ld1_vnum.c @@ -1,17 +1,11 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 3 // REQUIRES: aarch64-registered-target -// RUN: %clang_cc1 -DDISABLE_SME_ATTRIBUTES -triple aarch64-none-linux-gnu -target-feature +sme -target-feature +sve -S -O1 -Werror -emit-llvm -o - %s | FileCheck %s -check-prefixes=CHECK,CHECK-C -// RUN: %clang_cc1 -DDISABLE_SME_ATTRIBUTES -triple aarch64-none-linux-gnu -target-feature +sme -target-feature +sve -S -O1 -Werror -emit-llvm -o - -x c++ %s | FileCheck %s -check-prefixes=CHECK,CHECK-CXX -// RUN: %clang_cc1 -DDISABLE_SME_ATTRIBUTES -triple aarch64-none-linux-gnu -target-feature +sme -target-feature +sve -S -O1 -Werror -o /dev/null %s +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme -target-feature +sve -S -O1 -Werror -emit-llvm -o - %s | FileCheck %s -check-prefixes=CHECK,CHECK-C +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme -target-feature +sve -S -O1 -Werror -emit-llvm -o - -x c++ %s | FileCheck %s -check-prefixes=CHECK,CHECK-CXX +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme -target-feature +sve -S -O1 -Werror -o /dev/null %s #include -#ifdef DISABLE_SME_ATTRIBUTES -#define ARM_STREAMING_ATTR -#else -#define ARM_STREAMING_ATTR __attribute__((arm_streaming)) -#endif - // CHECK-C-LABEL: define dso_local void @test_svld1_hor_vnum_za8( // CHECK-C-SAME: i32 noundef [[SLICE_BASE:%.*]], [[PG:%.*]], ptr noundef [[PTR:%.*]], i64 noundef [[VNUM:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { // CHECK-C-NEXT: entry: @@ -34,7 +28,7 @@ // CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.ld1b.horiz( [[PG]], ptr [[TMP1]], i32 0, i32 [[ADD]]) // CHECK-CXX-NEXT: ret void // -ARM_STREAMING_ATTR void test_svld1_hor_vnum_za8(uint32_t slice_base, svbool_t pg, const void *ptr, int64_t vnum) { +void test_svld1_hor_vnum_za8(uint32_t slice_base, svbool_t pg, const void *ptr, int64_t vnum) __arm_streaming { svld1_hor_vnum_za8(0, slice_base, pg, ptr, vnum); svld1_hor_vnum_za8(0, slice_base + 15, pg, ptr, vnum); } @@ -63,7 +57,7 @@ ARM_STREAMING_ATTR void test_svld1_hor_vnum_za8(uint32_t slice_base, svbool_t pg // CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.ld1h.horiz( [[TMP0]], ptr [[TMP2]], i32 1, i32 [[ADD]]) // CHECK-CXX-NEXT: ret void // -ARM_STREAMING_ATTR void test_svld1_hor_vnum_za16(uint32_t slice_base, svbool_t pg, const void *ptr, int64_t vnum) { +void test_svld1_hor_vnum_za16(uint32_t slice_base, svbool_t pg, const void *ptr, int64_t vnum) __arm_streaming { svld1_hor_vnum_za16(0, slice_base, pg, ptr, vnum); svld1_hor_vnum_za16(1, slice_base + 7, pg, ptr, vnum); } @@ -92,7 +86,7 @@ ARM_STREAMING_ATTR void test_svld1_hor_vnum_za16(uint32_t slice_base, svbool_t p // CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.ld1w.horiz( [[TMP0]], ptr [[TMP2]], i32 3, i32 [[ADD]]) // CHECK-CXX-NEXT: ret void // -ARM_STREAMING_ATTR void test_svld1_hor_vnum_za32(uint32_t slice_base, svbool_t pg, const void *ptr, int64_t vnum) { +void test_svld1_hor_vnum_za32(uint32_t slice_base, svbool_t pg, const void *ptr, int64_t vnum) __arm_streaming { svld1_hor_vnum_za32(0, slice_base, pg, ptr, vnum); svld1_hor_vnum_za32(3, slice_base + 3, pg, ptr, vnum); } @@ -121,7 +115,7 @@ ARM_STREAMING_ATTR void test_svld1_hor_vnum_za32(uint32_t slice_base, svbool_t p // CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.ld1d.horiz( [[TMP0]], ptr [[TMP2]], i32 7, i32 [[ADD]]) // CHECK-CXX-NEXT: ret void // -ARM_STREAMING_ATTR void test_svld1_hor_vnum_za64(uint32_t slice_base, svbool_t pg, const void *ptr, int64_t vnum) { +void test_svld1_hor_vnum_za64(uint32_t slice_base, svbool_t pg, const void *ptr, int64_t vnum) __arm_streaming { svld1_hor_vnum_za64(0, slice_base, pg, ptr, vnum); svld1_hor_vnum_za64(7, slice_base + 1, pg, ptr, vnum); } @@ -148,7 +142,7 @@ ARM_STREAMING_ATTR void test_svld1_hor_vnum_za64(uint32_t slice_base, svbool_t p // CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.ld1q.horiz( [[TMP0]], ptr [[TMP2]], i32 15, i32 [[SLICE_BASE]]) // CHECK-CXX-NEXT: ret void // -ARM_STREAMING_ATTR void test_svld1_hor_vnum_za128(uint32_t slice_base, svbool_t pg, const void *ptr, int64_t vnum) { +void test_svld1_hor_vnum_za128(uint32_t slice_base, svbool_t pg, const void *ptr, int64_t vnum) __arm_streaming { svld1_hor_vnum_za128(0, slice_base, pg, ptr, vnum); svld1_hor_vnum_za128(15, slice_base, pg, ptr, vnum); } @@ -175,7 +169,7 @@ ARM_STREAMING_ATTR void test_svld1_hor_vnum_za128(uint32_t slice_base, svbool_t // CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.ld1b.vert( [[PG]], ptr [[TMP1]], i32 0, i32 [[ADD]]) // CHECK-CXX-NEXT: ret void // -ARM_STREAMING_ATTR void test_svld1_ver_hor_za8(uint32_t slice_base, svbool_t pg, const void *ptr, int64_t vnum) { +void test_svld1_ver_hor_za8(uint32_t slice_base, svbool_t pg, const void *ptr, int64_t vnum) __arm_streaming { svld1_ver_vnum_za8(0, slice_base, pg, ptr, vnum); svld1_ver_vnum_za8(0, slice_base + 15, pg, ptr, vnum); } @@ -204,7 +198,7 @@ ARM_STREAMING_ATTR void test_svld1_ver_hor_za8(uint32_t slice_base, svbool_t pg, // CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.ld1h.vert( [[TMP0]], ptr [[TMP2]], i32 1, i32 [[ADD]]) // CHECK-CXX-NEXT: ret void // -ARM_STREAMING_ATTR void test_svld1_ver_vnum_za16(uint32_t slice_base, svbool_t pg, const void *ptr, int64_t vnum) { +void test_svld1_ver_vnum_za16(uint32_t slice_base, svbool_t pg, const void *ptr, int64_t vnum) __arm_streaming { svld1_ver_vnum_za16(0, slice_base, pg, ptr, vnum); svld1_ver_vnum_za16(1, slice_base + 7, pg, ptr, vnum); } @@ -233,7 +227,7 @@ ARM_STREAMING_ATTR void test_svld1_ver_vnum_za16(uint32_t slice_base, svbool_t p // CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.ld1w.vert( [[TMP0]], ptr [[TMP2]], i32 3, i32 [[ADD]]) // CHECK-CXX-NEXT: ret void // -ARM_STREAMING_ATTR void test_svld1_ver_vnum_za32(uint32_t slice_base, svbool_t pg, const void *ptr, int64_t vnum) { +void test_svld1_ver_vnum_za32(uint32_t slice_base, svbool_t pg, const void *ptr, int64_t vnum) __arm_streaming { svld1_ver_vnum_za32(0, slice_base, pg, ptr, vnum); svld1_ver_vnum_za32(3, slice_base + 3, pg, ptr, vnum); } @@ -262,7 +256,7 @@ ARM_STREAMING_ATTR void test_svld1_ver_vnum_za32(uint32_t slice_base, svbool_t p // CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.ld1d.vert( [[TMP0]], ptr [[TMP2]], i32 7, i32 [[ADD]]) // CHECK-CXX-NEXT: ret void // -ARM_STREAMING_ATTR void test_svld1_ver_vnum_za64(uint32_t slice_base, svbool_t pg, const void *ptr, int64_t vnum) { +void test_svld1_ver_vnum_za64(uint32_t slice_base, svbool_t pg, const void *ptr, int64_t vnum) __arm_streaming { svld1_ver_vnum_za64(0, slice_base, pg, ptr, vnum); svld1_ver_vnum_za64(7, slice_base + 1, pg, ptr, vnum); } @@ -289,7 +283,7 @@ ARM_STREAMING_ATTR void test_svld1_ver_vnum_za64(uint32_t slice_base, svbool_t p // CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.ld1q.vert( [[TMP0]], ptr [[TMP2]], i32 15, i32 [[SLICE_BASE]]) // CHECK-CXX-NEXT: ret void // -ARM_STREAMING_ATTR void test_svld1_ver_vnum_za128(uint32_t slice_base, svbool_t pg, const void *ptr, int64_t vnum) { +void test_svld1_ver_vnum_za128(uint32_t slice_base, svbool_t pg, const void *ptr, int64_t vnum) __arm_streaming { svld1_ver_vnum_za128(0, slice_base, pg, ptr, vnum); svld1_ver_vnum_za128(15, slice_base, pg, ptr, vnum); } diff --git a/clang/test/CodeGen/aarch64-sme-intrinsics/acle_sme_st1.c b/clang/test/CodeGen/aarch64-sme-intrinsics/acle_sme_st1.c index 9ea5fa10c1bbc7b0486152ba84d1b379765125f7..9ed158aedf7e3b319c7e5884285d33bddc27314d 100644 --- a/clang/test/CodeGen/aarch64-sme-intrinsics/acle_sme_st1.c +++ b/clang/test/CodeGen/aarch64-sme-intrinsics/acle_sme_st1.c @@ -1,17 +1,11 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 3 // REQUIRES: aarch64-registered-target -// RUN: %clang_cc1 -DDISABLE_SME_ATTRIBUTES -triple aarch64-none-linux-gnu -target-feature +sme -target-feature +sve -S -O1 -Werror -emit-llvm -o - %s | FileCheck %s -check-prefixes=CHECK,CHECK-C -// RUN: %clang_cc1 -DDISABLE_SME_ATTRIBUTES -triple aarch64-none-linux-gnu -target-feature +sme -target-feature +sve -S -O1 -Werror -emit-llvm -o - -x c++ %s | FileCheck %s -check-prefixes=CHECK,CHECK-CXX -// RUN: %clang_cc1 -DDISABLE_SME_ATTRIBUTES -triple aarch64-none-linux-gnu -target-feature +sme -target-feature +sve -S -O1 -Werror -o /dev/null %s +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme -target-feature +sve -S -O1 -Werror -emit-llvm -o - %s | FileCheck %s -check-prefixes=CHECK,CHECK-C +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme -target-feature +sve -S -O1 -Werror -emit-llvm -o - -x c++ %s | FileCheck %s -check-prefixes=CHECK,CHECK-CXX +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme -target-feature +sve -S -O1 -Werror -o /dev/null %s #include -#ifdef DISABLE_SME_ATTRIBUTES -#define ARM_STREAMING_ATTR -#else -#define ARM_STREAMING_ATTR __attribute__((arm_streaming)) -#endif - // CHECK-C-LABEL: define dso_local void @test_svst1_hor_za8( // CHECK-C-SAME: i32 noundef [[SLICE_BASE:%.*]], [[PG:%.*]], ptr noundef [[PTR:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { // CHECK-C-NEXT: entry: @@ -28,7 +22,7 @@ // CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.st1b.horiz( [[PG]], ptr [[PTR]], i32 0, i32 [[ADD]]) // CHECK-CXX-NEXT: ret void // -ARM_STREAMING_ATTR void test_svst1_hor_za8(uint32_t slice_base, svbool_t pg, void *ptr) { +void test_svst1_hor_za8(uint32_t slice_base, svbool_t pg, void *ptr) __arm_streaming { svst1_hor_za8(0, slice_base, pg, ptr); svst1_hor_za8(0, slice_base + 15, pg, ptr); } @@ -51,7 +45,7 @@ ARM_STREAMING_ATTR void test_svst1_hor_za8(uint32_t slice_base, svbool_t pg, voi // CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.st1h.horiz( [[TMP0]], ptr [[PTR]], i32 1, i32 [[ADD]]) // CHECK-CXX-NEXT: ret void // -ARM_STREAMING_ATTR void test_svst1_hor_za16(uint32_t slice_base, svbool_t pg, void *ptr) { +void test_svst1_hor_za16(uint32_t slice_base, svbool_t pg, void *ptr) __arm_streaming { svst1_hor_za16(0, slice_base, pg, ptr); svst1_hor_za16(1, slice_base + 7, pg, ptr); } @@ -74,7 +68,7 @@ ARM_STREAMING_ATTR void test_svst1_hor_za16(uint32_t slice_base, svbool_t pg, vo // CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.st1w.horiz( [[TMP0]], ptr [[PTR]], i32 3, i32 [[ADD]]) // CHECK-CXX-NEXT: ret void // -ARM_STREAMING_ATTR void test_svst1_hor_za32(uint32_t slice_base, svbool_t pg, void *ptr) { +void test_svst1_hor_za32(uint32_t slice_base, svbool_t pg, void *ptr) __arm_streaming { svst1_hor_za32(0, slice_base, pg, ptr); svst1_hor_za32(3, slice_base + 3, pg, ptr); } @@ -97,7 +91,7 @@ ARM_STREAMING_ATTR void test_svst1_hor_za32(uint32_t slice_base, svbool_t pg, vo // CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.st1d.horiz( [[TMP0]], ptr [[PTR]], i32 7, i32 [[ADD]]) // CHECK-CXX-NEXT: ret void // -ARM_STREAMING_ATTR void test_svst1_hor_za64(uint32_t slice_base, svbool_t pg, void *ptr) { +void test_svst1_hor_za64(uint32_t slice_base, svbool_t pg, void *ptr) __arm_streaming { svst1_hor_za64(0, slice_base, pg, ptr); svst1_hor_za64(7, slice_base + 1, pg, ptr); } @@ -118,7 +112,7 @@ ARM_STREAMING_ATTR void test_svst1_hor_za64(uint32_t slice_base, svbool_t pg, vo // CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.st1q.horiz( [[TMP0]], ptr [[PTR]], i32 15, i32 [[SLICE_BASE]]) // CHECK-CXX-NEXT: ret void // -ARM_STREAMING_ATTR void test_svst1_hor_za128(uint32_t slice_base, svbool_t pg, void *ptr) { +void test_svst1_hor_za128(uint32_t slice_base, svbool_t pg, void *ptr) __arm_streaming { svst1_hor_za128(0, slice_base, pg, ptr); svst1_hor_za128(15, slice_base, pg, ptr); } @@ -139,7 +133,7 @@ ARM_STREAMING_ATTR void test_svst1_hor_za128(uint32_t slice_base, svbool_t pg, v // CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.st1b.vert( [[PG]], ptr [[PTR]], i32 0, i32 [[ADD]]) // CHECK-CXX-NEXT: ret void // -ARM_STREAMING_ATTR void test_svst1_ver_za8(uint32_t slice_base, svbool_t pg, void *ptr) { +void test_svst1_ver_za8(uint32_t slice_base, svbool_t pg, void *ptr) __arm_streaming { svst1_ver_za8(0, slice_base, pg, ptr); svst1_ver_za8(0, slice_base + 15, pg, ptr); } @@ -162,7 +156,7 @@ ARM_STREAMING_ATTR void test_svst1_ver_za8(uint32_t slice_base, svbool_t pg, voi // CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.st1h.vert( [[TMP0]], ptr [[PTR]], i32 1, i32 [[ADD]]) // CHECK-CXX-NEXT: ret void // -ARM_STREAMING_ATTR void test_svst1_ver_za16(uint32_t slice_base, svbool_t pg, void *ptr) { +void test_svst1_ver_za16(uint32_t slice_base, svbool_t pg, void *ptr) __arm_streaming { svst1_ver_za16(0, slice_base, pg, ptr); svst1_ver_za16(1, slice_base + 7, pg, ptr); } @@ -185,7 +179,7 @@ ARM_STREAMING_ATTR void test_svst1_ver_za16(uint32_t slice_base, svbool_t pg, vo // CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.st1w.vert( [[TMP0]], ptr [[PTR]], i32 3, i32 [[ADD]]) // CHECK-CXX-NEXT: ret void // -ARM_STREAMING_ATTR void test_svst1_ver_za32(uint32_t slice_base, svbool_t pg, void *ptr) { +void test_svst1_ver_za32(uint32_t slice_base, svbool_t pg, void *ptr) __arm_streaming { svst1_ver_za32(0, slice_base, pg, ptr); svst1_ver_za32(3, slice_base + 3, pg, ptr); } @@ -208,7 +202,7 @@ ARM_STREAMING_ATTR void test_svst1_ver_za32(uint32_t slice_base, svbool_t pg, vo // CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.st1d.vert( [[TMP0]], ptr [[PTR]], i32 7, i32 [[ADD]]) // CHECK-CXX-NEXT: ret void // -ARM_STREAMING_ATTR void test_svst1_ver_za64(uint32_t slice_base, svbool_t pg, void *ptr) { +void test_svst1_ver_za64(uint32_t slice_base, svbool_t pg, void *ptr) __arm_streaming { svst1_ver_za64(0, slice_base, pg, ptr); svst1_ver_za64(7, slice_base + 1, pg, ptr); } @@ -229,7 +223,7 @@ ARM_STREAMING_ATTR void test_svst1_ver_za64(uint32_t slice_base, svbool_t pg, vo // CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.st1q.vert( [[TMP0]], ptr [[PTR]], i32 15, i32 [[SLICE_BASE]]) // CHECK-CXX-NEXT: ret void // -ARM_STREAMING_ATTR void test_svst1_ver_za128(uint32_t slice_base, svbool_t pg, void *ptr) { +void test_svst1_ver_za128(uint32_t slice_base, svbool_t pg, void *ptr) __arm_streaming { svst1_ver_za128(0, slice_base, pg, ptr); svst1_ver_za128(15, slice_base, pg, ptr); } diff --git a/clang/test/CodeGen/aarch64-sme-intrinsics/acle_sme_st1_vnum.c b/clang/test/CodeGen/aarch64-sme-intrinsics/acle_sme_st1_vnum.c index 6b534f25a1f8db8a9a62be76017f637786637e52..627098d9365bd43821ade095f07cb7656af5a1bf 100644 --- a/clang/test/CodeGen/aarch64-sme-intrinsics/acle_sme_st1_vnum.c +++ b/clang/test/CodeGen/aarch64-sme-intrinsics/acle_sme_st1_vnum.c @@ -1,17 +1,11 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 3 // REQUIRES: aarch64-registered-target -// RUN: %clang_cc1 -DDISABLE_SME_ATTRIBUTES -triple aarch64-none-linux-gnu -target-feature +sme -target-feature +sve -S -O1 -Werror -emit-llvm -o - %s | FileCheck %s -check-prefixes=CHECK,CHECK-C -// RUN: %clang_cc1 -DDISABLE_SME_ATTRIBUTES -triple aarch64-none-linux-gnu -target-feature +sme -target-feature +sve -S -O1 -Werror -emit-llvm -o - -x c++ %s | FileCheck %s -check-prefixes=CHECK,CHECK-CXX -// RUN: %clang_cc1 -DDISABLE_SME_ATTRIBUTES -triple aarch64-none-linux-gnu -target-feature +sme -target-feature +sve -S -O1 -Werror -o /dev/null %s +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme -target-feature +sve -S -O1 -Werror -emit-llvm -o - %s | FileCheck %s -check-prefixes=CHECK,CHECK-C +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme -target-feature +sve -S -O1 -Werror -emit-llvm -o - -x c++ %s | FileCheck %s -check-prefixes=CHECK,CHECK-CXX +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme -target-feature +sve -S -O1 -Werror -o /dev/null %s #include -#ifdef DISABLE_SME_ATTRIBUTES -#define ARM_STREAMING_ATTR -#else -#define ARM_STREAMING_ATTR __attribute__((arm_streaming)) -#endif - // CHECK-C-LABEL: define dso_local void @test_svst1_hor_vnum_za8( // CHECK-C-SAME: i32 noundef [[SLICE_BASE:%.*]], [[PG:%.*]], ptr noundef [[PTR:%.*]], i64 noundef [[VNUM:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { // CHECK-C-NEXT: entry: @@ -34,7 +28,7 @@ // CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.st1b.horiz( [[PG]], ptr [[TMP1]], i32 0, i32 [[ADD]]) // CHECK-CXX-NEXT: ret void // -ARM_STREAMING_ATTR void test_svst1_hor_vnum_za8(uint32_t slice_base, svbool_t pg, void *ptr, int64_t vnum) { +void test_svst1_hor_vnum_za8(uint32_t slice_base, svbool_t pg, void *ptr, int64_t vnum) __arm_streaming { svst1_hor_vnum_za8(0, slice_base, pg, ptr, vnum); svst1_hor_vnum_za8(0, slice_base + 15, pg, ptr, vnum); } @@ -63,7 +57,7 @@ ARM_STREAMING_ATTR void test_svst1_hor_vnum_za8(uint32_t slice_base, svbool_t pg // CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.st1h.horiz( [[TMP0]], ptr [[TMP2]], i32 1, i32 [[ADD]]) // CHECK-CXX-NEXT: ret void // -ARM_STREAMING_ATTR void test_svst1_hor_vnum_za16(uint32_t slice_base, svbool_t pg, void *ptr, int64_t vnum) { +void test_svst1_hor_vnum_za16(uint32_t slice_base, svbool_t pg, void *ptr, int64_t vnum) __arm_streaming { svst1_hor_vnum_za16(0, slice_base, pg, ptr, vnum); svst1_hor_vnum_za16(1, slice_base + 7, pg, ptr, vnum); } @@ -92,7 +86,7 @@ ARM_STREAMING_ATTR void test_svst1_hor_vnum_za16(uint32_t slice_base, svbool_t p // CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.st1w.horiz( [[TMP0]], ptr [[TMP2]], i32 3, i32 [[ADD]]) // CHECK-CXX-NEXT: ret void // -ARM_STREAMING_ATTR void test_svst1_hor_vnum_za32(uint32_t slice_base, svbool_t pg, void *ptr, int64_t vnum) { +void test_svst1_hor_vnum_za32(uint32_t slice_base, svbool_t pg, void *ptr, int64_t vnum) __arm_streaming { svst1_hor_vnum_za32(0, slice_base, pg, ptr, vnum); svst1_hor_vnum_za32(3, slice_base + 3, pg, ptr, vnum); } @@ -121,7 +115,7 @@ ARM_STREAMING_ATTR void test_svst1_hor_vnum_za32(uint32_t slice_base, svbool_t p // CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.st1d.horiz( [[TMP0]], ptr [[TMP2]], i32 7, i32 [[ADD]]) // CHECK-CXX-NEXT: ret void // -ARM_STREAMING_ATTR void test_svst1_hor_vnum_za64(uint32_t slice_base, svbool_t pg, void *ptr, int64_t vnum) { +void test_svst1_hor_vnum_za64(uint32_t slice_base, svbool_t pg, void *ptr, int64_t vnum) __arm_streaming { svst1_hor_vnum_za64(0, slice_base, pg, ptr, vnum); svst1_hor_vnum_za64(7, slice_base + 1, pg, ptr, vnum); } @@ -148,7 +142,7 @@ ARM_STREAMING_ATTR void test_svst1_hor_vnum_za64(uint32_t slice_base, svbool_t p // CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.st1q.horiz( [[TMP0]], ptr [[TMP2]], i32 15, i32 [[SLICE_BASE]]) // CHECK-CXX-NEXT: ret void // -ARM_STREAMING_ATTR void test_svst1_hor_vnum_za128(uint32_t slice_base, svbool_t pg, void *ptr, int64_t vnum) { +void test_svst1_hor_vnum_za128(uint32_t slice_base, svbool_t pg, void *ptr, int64_t vnum) __arm_streaming { svst1_hor_vnum_za128(0, slice_base, pg, ptr, vnum); svst1_hor_vnum_za128(15, slice_base, pg, ptr, vnum); } @@ -175,7 +169,7 @@ ARM_STREAMING_ATTR void test_svst1_hor_vnum_za128(uint32_t slice_base, svbool_t // CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.st1b.vert( [[PG]], ptr [[TMP1]], i32 0, i32 [[ADD]]) // CHECK-CXX-NEXT: ret void // -ARM_STREAMING_ATTR void test_svst1_ver_vnum_za8(uint32_t slice_base, svbool_t pg, void *ptr, int64_t vnum) { +void test_svst1_ver_vnum_za8(uint32_t slice_base, svbool_t pg, void *ptr, int64_t vnum) __arm_streaming { svst1_ver_vnum_za8(0, slice_base, pg, ptr, vnum); svst1_ver_vnum_za8(0, slice_base + 15, pg, ptr, vnum); } @@ -204,7 +198,7 @@ ARM_STREAMING_ATTR void test_svst1_ver_vnum_za8(uint32_t slice_base, svbool_t pg // CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.st1h.vert( [[TMP0]], ptr [[TMP2]], i32 1, i32 [[ADD]]) // CHECK-CXX-NEXT: ret void // -ARM_STREAMING_ATTR void test_svst1_ver_vnum_za16(uint32_t slice_base, svbool_t pg, void *ptr, int64_t vnum) { +void test_svst1_ver_vnum_za16(uint32_t slice_base, svbool_t pg, void *ptr, int64_t vnum) __arm_streaming { svst1_ver_vnum_za16(0, slice_base, pg, ptr, vnum); svst1_ver_vnum_za16(1, slice_base + 7, pg, ptr, vnum); } @@ -233,7 +227,7 @@ ARM_STREAMING_ATTR void test_svst1_ver_vnum_za16(uint32_t slice_base, svbool_t p // CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.st1w.vert( [[TMP0]], ptr [[TMP2]], i32 3, i32 [[ADD]]) // CHECK-CXX-NEXT: ret void // -ARM_STREAMING_ATTR void test_svst1_ver_vnum_za32(uint32_t slice_base, svbool_t pg, void *ptr, int64_t vnum) { +void test_svst1_ver_vnum_za32(uint32_t slice_base, svbool_t pg, void *ptr, int64_t vnum) __arm_streaming { svst1_ver_vnum_za32(0, slice_base, pg, ptr, vnum); svst1_ver_vnum_za32(3, slice_base + 3, pg, ptr, vnum); } @@ -262,7 +256,7 @@ ARM_STREAMING_ATTR void test_svst1_ver_vnum_za32(uint32_t slice_base, svbool_t p // CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.st1d.vert( [[TMP0]], ptr [[TMP2]], i32 7, i32 [[ADD]]) // CHECK-CXX-NEXT: ret void // -ARM_STREAMING_ATTR void test_svst1_ver_vnum_za64(uint32_t slice_base, svbool_t pg, void *ptr, int64_t vnum) { +void test_svst1_ver_vnum_za64(uint32_t slice_base, svbool_t pg, void *ptr, int64_t vnum) __arm_streaming { svst1_ver_vnum_za64(0, slice_base, pg, ptr, vnum); svst1_ver_vnum_za64(7, slice_base + 1, pg, ptr, vnum); } @@ -289,7 +283,7 @@ ARM_STREAMING_ATTR void test_svst1_ver_vnum_za64(uint32_t slice_base, svbool_t p // CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.st1q.vert( [[TMP0]], ptr [[TMP2]], i32 15, i32 [[SLICE_BASE]]) // CHECK-CXX-NEXT: ret void // -ARM_STREAMING_ATTR void test_svst1_ver_vnum_za128(uint32_t slice_base, svbool_t pg, void *ptr, int64_t vnum) { +void test_svst1_ver_vnum_za128(uint32_t slice_base, svbool_t pg, void *ptr, int64_t vnum) __arm_streaming { svst1_ver_vnum_za128(0, slice_base, pg, ptr, vnum); svst1_ver_vnum_za128(15, slice_base, pg, ptr, vnum); } diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_cvt.c b/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_cvt.c new file mode 100644 index 0000000000000000000000000000000000000000..a3ee7d2092f79f4aa27d00e311456bc214b9a37e --- /dev/null +++ b/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_cvt.c @@ -0,0 +1,499 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py + +// REQUIRES: aarch64-registered-target + +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +sme2 -target-feature +bf16 -S -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +sme2 -target-feature +bf16 -S -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK +// RUN: %clang_cc1 -D__SVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +sme2 -target-feature +bf16 -S -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s +// RUN: %clang_cc1 -D__SVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +sme2 -target-feature +bf16 -S -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +sme2 -target-feature +bf16 -S -disable-O0-optnone -Werror -Wall -o /dev/null %s + +#include + +#ifdef SVE_OVERLOADED_FORMS +// A simple used,unused... macro, long enough to represent any SVE builtin. +#define SVE_ACLE_FUNC(A1,A2_UNUSED,A3,A4_UNUSED) A1##A3 +#else +#define SVE_ACLE_FUNC(A1,A2,A3,A4) A1##A2##A3##A4 +#endif + +// CHECK-LABEL: @test_cvt_f16_x2( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4f32.nxv8f32( [[ZN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4f32.nxv8f32( [[ZN]], i64 4) +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.aarch64.sve.fcvt.x2.nxv4f32( [[TMP0]], [[TMP1]]) +// CHECK-NEXT: ret [[TMP2]] +// +// CPP-CHECK-LABEL: @_Z15test_cvt_f16_x213svfloat32x2_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4f32.nxv8f32( [[ZN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4f32.nxv8f32( [[ZN]], i64 4) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.aarch64.sve.fcvt.x2.nxv4f32( [[TMP0]], [[TMP1]]) +// CPP-CHECK-NEXT: ret [[TMP2]] +// +svfloat16_t test_cvt_f16_x2(svfloat32x2_t zn) __arm_streaming { + return SVE_ACLE_FUNC(svcvt_f16,_f32_x2,,)(zn); +} + +// CHECK-LABEL: @test_cvt_bf16_x2( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4f32.nxv8f32( [[ZN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4f32.nxv8f32( [[ZN]], i64 4) +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.aarch64.sve.bfcvt.x2( [[TMP0]], [[TMP1]]) +// CHECK-NEXT: ret [[TMP2]] +// +// CPP-CHECK-LABEL: @_Z16test_cvt_bf16_x213svfloat32x2_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4f32.nxv8f32( [[ZN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4f32.nxv8f32( [[ZN]], i64 4) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.aarch64.sve.bfcvt.x2( [[TMP0]], [[TMP1]]) +// CPP-CHECK-NEXT: ret [[TMP2]] +// +svbfloat16_t test_cvt_bf16_x2(svfloat32x2_t zn) __arm_streaming { + return SVE_ACLE_FUNC(svcvt_bf16,_f32_x2,,)(zn); +} + + +// x2 +// CHECK-LABEL: @test_svcvt_f32_u32_x2( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv8i32( [[ZN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv8i32( [[ZN]], i64 4) +// CHECK-NEXT: [[TMP2:%.*]] = tail call { , } @llvm.aarch64.sve.fcvtu.x2.nxv4f32( [[TMP0]], [[TMP1]]) +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP2]], 0 +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv8f32.nxv4f32( poison, [[TMP3]], i64 0) +// CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , } [[TMP2]], 1 +// CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv8f32.nxv4f32( [[TMP4]], [[TMP5]], i64 4) +// CHECK-NEXT: ret [[TMP6]] +// +// CPP-CHECK-LABEL: @_Z21test_svcvt_f32_u32_x212svuint32x2_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv8i32( [[ZN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv8i32( [[ZN]], i64 4) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call { , } @llvm.aarch64.sve.fcvtu.x2.nxv4f32( [[TMP0]], [[TMP1]]) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP2]], 0 +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv8f32.nxv4f32( poison, [[TMP3]], i64 0) +// CPP-CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , } [[TMP2]], 1 +// CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv8f32.nxv4f32( [[TMP4]], [[TMP5]], i64 4) +// CPP-CHECK-NEXT: ret [[TMP6]] +// +svfloat32x2_t test_svcvt_f32_u32_x2(svuint32x2_t zn) __arm_streaming { + return SVE_ACLE_FUNC(svcvt_f32,_u32_x2,,)(zn); +} + +// CHECK-LABEL: @test_svcvt_f32_s32_x2( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv8i32( [[ZN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv8i32( [[ZN]], i64 4) +// CHECK-NEXT: [[TMP2:%.*]] = tail call { , } @llvm.aarch64.sve.fcvts.x2.nxv4f32( [[TMP0]], [[TMP1]]) +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP2]], 0 +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv8f32.nxv4f32( poison, [[TMP3]], i64 0) +// CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , } [[TMP2]], 1 +// CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv8f32.nxv4f32( [[TMP4]], [[TMP5]], i64 4) +// CHECK-NEXT: ret [[TMP6]] +// +// CPP-CHECK-LABEL: @_Z21test_svcvt_f32_s32_x211svint32x2_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv8i32( [[ZN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv8i32( [[ZN]], i64 4) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call { , } @llvm.aarch64.sve.fcvts.x2.nxv4f32( [[TMP0]], [[TMP1]]) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP2]], 0 +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv8f32.nxv4f32( poison, [[TMP3]], i64 0) +// CPP-CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , } [[TMP2]], 1 +// CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv8f32.nxv4f32( [[TMP4]], [[TMP5]], i64 4) +// CPP-CHECK-NEXT: ret [[TMP6]] +// +svfloat32x2_t test_svcvt_f32_s32_x2(svint32x2_t zn) __arm_streaming { + return SVE_ACLE_FUNC(svcvt_f32,_s32_x2,,)(zn); +} + +// CHECK-LABEL: @test_svcvt_u32_f32_x2( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4f32.nxv8f32( [[ZN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4f32.nxv8f32( [[ZN]], i64 4) +// CHECK-NEXT: [[TMP2:%.*]] = tail call { , } @llvm.aarch64.sve.ucvtf.x2.nxv4f32( [[TMP0]], [[TMP1]]) +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP2]], 0 +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv8i32.nxv4i32( poison, [[TMP3]], i64 0) +// CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , } [[TMP2]], 1 +// CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv8i32.nxv4i32( [[TMP4]], [[TMP5]], i64 4) +// CHECK-NEXT: ret [[TMP6]] +// +// CPP-CHECK-LABEL: @_Z21test_svcvt_u32_f32_x213svfloat32x2_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4f32.nxv8f32( [[ZN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4f32.nxv8f32( [[ZN]], i64 4) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call { , } @llvm.aarch64.sve.ucvtf.x2.nxv4f32( [[TMP0]], [[TMP1]]) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP2]], 0 +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv8i32.nxv4i32( poison, [[TMP3]], i64 0) +// CPP-CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , } [[TMP2]], 1 +// CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv8i32.nxv4i32( [[TMP4]], [[TMP5]], i64 4) +// CPP-CHECK-NEXT: ret [[TMP6]] +// +svuint32x2_t test_svcvt_u32_f32_x2(svfloat32x2_t zn) __arm_streaming { + return SVE_ACLE_FUNC(svcvt_u32,_f32_x2,,)(zn); +} + +// CHECK-LABEL: @test_svcvt_s32_f32_x2( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4f32.nxv8f32( [[ZN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4f32.nxv8f32( [[ZN]], i64 4) +// CHECK-NEXT: [[TMP2:%.*]] = tail call { , } @llvm.aarch64.sve.scvtf.x2.nxv4f32( [[TMP0]], [[TMP1]]) +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP2]], 0 +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv8i32.nxv4i32( poison, [[TMP3]], i64 0) +// CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , } [[TMP2]], 1 +// CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv8i32.nxv4i32( [[TMP4]], [[TMP5]], i64 4) +// CHECK-NEXT: ret [[TMP6]] +// +// CPP-CHECK-LABEL: @_Z21test_svcvt_s32_f32_x213svfloat32x2_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4f32.nxv8f32( [[ZN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4f32.nxv8f32( [[ZN]], i64 4) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call { , } @llvm.aarch64.sve.scvtf.x2.nxv4f32( [[TMP0]], [[TMP1]]) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP2]], 0 +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv8i32.nxv4i32( poison, [[TMP3]], i64 0) +// CPP-CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , } [[TMP2]], 1 +// CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv8i32.nxv4i32( [[TMP4]], [[TMP5]], i64 4) +// CPP-CHECK-NEXT: ret [[TMP6]] +// +svint32x2_t test_svcvt_s32_f32_x2(svfloat32x2_t zn) __arm_streaming { + return SVE_ACLE_FUNC(svcvt_s32,_f32_x2,,)(zn); +} + +// x4 +// CHECK-LABEL: @test_svcvt_f32_u32_x4( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 4) +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 8) +// CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 12) +// CHECK-NEXT: [[TMP4:%.*]] = tail call { , , , } @llvm.aarch64.sve.fcvtu.x4.nxv4f32( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) +// CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP4]], 0 +// CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv16f32.nxv4f32( poison, [[TMP5]], i64 0) +// CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP4]], 1 +// CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv16f32.nxv4f32( [[TMP6]], [[TMP7]], i64 4) +// CHECK-NEXT: [[TMP9:%.*]] = extractvalue { , , , } [[TMP4]], 2 +// CHECK-NEXT: [[TMP10:%.*]] = tail call @llvm.vector.insert.nxv16f32.nxv4f32( [[TMP8]], [[TMP9]], i64 8) +// CHECK-NEXT: [[TMP11:%.*]] = extractvalue { , , , } [[TMP4]], 3 +// CHECK-NEXT: [[TMP12:%.*]] = tail call @llvm.vector.insert.nxv16f32.nxv4f32( [[TMP10]], [[TMP11]], i64 12) +// CHECK-NEXT: ret [[TMP12]] +// +// CPP-CHECK-LABEL: @_Z21test_svcvt_f32_u32_x412svuint32x4_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 4) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 8) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 12) +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call { , , , } @llvm.aarch64.sve.fcvtu.x4.nxv4f32( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) +// CPP-CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP4]], 0 +// CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv16f32.nxv4f32( poison, [[TMP5]], i64 0) +// CPP-CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP4]], 1 +// CPP-CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv16f32.nxv4f32( [[TMP6]], [[TMP7]], i64 4) +// CPP-CHECK-NEXT: [[TMP9:%.*]] = extractvalue { , , , } [[TMP4]], 2 +// CPP-CHECK-NEXT: [[TMP10:%.*]] = tail call @llvm.vector.insert.nxv16f32.nxv4f32( [[TMP8]], [[TMP9]], i64 8) +// CPP-CHECK-NEXT: [[TMP11:%.*]] = extractvalue { , , , } [[TMP4]], 3 +// CPP-CHECK-NEXT: [[TMP12:%.*]] = tail call @llvm.vector.insert.nxv16f32.nxv4f32( [[TMP10]], [[TMP11]], i64 12) +// CPP-CHECK-NEXT: ret [[TMP12]] +// +svfloat32x4_t test_svcvt_f32_u32_x4(svuint32x4_t zn) __arm_streaming { + return SVE_ACLE_FUNC(svcvt_f32,_u32_x4,,)(zn); +} + +// CHECK-LABEL: @test_svcvt_f32_s32_x4( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 4) +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 8) +// CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 12) +// CHECK-NEXT: [[TMP4:%.*]] = tail call { , , , } @llvm.aarch64.sve.fcvts.x4.nxv4f32( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) +// CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP4]], 0 +// CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv16f32.nxv4f32( poison, [[TMP5]], i64 0) +// CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP4]], 1 +// CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv16f32.nxv4f32( [[TMP6]], [[TMP7]], i64 4) +// CHECK-NEXT: [[TMP9:%.*]] = extractvalue { , , , } [[TMP4]], 2 +// CHECK-NEXT: [[TMP10:%.*]] = tail call @llvm.vector.insert.nxv16f32.nxv4f32( [[TMP8]], [[TMP9]], i64 8) +// CHECK-NEXT: [[TMP11:%.*]] = extractvalue { , , , } [[TMP4]], 3 +// CHECK-NEXT: [[TMP12:%.*]] = tail call @llvm.vector.insert.nxv16f32.nxv4f32( [[TMP10]], [[TMP11]], i64 12) +// CHECK-NEXT: ret [[TMP12]] +// +// CPP-CHECK-LABEL: @_Z21test_svcvt_f32_s32_x411svint32x4_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 4) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 8) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 12) +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call { , , , } @llvm.aarch64.sve.fcvts.x4.nxv4f32( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) +// CPP-CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP4]], 0 +// CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv16f32.nxv4f32( poison, [[TMP5]], i64 0) +// CPP-CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP4]], 1 +// CPP-CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv16f32.nxv4f32( [[TMP6]], [[TMP7]], i64 4) +// CPP-CHECK-NEXT: [[TMP9:%.*]] = extractvalue { , , , } [[TMP4]], 2 +// CPP-CHECK-NEXT: [[TMP10:%.*]] = tail call @llvm.vector.insert.nxv16f32.nxv4f32( [[TMP8]], [[TMP9]], i64 8) +// CPP-CHECK-NEXT: [[TMP11:%.*]] = extractvalue { , , , } [[TMP4]], 3 +// CPP-CHECK-NEXT: [[TMP12:%.*]] = tail call @llvm.vector.insert.nxv16f32.nxv4f32( [[TMP10]], [[TMP11]], i64 12) +// CPP-CHECK-NEXT: ret [[TMP12]] +// +svfloat32x4_t test_svcvt_f32_s32_x4(svint32x4_t zn) __arm_streaming { + return SVE_ACLE_FUNC(svcvt_f32,_s32_x4,,)(zn); +} + +// CHECK-LABEL: @test_svcvt_u32_f32_x4( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4f32.nxv16f32( [[ZN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4f32.nxv16f32( [[ZN]], i64 4) +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv4f32.nxv16f32( [[ZN]], i64 8) +// CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv4f32.nxv16f32( [[ZN]], i64 12) +// CHECK-NEXT: [[TMP4:%.*]] = tail call { , , , } @llvm.aarch64.sve.ucvtf.x4.nxv4f32( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) +// CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP4]], 0 +// CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv16i32.nxv4i32( poison, [[TMP5]], i64 0) +// CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP4]], 1 +// CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv16i32.nxv4i32( [[TMP6]], [[TMP7]], i64 4) +// CHECK-NEXT: [[TMP9:%.*]] = extractvalue { , , , } [[TMP4]], 2 +// CHECK-NEXT: [[TMP10:%.*]] = tail call @llvm.vector.insert.nxv16i32.nxv4i32( [[TMP8]], [[TMP9]], i64 8) +// CHECK-NEXT: [[TMP11:%.*]] = extractvalue { , , , } [[TMP4]], 3 +// CHECK-NEXT: [[TMP12:%.*]] = tail call @llvm.vector.insert.nxv16i32.nxv4i32( [[TMP10]], [[TMP11]], i64 12) +// CHECK-NEXT: ret [[TMP12]] +// +// CPP-CHECK-LABEL: @_Z21test_svcvt_u32_f32_x413svfloat32x4_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4f32.nxv16f32( [[ZN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4f32.nxv16f32( [[ZN]], i64 4) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv4f32.nxv16f32( [[ZN]], i64 8) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv4f32.nxv16f32( [[ZN]], i64 12) +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call { , , , } @llvm.aarch64.sve.ucvtf.x4.nxv4f32( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) +// CPP-CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP4]], 0 +// CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv16i32.nxv4i32( poison, [[TMP5]], i64 0) +// CPP-CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP4]], 1 +// CPP-CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv16i32.nxv4i32( [[TMP6]], [[TMP7]], i64 4) +// CPP-CHECK-NEXT: [[TMP9:%.*]] = extractvalue { , , , } [[TMP4]], 2 +// CPP-CHECK-NEXT: [[TMP10:%.*]] = tail call @llvm.vector.insert.nxv16i32.nxv4i32( [[TMP8]], [[TMP9]], i64 8) +// CPP-CHECK-NEXT: [[TMP11:%.*]] = extractvalue { , , , } [[TMP4]], 3 +// CPP-CHECK-NEXT: [[TMP12:%.*]] = tail call @llvm.vector.insert.nxv16i32.nxv4i32( [[TMP10]], [[TMP11]], i64 12) +// CPP-CHECK-NEXT: ret [[TMP12]] +// +svuint32x4_t test_svcvt_u32_f32_x4(svfloat32x4_t zn) __arm_streaming { + return SVE_ACLE_FUNC(svcvt_u32,_f32_x4,,)(zn); +} + +// CHECK-LABEL: @test_svcvt_s32_f32_x4( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4f32.nxv16f32( [[ZN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4f32.nxv16f32( [[ZN]], i64 4) +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv4f32.nxv16f32( [[ZN]], i64 8) +// CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv4f32.nxv16f32( [[ZN]], i64 12) +// CHECK-NEXT: [[TMP4:%.*]] = tail call { , , , } @llvm.aarch64.sve.scvtf.x4.nxv4f32( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) +// CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP4]], 0 +// CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv16i32.nxv4i32( poison, [[TMP5]], i64 0) +// CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP4]], 1 +// CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv16i32.nxv4i32( [[TMP6]], [[TMP7]], i64 4) +// CHECK-NEXT: [[TMP9:%.*]] = extractvalue { , , , } [[TMP4]], 2 +// CHECK-NEXT: [[TMP10:%.*]] = tail call @llvm.vector.insert.nxv16i32.nxv4i32( [[TMP8]], [[TMP9]], i64 8) +// CHECK-NEXT: [[TMP11:%.*]] = extractvalue { , , , } [[TMP4]], 3 +// CHECK-NEXT: [[TMP12:%.*]] = tail call @llvm.vector.insert.nxv16i32.nxv4i32( [[TMP10]], [[TMP11]], i64 12) +// CHECK-NEXT: ret [[TMP12]] +// +// CPP-CHECK-LABEL: @_Z21test_svcvt_s32_f32_x413svfloat32x4_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4f32.nxv16f32( [[ZN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4f32.nxv16f32( [[ZN]], i64 4) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv4f32.nxv16f32( [[ZN]], i64 8) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv4f32.nxv16f32( [[ZN]], i64 12) +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call { , , , } @llvm.aarch64.sve.scvtf.x4.nxv4f32( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) +// CPP-CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP4]], 0 +// CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv16i32.nxv4i32( poison, [[TMP5]], i64 0) +// CPP-CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP4]], 1 +// CPP-CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv16i32.nxv4i32( [[TMP6]], [[TMP7]], i64 4) +// CPP-CHECK-NEXT: [[TMP9:%.*]] = extractvalue { , , , } [[TMP4]], 2 +// CPP-CHECK-NEXT: [[TMP10:%.*]] = tail call @llvm.vector.insert.nxv16i32.nxv4i32( [[TMP8]], [[TMP9]], i64 8) +// CPP-CHECK-NEXT: [[TMP11:%.*]] = extractvalue { , , , } [[TMP4]], 3 +// CPP-CHECK-NEXT: [[TMP12:%.*]] = tail call @llvm.vector.insert.nxv16i32.nxv4i32( [[TMP10]], [[TMP11]], i64 12) +// CPP-CHECK-NEXT: ret [[TMP12]] +// +svint32x4_t test_svcvt_s32_f32_x4(svfloat32x4_t zn) __arm_streaming { + return SVE_ACLE_FUNC(svcvt_s32,_f32_x4,,)(zn); +} + +// CHECK-LABEL: @test_qcvt_s16_s32_x2( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv8i32( [[ZN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv8i32( [[ZN]], i64 4) +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.aarch64.sve.sqcvt.x2.nxv4i32( [[TMP0]], [[TMP1]]) +// CHECK-NEXT: ret [[TMP2]] +// +// CPP-CHECK-LABEL: @_Z20test_qcvt_s16_s32_x211svint32x2_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv8i32( [[ZN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv8i32( [[ZN]], i64 4) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.aarch64.sve.sqcvt.x2.nxv4i32( [[TMP0]], [[TMP1]]) +// CPP-CHECK-NEXT: ret [[TMP2]] +// +svint16_t test_qcvt_s16_s32_x2(svint32x2_t zn) __arm_streaming { + return SVE_ACLE_FUNC(svqcvt_s16,_s32_x2,,)(zn); +} + +// CHECK-LABEL: @test_qcvt_u16_u32_x2( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv8i32( [[ZN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv8i32( [[ZN]], i64 4) +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.aarch64.sve.uqcvt.x2.nxv4i32( [[TMP0]], [[TMP1]]) +// CHECK-NEXT: ret [[TMP2]] +// +// CPP-CHECK-LABEL: @_Z20test_qcvt_u16_u32_x212svuint32x2_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv8i32( [[ZN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv8i32( [[ZN]], i64 4) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.aarch64.sve.uqcvt.x2.nxv4i32( [[TMP0]], [[TMP1]]) +// CPP-CHECK-NEXT: ret [[TMP2]] +// +svuint16_t test_qcvt_u16_u32_x2(svuint32x2_t zn) __arm_streaming { + return SVE_ACLE_FUNC(svqcvt_u16,_u32_x2,,)(zn); +} + +// CHECK-LABEL: @test_qcvt_u16_s32_x2( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv8i32( [[ZN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv8i32( [[ZN]], i64 4) +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.aarch64.sve.sqcvtu.x2.nxv4i32( [[TMP0]], [[TMP1]]) +// CHECK-NEXT: ret [[TMP2]] +// +// CPP-CHECK-LABEL: @_Z20test_qcvt_u16_s32_x211svint32x2_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv8i32( [[ZN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv8i32( [[ZN]], i64 4) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.aarch64.sve.sqcvtu.x2.nxv4i32( [[TMP0]], [[TMP1]]) +// CPP-CHECK-NEXT: ret [[TMP2]] +// +svuint16_t test_qcvt_u16_s32_x2(svint32x2_t zn) __arm_streaming { + return SVE_ACLE_FUNC(svqcvt_u16,_s32_x2,,)(zn); +} + +// CHECK-LABEL: @test_qcvt_u8_u32_x4( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 4) +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 8) +// CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 12) +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.aarch64.sve.uqcvt.x4.nxv4i32( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) +// CHECK-NEXT: ret [[TMP4]] +// +// CPP-CHECK-LABEL: @_Z19test_qcvt_u8_u32_x412svuint32x4_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 4) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 8) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 12) +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.aarch64.sve.uqcvt.x4.nxv4i32( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) +// CPP-CHECK-NEXT: ret [[TMP4]] +// +svuint8_t test_qcvt_u8_u32_x4(svuint32x4_t zn) __arm_streaming { + return SVE_ACLE_FUNC(svqcvt_u8,_u32_x4,,)(zn); +} + +// CHECK-LABEL: @test_qcvt_u16_u64_x4( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 2) +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 4) +// CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 6) +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.aarch64.sve.uqcvt.x4.nxv2i64( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) +// CHECK-NEXT: ret [[TMP4]] +// +// CPP-CHECK-LABEL: @_Z20test_qcvt_u16_u64_x412svuint64x4_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 2) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 4) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 6) +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.aarch64.sve.uqcvt.x4.nxv2i64( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) +// CPP-CHECK-NEXT: ret [[TMP4]] +// +svuint16_t test_qcvt_u16_u64_x4(svuint64x4_t zn) __arm_streaming { + return SVE_ACLE_FUNC(svqcvt_u16,_u64_x4,,)(zn); +} + +// CHECK-LABEL: @test_qcvt_s8_s32_x4( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 4) +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 8) +// CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 12) +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.aarch64.sve.sqcvt.x4.nxv4i32( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) +// CHECK-NEXT: ret [[TMP4]] +// +// CPP-CHECK-LABEL: @_Z19test_qcvt_s8_s32_x411svint32x4_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 4) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 8) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 12) +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.aarch64.sve.sqcvt.x4.nxv4i32( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) +// CPP-CHECK-NEXT: ret [[TMP4]] +// +svint8_t test_qcvt_s8_s32_x4(svint32x4_t zn) __arm_streaming { + return SVE_ACLE_FUNC(svqcvt_s8,_s32_x4,,)(zn); +} + +// CHECK-LABEL: @test_qcvt_s16_s64_x4( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 2) +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 4) +// CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 6) +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.aarch64.sve.sqcvt.x4.nxv2i64( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) +// CHECK-NEXT: ret [[TMP4]] +// +// CPP-CHECK-LABEL: @_Z20test_qcvt_s16_s64_x411svint64x4_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 2) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 4) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 6) +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.aarch64.sve.sqcvt.x4.nxv2i64( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) +// CPP-CHECK-NEXT: ret [[TMP4]] +// +svint16_t test_qcvt_s16_s64_x4(svint64x4_t zn) __arm_streaming { + return SVE_ACLE_FUNC(svqcvt_s16,_s64_x4,,)(zn); +} + +// CHECK-LABEL: @test_qcvt_u8_s32_x4( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 4) +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 8) +// CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 12) +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.aarch64.sve.sqcvtu.x4.nxv4i32( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) +// CHECK-NEXT: ret [[TMP4]] +// +// CPP-CHECK-LABEL: @_Z19test_qcvt_u8_s32_x411svint32x4_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 4) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 8) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 12) +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.aarch64.sve.sqcvtu.x4.nxv4i32( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) +// CPP-CHECK-NEXT: ret [[TMP4]] +// +svuint8_t test_qcvt_u8_s32_x4(svint32x4_t zn) __arm_streaming { + return SVE_ACLE_FUNC(svqcvt_u8,_s32_x4,,)(zn); +} + +// CHECK-LABEL: @test_qcvt_u16_s64_x4( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 2) +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 4) +// CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 6) +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.aarch64.sve.sqcvtu.x4.nxv2i64( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) +// CHECK-NEXT: ret [[TMP4]] +// +// CPP-CHECK-LABEL: @_Z20test_qcvt_u16_s64_x411svint64x4_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 2) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 4) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 6) +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.aarch64.sve.sqcvtu.x4.nxv2i64( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) +// CPP-CHECK-NEXT: ret [[TMP4]] +// +svuint16_t test_qcvt_u16_s64_x4(svint64x4_t zn) __arm_streaming { + return SVE_ACLE_FUNC(svqcvt_u16,_s64_x4,,)(zn); +} diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_cvtn.c b/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_cvtn.c new file mode 100644 index 0000000000000000000000000000000000000000..84aa6764ba380a6471b3b17ddcb115640e1d1344 --- /dev/null +++ b/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_cvtn.c @@ -0,0 +1,242 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py + +// REQUIRES: aarch64-registered-target + +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +sme2 -target-feature +bf16 -S -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +sme2 -target-feature +bf16 -S -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK +// RUN: %clang_cc1 -D__SVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +sme2 -target-feature +bf16 -S -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s +// RUN: %clang_cc1 -D__SVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +sme2 -target-feature +bf16 -S -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +sme2 -target-feature +bf16 -S -disable-O0-optnone -Werror -Wall -o /dev/null %s + +#include + +#ifdef SVE_OVERLOADED_FORMS +// A simple used,unused... macro, long enough to represent any SVE builtin. +#define SVE_ACLE_FUNC(A1,A2_UNUSED,A3,A4_UNUSED) A1##A3 +#else +#define SVE_ACLE_FUNC(A1,A2,A3,A4) A1##A2##A3##A4 +#endif + +// CHECK-LABEL: @test_cvtn_f16_x2( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4f32.nxv8f32( [[ZN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4f32.nxv8f32( [[ZN]], i64 4) +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.aarch64.sve.fcvtn.x2.nxv4f32( [[TMP0]], [[TMP1]]) +// CHECK-NEXT: ret [[TMP2]] +// +// CPP-CHECK-LABEL: @_Z16test_cvtn_f16_x213svfloat32x2_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4f32.nxv8f32( [[ZN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4f32.nxv8f32( [[ZN]], i64 4) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.aarch64.sve.fcvtn.x2.nxv4f32( [[TMP0]], [[TMP1]]) +// CPP-CHECK-NEXT: ret [[TMP2]] +// +svfloat16_t test_cvtn_f16_x2(svfloat32x2_t zn) __arm_streaming { + return SVE_ACLE_FUNC(svcvtn_f16,_f32_x2,,)(zn); +} + +// CHECK-LABEL: @test_cvtn_bf16_x2( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4f32.nxv8f32( [[ZN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4f32.nxv8f32( [[ZN]], i64 4) +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.aarch64.sve.bfcvtn.x2( [[TMP0]], [[TMP1]]) +// CHECK-NEXT: ret [[TMP2]] +// +// CPP-CHECK-LABEL: @_Z17test_cvtn_bf16_x213svfloat32x2_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4f32.nxv8f32( [[ZN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4f32.nxv8f32( [[ZN]], i64 4) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.aarch64.sve.bfcvtn.x2( [[TMP0]], [[TMP1]]) +// CPP-CHECK-NEXT: ret [[TMP2]] +// +svbfloat16_t test_cvtn_bf16_x2(svfloat32x2_t zn) __arm_streaming { + return SVE_ACLE_FUNC(svcvtn_bf16,_f32_x2,,)(zn); +} + +// CHECK-LABEL: @test_qcvtn_s16_s32_x2( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv8i32( [[ZN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv8i32( [[ZN]], i64 4) +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.aarch64.sve.sqcvtn.x2.nxv4i32( [[TMP0]], [[TMP1]]) +// CHECK-NEXT: ret [[TMP2]] +// +// CPP-CHECK-LABEL: @_Z21test_qcvtn_s16_s32_x211svint32x2_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv8i32( [[ZN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv8i32( [[ZN]], i64 4) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.aarch64.sve.sqcvtn.x2.nxv4i32( [[TMP0]], [[TMP1]]) +// CPP-CHECK-NEXT: ret [[TMP2]] +// +svint16_t test_qcvtn_s16_s32_x2(svint32x2_t zn) __arm_streaming_compatible { + return SVE_ACLE_FUNC(svqcvtn_s16,_s32_x2,,)(zn); +} + +// CHECK-LABEL: @test_qcvtn_u16_u32_x2( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv8i32( [[ZN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv8i32( [[ZN]], i64 4) +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.aarch64.sve.uqcvtn.x2.nxv4i32( [[TMP0]], [[TMP1]]) +// CHECK-NEXT: ret [[TMP2]] +// +// CPP-CHECK-LABEL: @_Z21test_qcvtn_u16_u32_x212svuint32x2_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv8i32( [[ZN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv8i32( [[ZN]], i64 4) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.aarch64.sve.uqcvtn.x2.nxv4i32( [[TMP0]], [[TMP1]]) +// CPP-CHECK-NEXT: ret [[TMP2]] +// +svuint16_t test_qcvtn_u16_u32_x2(svuint32x2_t zn) __arm_streaming_compatible { + return SVE_ACLE_FUNC(svqcvtn_u16,_u32_x2,,)(zn); +} + +// CHECK-LABEL: @test_qcvtn_u16_s32_x2( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv8i32( [[ZN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv8i32( [[ZN]], i64 4) +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.aarch64.sve.sqcvtun.x2.nxv4i32( [[TMP0]], [[TMP1]]) +// CHECK-NEXT: ret [[TMP2]] +// +// CPP-CHECK-LABEL: @_Z21test_qcvtn_u16_s32_x211svint32x2_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv8i32( [[ZN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv8i32( [[ZN]], i64 4) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.aarch64.sve.sqcvtun.x2.nxv4i32( [[TMP0]], [[TMP1]]) +// CPP-CHECK-NEXT: ret [[TMP2]] +// +svuint16_t test_qcvtn_u16_s32_x2(svint32x2_t zn) __arm_streaming_compatible { + return SVE_ACLE_FUNC(svqcvtn_u16,_s32_x2,,)(zn); +} + +// CHECK-LABEL: @test_qcvtn_u8_u32_x4( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 4) +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 8) +// CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 12) +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.aarch64.sve.uqcvtn.x4.nxv4i32( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) +// CHECK-NEXT: ret [[TMP4]] +// +// CPP-CHECK-LABEL: @_Z20test_qcvtn_u8_u32_x412svuint32x4_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 4) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 8) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 12) +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.aarch64.sve.uqcvtn.x4.nxv4i32( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) +// CPP-CHECK-NEXT: ret [[TMP4]] +// +svuint8_t test_qcvtn_u8_u32_x4(svuint32x4_t zn) __arm_streaming { + return SVE_ACLE_FUNC(svqcvtn_u8,_u32_x4,,)(zn); +} + +// CHECK-LABEL: @test_qcvtn_u16_u64_x4( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 2) +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 4) +// CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 6) +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.aarch64.sve.uqcvtn.x4.nxv2i64( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) +// CHECK-NEXT: ret [[TMP4]] +// +// CPP-CHECK-LABEL: @_Z21test_qcvtn_u16_u64_x412svuint64x4_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 2) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 4) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 6) +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.aarch64.sve.uqcvtn.x4.nxv2i64( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) +// CPP-CHECK-NEXT: ret [[TMP4]] +// +svuint16_t test_qcvtn_u16_u64_x4(svuint64x4_t zn) __arm_streaming { + return SVE_ACLE_FUNC(svqcvtn_u16,_u64_x4,,)(zn); +} + +// CHECK-LABEL: @test_qcvtn_s8_s32_x4( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 4) +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 8) +// CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 12) +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.aarch64.sve.sqcvtn.x4.nxv4i32( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) +// CHECK-NEXT: ret [[TMP4]] +// +// CPP-CHECK-LABEL: @_Z20test_qcvtn_s8_s32_x411svint32x4_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 4) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 8) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 12) +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.aarch64.sve.sqcvtn.x4.nxv4i32( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) +// CPP-CHECK-NEXT: ret [[TMP4]] +// +svint8_t test_qcvtn_s8_s32_x4(svint32x4_t zn) __arm_streaming { + return SVE_ACLE_FUNC(svqcvtn_s8,_s32_x4,,)(zn); +} + +// CHECK-LABEL: @test_qcvtn_s16_s64_x4( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 2) +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 4) +// CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 6) +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.aarch64.sve.sqcvtn.x4.nxv2i64( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) +// CHECK-NEXT: ret [[TMP4]] +// +// CPP-CHECK-LABEL: @_Z21test_qcvtn_s16_s64_x411svint64x4_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 2) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 4) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 6) +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.aarch64.sve.sqcvtn.x4.nxv2i64( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) +// CPP-CHECK-NEXT: ret [[TMP4]] +// +svint16_t test_qcvtn_s16_s64_x4(svint64x4_t zn) __arm_streaming { + return SVE_ACLE_FUNC(svqcvtn_s16,_s64_x4,,)(zn); +} + +// CHECK-LABEL: @test_qcvtn_u8_32_x4( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 4) +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 8) +// CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 12) +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.aarch64.sve.sqcvtun.x4.nxv4i32( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) +// CHECK-NEXT: ret [[TMP4]] +// +// CPP-CHECK-LABEL: @_Z19test_qcvtn_u8_32_x411svint32x4_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 4) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 8) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 12) +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.aarch64.sve.sqcvtun.x4.nxv4i32( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) +// CPP-CHECK-NEXT: ret [[TMP4]] +// +svuint8_t test_qcvtn_u8_32_x4(svint32x4_t zn) __arm_streaming { + return SVE_ACLE_FUNC(svqcvtn_u8,_s32_x4,,)(zn); +} + +// CHECK-LABEL: @test_qcvtn_u16_s64_x4( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 2) +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 4) +// CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 6) +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.aarch64.sve.sqcvtun.x4.nxv2i64( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) +// CHECK-NEXT: ret [[TMP4]] +// +// CPP-CHECK-LABEL: @_Z21test_qcvtn_u16_s64_x411svint64x4_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 2) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 4) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 6) +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.aarch64.sve.sqcvtun.x4.nxv2i64( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) +// CPP-CHECK-NEXT: ret [[TMP4]] +// +svuint16_t test_qcvtn_u16_s64_x4(svint64x4_t zn) __arm_streaming { + return SVE_ACLE_FUNC(svqcvtn_u16,_s64_x4,,)(zn); +} + + diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_ldr_str_zt.c b/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_ldr_str_zt.c index 126a4fc1045853f0e3bd36394f86394139958ca0..83fbd6e5855caa11629fa7ff262dc07286409f0e 100644 --- a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_ldr_str_zt.c +++ b/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_ldr_str_zt.c @@ -20,7 +20,7 @@ // CPP-CHECK-NEXT: tail call void @llvm.aarch64.sme.ldr.zt(i32 0, ptr [[BASE:%.*]]) // CPP-CHECK-NEXT: ret void // -void test_svldr_zt(const void *base) __arm_streaming_compatible __arm_shared_za __arm_preserves_za { +void test_svldr_zt(const void *base) __arm_streaming_compatible __arm_shared_za { svldr_zt(0, base); } diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_luti2_lane_zt.c b/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_luti2_lane_zt.c new file mode 100644 index 0000000000000000000000000000000000000000..cb34db3695b2428192b73b2a6fe5273d631ec5cb --- /dev/null +++ b/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_luti2_lane_zt.c @@ -0,0 +1,138 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py + +// REQUIRES: aarch64-registered-target + +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +sme2 -S -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +sme2 -S -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +sme2 -S -disable-O0-optnone -Werror -Wall -o /dev/null %s + +#include + + +// CHECK-LABEL: @test_svluti2_lane_zt_u8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sme.luti2.lane.zt.nxv16i8(i32 0, [[ZN:%.*]], i32 15) +// CHECK-NEXT: ret [[TMP0]] +// +// CPP-CHECK-LABEL: @_Z23test_svluti2_lane_zt_u8u11__SVUint8_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sme.luti2.lane.zt.nxv16i8(i32 0, [[ZN:%.*]], i32 15) +// CPP-CHECK-NEXT: ret [[TMP0]] +// +svuint8_t test_svluti2_lane_zt_u8(svuint8_t zn) __arm_streaming __arm_shared_za __arm_preserves_za { + return svluti2_lane_zt_u8(0, zn, 15); +} + + +// CHECK-LABEL: @test_svluti2_lane_zt_s8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sme.luti2.lane.zt.nxv16i8(i32 0, [[ZN:%.*]], i32 15) +// CHECK-NEXT: ret [[TMP0]] +// +// CPP-CHECK-LABEL: @_Z23test_svluti2_lane_zt_s8u11__SVUint8_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sme.luti2.lane.zt.nxv16i8(i32 0, [[ZN:%.*]], i32 15) +// CPP-CHECK-NEXT: ret [[TMP0]] +// +svint8_t test_svluti2_lane_zt_s8(svuint8_t zn) __arm_streaming __arm_shared_za __arm_preserves_za { + return svluti2_lane_zt_s8(0, zn, 15); +} + +// CHECK-LABEL: @test_svluti2_lane_zt_u16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sme.luti2.lane.zt.nxv8i16(i32 0, [[ZN:%.*]], i32 15) +// CHECK-NEXT: ret [[TMP0]] +// +// CPP-CHECK-LABEL: @_Z24test_svluti2_lane_zt_u16u11__SVUint8_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sme.luti2.lane.zt.nxv8i16(i32 0, [[ZN:%.*]], i32 15) +// CPP-CHECK-NEXT: ret [[TMP0]] +// +svuint16_t test_svluti2_lane_zt_u16(svuint8_t zn) __arm_streaming __arm_shared_za __arm_preserves_za { + return svluti2_lane_zt_u16(0, zn, 15); +} + + +// CHECK-LABEL: @test_svluti2_lane_zt_s16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sme.luti2.lane.zt.nxv8i16(i32 0, [[ZN:%.*]], i32 15) +// CHECK-NEXT: ret [[TMP0]] +// +// CPP-CHECK-LABEL: @_Z24test_svluti2_lane_zt_s16u11__SVUint8_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sme.luti2.lane.zt.nxv8i16(i32 0, [[ZN:%.*]], i32 15) +// CPP-CHECK-NEXT: ret [[TMP0]] +// +svint16_t test_svluti2_lane_zt_s16(svuint8_t zn) __arm_streaming __arm_shared_za __arm_preserves_za { + return svluti2_lane_zt_s16(0, zn, 15); +} + +// CHECK-LABEL: @test_svluti2_lane_zt_f16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sme.luti2.lane.zt.nxv8f16(i32 0, [[ZN:%.*]], i32 15) +// CHECK-NEXT: ret [[TMP0]] +// +// CPP-CHECK-LABEL: @_Z24test_svluti2_lane_zt_f16u11__SVUint8_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sme.luti2.lane.zt.nxv8f16(i32 0, [[ZN:%.*]], i32 15) +// CPP-CHECK-NEXT: ret [[TMP0]] +// +svfloat16_t test_svluti2_lane_zt_f16(svuint8_t zn) __arm_streaming __arm_shared_za __arm_preserves_za { + return svluti2_lane_zt_f16(0, zn, 15); +} + +// CHECK-LABEL: @test_svluti2_lane_zt_bf16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sme.luti2.lane.zt.nxv8bf16(i32 0, [[ZN:%.*]], i32 15) +// CHECK-NEXT: ret [[TMP0]] +// +// CPP-CHECK-LABEL: @_Z25test_svluti2_lane_zt_bf16u11__SVUint8_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sme.luti2.lane.zt.nxv8bf16(i32 0, [[ZN:%.*]], i32 15) +// CPP-CHECK-NEXT: ret [[TMP0]] +// +svbfloat16_t test_svluti2_lane_zt_bf16(svuint8_t zn) __arm_streaming __arm_shared_za __arm_preserves_za { + return svluti2_lane_zt_bf16(0, zn, 15); +} + +// CHECK-LABEL: @test_svluti2_lane_zt_u32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sme.luti2.lane.zt.nxv4i32(i32 0, [[ZN:%.*]], i32 15) +// CHECK-NEXT: ret [[TMP0]] +// +// CPP-CHECK-LABEL: @_Z24test_svluti2_lane_zt_u32u11__SVUint8_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sme.luti2.lane.zt.nxv4i32(i32 0, [[ZN:%.*]], i32 15) +// CPP-CHECK-NEXT: ret [[TMP0]] +// +svuint32_t test_svluti2_lane_zt_u32(svuint8_t zn) __arm_streaming __arm_shared_za __arm_preserves_za { + return svluti2_lane_zt_u32(0, zn, 15); +} + +// CHECK-LABEL: @test_svluti2_lane_zt_s32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sme.luti2.lane.zt.nxv4i32(i32 0, [[ZN:%.*]], i32 15) +// CHECK-NEXT: ret [[TMP0]] +// +// CPP-CHECK-LABEL: @_Z24test_svluti2_lane_zt_s32u11__SVUint8_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sme.luti2.lane.zt.nxv4i32(i32 0, [[ZN:%.*]], i32 15) +// CPP-CHECK-NEXT: ret [[TMP0]] +// +svint32_t test_svluti2_lane_zt_s32(svuint8_t zn) __arm_streaming __arm_shared_za __arm_preserves_za { + return svluti2_lane_zt_s32(0, zn, 15); +} + +// CHECK-LABEL: @test_svluti2_lane_zt_f32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sme.luti2.lane.zt.nxv4f32(i32 0, [[ZN:%.*]], i32 15) +// CHECK-NEXT: ret [[TMP0]] +// +// CPP-CHECK-LABEL: @_Z24test_svluti2_lane_zt_f32u11__SVUint8_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sme.luti2.lane.zt.nxv4f32(i32 0, [[ZN:%.*]], i32 15) +// CPP-CHECK-NEXT: ret [[TMP0]] +// +svfloat32_t test_svluti2_lane_zt_f32(svuint8_t zn) __arm_streaming __arm_shared_za __arm_preserves_za { + return svluti2_lane_zt_f32(0, zn, 15); +} diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_luti2_lane_zt_x2.c b/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_luti2_lane_zt_x2.c new file mode 100644 index 0000000000000000000000000000000000000000..04f37af46767ab1a26ca5a76fe8b57edf80729e4 --- /dev/null +++ b/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_luti2_lane_zt_x2.c @@ -0,0 +1,209 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py + +// REQUIRES: aarch64-registered-target + +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +sme2 -S -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +sme2 -S -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +sme2 -S -disable-O0-optnone -Werror -Wall -o /dev/null %s + +#include + +// CHECK-LABEL: @test_svluti2_lane_zt_u8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call { , } @llvm.aarch64.sme.luti2.lane.zt.x2.nxv16i8(i32 0, [[ZN:%.*]], i32 7) +// CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv32i8.nxv16i8( poison, [[TMP1]], i64 0) +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP0]], 1 +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv32i8.nxv16i8( [[TMP2]], [[TMP3]], i64 16) +// CHECK-NEXT: ret [[TMP4]] +// +// CPP-CHECK-LABEL: @_Z23test_svluti2_lane_zt_u8u11__SVUint8_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call { , } @llvm.aarch64.sme.luti2.lane.zt.x2.nxv16i8(i32 0, [[ZN:%.*]], i32 7) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv32i8.nxv16i8( poison, [[TMP1]], i64 0) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP0]], 1 +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv32i8.nxv16i8( [[TMP2]], [[TMP3]], i64 16) +// CPP-CHECK-NEXT: ret [[TMP4]] +// +svuint8x2_t test_svluti2_lane_zt_u8(svuint8_t zn) __arm_streaming __arm_shared_za __arm_preserves_za { + return svluti2_lane_zt_u8_x2(0, zn, 7); +} + + +// CHECK-LABEL: @test_svluti2_lane_zt_s8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call { , } @llvm.aarch64.sme.luti2.lane.zt.x2.nxv16i8(i32 0, [[ZN:%.*]], i32 7) +// CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv32i8.nxv16i8( poison, [[TMP1]], i64 0) +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP0]], 1 +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv32i8.nxv16i8( [[TMP2]], [[TMP3]], i64 16) +// CHECK-NEXT: ret [[TMP4]] +// +// CPP-CHECK-LABEL: @_Z23test_svluti2_lane_zt_s8u11__SVUint8_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call { , } @llvm.aarch64.sme.luti2.lane.zt.x2.nxv16i8(i32 0, [[ZN:%.*]], i32 7) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv32i8.nxv16i8( poison, [[TMP1]], i64 0) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP0]], 1 +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv32i8.nxv16i8( [[TMP2]], [[TMP3]], i64 16) +// CPP-CHECK-NEXT: ret [[TMP4]] +// +svint8x2_t test_svluti2_lane_zt_s8(svuint8_t zn) __arm_streaming __arm_shared_za __arm_preserves_za { + return svluti2_lane_zt_s8_x2(0, zn, 7); +} + +// CHECK-LABEL: @test_svluti2_lane_zt_u16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call { , } @llvm.aarch64.sme.luti2.lane.zt.x2.nxv8i16(i32 0, [[ZN:%.*]], i32 7) +// CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv16i16.nxv8i16( poison, [[TMP1]], i64 0) +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP0]], 1 +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv16i16.nxv8i16( [[TMP2]], [[TMP3]], i64 8) +// CHECK-NEXT: ret [[TMP4]] +// +// CPP-CHECK-LABEL: @_Z24test_svluti2_lane_zt_u16u11__SVUint8_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call { , } @llvm.aarch64.sme.luti2.lane.zt.x2.nxv8i16(i32 0, [[ZN:%.*]], i32 7) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv16i16.nxv8i16( poison, [[TMP1]], i64 0) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP0]], 1 +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv16i16.nxv8i16( [[TMP2]], [[TMP3]], i64 8) +// CPP-CHECK-NEXT: ret [[TMP4]] +// +svuint16x2_t test_svluti2_lane_zt_u16(svuint8_t zn) __arm_streaming __arm_shared_za __arm_preserves_za { + return svluti2_lane_zt_u16_x2(0, zn, 7); +} + + +// CHECK-LABEL: @test_svluti2_lane_zt_s16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call { , } @llvm.aarch64.sme.luti2.lane.zt.x2.nxv8i16(i32 0, [[ZN:%.*]], i32 7) +// CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv16i16.nxv8i16( poison, [[TMP1]], i64 0) +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP0]], 1 +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv16i16.nxv8i16( [[TMP2]], [[TMP3]], i64 8) +// CHECK-NEXT: ret [[TMP4]] +// +// CPP-CHECK-LABEL: @_Z24test_svluti2_lane_zt_s16u11__SVUint8_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call { , } @llvm.aarch64.sme.luti2.lane.zt.x2.nxv8i16(i32 0, [[ZN:%.*]], i32 7) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv16i16.nxv8i16( poison, [[TMP1]], i64 0) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP0]], 1 +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv16i16.nxv8i16( [[TMP2]], [[TMP3]], i64 8) +// CPP-CHECK-NEXT: ret [[TMP4]] +// +svint16x2_t test_svluti2_lane_zt_s16(svuint8_t zn) __arm_streaming __arm_shared_za __arm_preserves_za { + return svluti2_lane_zt_s16_x2(0, zn, 7); +} + +// CHECK-LABEL: @test_svluti2_lane_zt_f16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call { , } @llvm.aarch64.sme.luti2.lane.zt.x2.nxv8f16(i32 0, [[ZN:%.*]], i32 7) +// CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv16f16.nxv8f16( poison, [[TMP1]], i64 0) +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP0]], 1 +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv16f16.nxv8f16( [[TMP2]], [[TMP3]], i64 8) +// CHECK-NEXT: ret [[TMP4]] +// +// CPP-CHECK-LABEL: @_Z24test_svluti2_lane_zt_f16u11__SVUint8_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call { , } @llvm.aarch64.sme.luti2.lane.zt.x2.nxv8f16(i32 0, [[ZN:%.*]], i32 7) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv16f16.nxv8f16( poison, [[TMP1]], i64 0) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP0]], 1 +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv16f16.nxv8f16( [[TMP2]], [[TMP3]], i64 8) +// CPP-CHECK-NEXT: ret [[TMP4]] +// +svfloat16x2_t test_svluti2_lane_zt_f16(svuint8_t zn) __arm_streaming __arm_shared_za __arm_preserves_za { + return svluti2_lane_zt_f16_x2(0, zn, 7); +} + +// CHECK-LABEL: @test_svluti2_lane_zt_bf16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call { , } @llvm.aarch64.sme.luti2.lane.zt.x2.nxv8bf16(i32 0, [[ZN:%.*]], i32 7) +// CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( poison, [[TMP1]], i64 0) +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP0]], 1 +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( [[TMP2]], [[TMP3]], i64 8) +// CHECK-NEXT: ret [[TMP4]] +// +// CPP-CHECK-LABEL: @_Z25test_svluti2_lane_zt_bf16u11__SVUint8_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call { , } @llvm.aarch64.sme.luti2.lane.zt.x2.nxv8bf16(i32 0, [[ZN:%.*]], i32 7) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( poison, [[TMP1]], i64 0) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP0]], 1 +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( [[TMP2]], [[TMP3]], i64 8) +// CPP-CHECK-NEXT: ret [[TMP4]] +// +svbfloat16x2_t test_svluti2_lane_zt_bf16(svuint8_t zn) __arm_streaming __arm_shared_za __arm_preserves_za { + return svluti2_lane_zt_bf16_x2(0, zn, 7); +} + +// CHECK-LABEL: @test_svluti2_lane_zt_u32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call { , } @llvm.aarch64.sme.luti2.lane.zt.x2.nxv4i32(i32 0, [[ZN:%.*]], i32 7) +// CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv8i32.nxv4i32( poison, [[TMP1]], i64 0) +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP0]], 1 +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv8i32.nxv4i32( [[TMP2]], [[TMP3]], i64 4) +// CHECK-NEXT: ret [[TMP4]] +// +// CPP-CHECK-LABEL: @_Z24test_svluti2_lane_zt_u32u11__SVUint8_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call { , } @llvm.aarch64.sme.luti2.lane.zt.x2.nxv4i32(i32 0, [[ZN:%.*]], i32 7) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv8i32.nxv4i32( poison, [[TMP1]], i64 0) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP0]], 1 +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv8i32.nxv4i32( [[TMP2]], [[TMP3]], i64 4) +// CPP-CHECK-NEXT: ret [[TMP4]] +// +svuint32x2_t test_svluti2_lane_zt_u32(svuint8_t zn) __arm_streaming __arm_shared_za __arm_preserves_za { + return svluti2_lane_zt_u32_x2(0, zn, 7); +} + +// CHECK-LABEL: @test_svluti2_lane_zt_s32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call { , } @llvm.aarch64.sme.luti2.lane.zt.x2.nxv4i32(i32 0, [[ZN:%.*]], i32 7) +// CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv8i32.nxv4i32( poison, [[TMP1]], i64 0) +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP0]], 1 +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv8i32.nxv4i32( [[TMP2]], [[TMP3]], i64 4) +// CHECK-NEXT: ret [[TMP4]] +// +// CPP-CHECK-LABEL: @_Z24test_svluti2_lane_zt_s32u11__SVUint8_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call { , } @llvm.aarch64.sme.luti2.lane.zt.x2.nxv4i32(i32 0, [[ZN:%.*]], i32 7) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv8i32.nxv4i32( poison, [[TMP1]], i64 0) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP0]], 1 +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv8i32.nxv4i32( [[TMP2]], [[TMP3]], i64 4) +// CPP-CHECK-NEXT: ret [[TMP4]] +// +svint32x2_t test_svluti2_lane_zt_s32(svuint8_t zn) __arm_streaming __arm_shared_za __arm_preserves_za { + return svluti2_lane_zt_s32_x2(0, zn, 7); +} + +// CHECK-LABEL: @test_svluti2_lane_zt_f32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call { , } @llvm.aarch64.sme.luti2.lane.zt.x2.nxv4f32(i32 0, [[ZN:%.*]], i32 7) +// CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv8f32.nxv4f32( poison, [[TMP1]], i64 0) +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP0]], 1 +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv8f32.nxv4f32( [[TMP2]], [[TMP3]], i64 4) +// CHECK-NEXT: ret [[TMP4]] +// +// CPP-CHECK-LABEL: @_Z24test_svluti2_lane_zt_f32u11__SVUint8_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call { , } @llvm.aarch64.sme.luti2.lane.zt.x2.nxv4f32(i32 0, [[ZN:%.*]], i32 7) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv8f32.nxv4f32( poison, [[TMP1]], i64 0) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP0]], 1 +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv8f32.nxv4f32( [[TMP2]], [[TMP3]], i64 4) +// CPP-CHECK-NEXT: ret [[TMP4]] +// +svfloat32x2_t test_svluti2_lane_zt_f32(svuint8_t zn) __arm_streaming __arm_shared_za __arm_preserves_za { + return svluti2_lane_zt_f32_x2(0, zn, 7); +} diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_luti2_lane_zt_x4.c b/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_luti2_lane_zt_x4.c new file mode 100644 index 0000000000000000000000000000000000000000..8c38d829a7f4cabeb245d7971db68bbbe9c9d299 --- /dev/null +++ b/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_luti2_lane_zt_x4.c @@ -0,0 +1,280 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py + +// REQUIRES: aarch64-registered-target + +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme2 -target-feature +sve -S -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme2 -target-feature +sve -S -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme2 -target-feature +sve -S -disable-O0-optnone -Werror -Wall -o /dev/null %s + +#include + +// CHECK-LABEL: @test_svluti2_lane_zt_u8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call { , , , } @llvm.aarch64.sme.luti2.lane.zt.x4.nxv16i8(i32 0, [[ZN:%.*]], i32 3) +// CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , , , } [[TMP0]], 0 +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv64i8.nxv16i8( poison, [[TMP1]], i64 0) +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , , , } [[TMP0]], 1 +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv64i8.nxv16i8( [[TMP2]], [[TMP3]], i64 16) +// CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP0]], 2 +// CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv64i8.nxv16i8( [[TMP4]], [[TMP5]], i64 32) +// CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP0]], 3 +// CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv64i8.nxv16i8( [[TMP6]], [[TMP7]], i64 48) +// CHECK-NEXT: ret [[TMP8]] +// +// CPP-CHECK-LABEL: @_Z23test_svluti2_lane_zt_u8u11__SVUint8_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call { , , , } @llvm.aarch64.sme.luti2.lane.zt.x4.nxv16i8(i32 0, [[ZN:%.*]], i32 3) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , , , } [[TMP0]], 0 +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv64i8.nxv16i8( poison, [[TMP1]], i64 0) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , , , } [[TMP0]], 1 +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv64i8.nxv16i8( [[TMP2]], [[TMP3]], i64 16) +// CPP-CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP0]], 2 +// CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv64i8.nxv16i8( [[TMP4]], [[TMP5]], i64 32) +// CPP-CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP0]], 3 +// CPP-CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv64i8.nxv16i8( [[TMP6]], [[TMP7]], i64 48) +// CPP-CHECK-NEXT: ret [[TMP8]] +// +svuint8x4_t test_svluti2_lane_zt_u8(svuint8_t zn) __arm_streaming __arm_shared_za __arm_preserves_za { + return svluti2_lane_zt_u8_x4(0, zn, 3); +} + + +// CHECK-LABEL: @test_svluti2_lane_zt_s8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call { , , , } @llvm.aarch64.sme.luti2.lane.zt.x4.nxv16i8(i32 0, [[ZN:%.*]], i32 3) +// CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , , , } [[TMP0]], 0 +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv64i8.nxv16i8( poison, [[TMP1]], i64 0) +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , , , } [[TMP0]], 1 +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv64i8.nxv16i8( [[TMP2]], [[TMP3]], i64 16) +// CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP0]], 2 +// CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv64i8.nxv16i8( [[TMP4]], [[TMP5]], i64 32) +// CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP0]], 3 +// CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv64i8.nxv16i8( [[TMP6]], [[TMP7]], i64 48) +// CHECK-NEXT: ret [[TMP8]] +// +// CPP-CHECK-LABEL: @_Z23test_svluti2_lane_zt_s8u11__SVUint8_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call { , , , } @llvm.aarch64.sme.luti2.lane.zt.x4.nxv16i8(i32 0, [[ZN:%.*]], i32 3) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , , , } [[TMP0]], 0 +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv64i8.nxv16i8( poison, [[TMP1]], i64 0) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , , , } [[TMP0]], 1 +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv64i8.nxv16i8( [[TMP2]], [[TMP3]], i64 16) +// CPP-CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP0]], 2 +// CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv64i8.nxv16i8( [[TMP4]], [[TMP5]], i64 32) +// CPP-CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP0]], 3 +// CPP-CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv64i8.nxv16i8( [[TMP6]], [[TMP7]], i64 48) +// CPP-CHECK-NEXT: ret [[TMP8]] +// +svint8x4_t test_svluti2_lane_zt_s8(svuint8_t zn) __arm_streaming __arm_shared_za __arm_preserves_za { + return svluti2_lane_zt_s8_x4(0, zn, 3); +} + +// CHECK-LABEL: @test_svluti2_lane_zt_u16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call { , , , } @llvm.aarch64.sme.luti2.lane.zt.x4.nxv8i16(i32 0, [[ZN:%.*]], i32 3) +// CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , , , } [[TMP0]], 0 +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv32i16.nxv8i16( poison, [[TMP1]], i64 0) +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , , , } [[TMP0]], 1 +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv32i16.nxv8i16( [[TMP2]], [[TMP3]], i64 8) +// CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP0]], 2 +// CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv32i16.nxv8i16( [[TMP4]], [[TMP5]], i64 16) +// CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP0]], 3 +// CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv32i16.nxv8i16( [[TMP6]], [[TMP7]], i64 24) +// CHECK-NEXT: ret [[TMP8]] +// +// CPP-CHECK-LABEL: @_Z24test_svluti2_lane_zt_u16u11__SVUint8_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call { , , , } @llvm.aarch64.sme.luti2.lane.zt.x4.nxv8i16(i32 0, [[ZN:%.*]], i32 3) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , , , } [[TMP0]], 0 +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv32i16.nxv8i16( poison, [[TMP1]], i64 0) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , , , } [[TMP0]], 1 +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv32i16.nxv8i16( [[TMP2]], [[TMP3]], i64 8) +// CPP-CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP0]], 2 +// CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv32i16.nxv8i16( [[TMP4]], [[TMP5]], i64 16) +// CPP-CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP0]], 3 +// CPP-CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv32i16.nxv8i16( [[TMP6]], [[TMP7]], i64 24) +// CPP-CHECK-NEXT: ret [[TMP8]] +// +svuint16x4_t test_svluti2_lane_zt_u16(svuint8_t zn) __arm_streaming __arm_shared_za __arm_preserves_za { + return svluti2_lane_zt_u16_x4(0, zn, 3); +} + +// CHECK-LABEL: @test_svluti2_lane_zt_s16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call { , , , } @llvm.aarch64.sme.luti2.lane.zt.x4.nxv8i16(i32 0, [[ZN:%.*]], i32 3) +// CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , , , } [[TMP0]], 0 +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv32i16.nxv8i16( poison, [[TMP1]], i64 0) +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , , , } [[TMP0]], 1 +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv32i16.nxv8i16( [[TMP2]], [[TMP3]], i64 8) +// CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP0]], 2 +// CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv32i16.nxv8i16( [[TMP4]], [[TMP5]], i64 16) +// CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP0]], 3 +// CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv32i16.nxv8i16( [[TMP6]], [[TMP7]], i64 24) +// CHECK-NEXT: ret [[TMP8]] +// +// CPP-CHECK-LABEL: @_Z24test_svluti2_lane_zt_s16u11__SVUint8_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call { , , , } @llvm.aarch64.sme.luti2.lane.zt.x4.nxv8i16(i32 0, [[ZN:%.*]], i32 3) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , , , } [[TMP0]], 0 +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv32i16.nxv8i16( poison, [[TMP1]], i64 0) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , , , } [[TMP0]], 1 +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv32i16.nxv8i16( [[TMP2]], [[TMP3]], i64 8) +// CPP-CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP0]], 2 +// CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv32i16.nxv8i16( [[TMP4]], [[TMP5]], i64 16) +// CPP-CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP0]], 3 +// CPP-CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv32i16.nxv8i16( [[TMP6]], [[TMP7]], i64 24) +// CPP-CHECK-NEXT: ret [[TMP8]] +// +svint16x4_t test_svluti2_lane_zt_s16(svuint8_t zn) __arm_streaming __arm_shared_za __arm_preserves_za { + return svluti2_lane_zt_s16_x4(0, zn, 3); +} + +// CHECK-LABEL: @test_svluti2_lane_zt_f16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call { , , , } @llvm.aarch64.sme.luti2.lane.zt.x4.nxv8f16(i32 0, [[ZN:%.*]], i32 3) +// CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , , , } [[TMP0]], 0 +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv32f16.nxv8f16( poison, [[TMP1]], i64 0) +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , , , } [[TMP0]], 1 +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv32f16.nxv8f16( [[TMP2]], [[TMP3]], i64 8) +// CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP0]], 2 +// CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv32f16.nxv8f16( [[TMP4]], [[TMP5]], i64 16) +// CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP0]], 3 +// CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv32f16.nxv8f16( [[TMP6]], [[TMP7]], i64 24) +// CHECK-NEXT: ret [[TMP8]] +// +// CPP-CHECK-LABEL: @_Z24test_svluti2_lane_zt_f16u11__SVUint8_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call { , , , } @llvm.aarch64.sme.luti2.lane.zt.x4.nxv8f16(i32 0, [[ZN:%.*]], i32 3) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , , , } [[TMP0]], 0 +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv32f16.nxv8f16( poison, [[TMP1]], i64 0) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , , , } [[TMP0]], 1 +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv32f16.nxv8f16( [[TMP2]], [[TMP3]], i64 8) +// CPP-CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP0]], 2 +// CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv32f16.nxv8f16( [[TMP4]], [[TMP5]], i64 16) +// CPP-CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP0]], 3 +// CPP-CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv32f16.nxv8f16( [[TMP6]], [[TMP7]], i64 24) +// CPP-CHECK-NEXT: ret [[TMP8]] +// +svfloat16x4_t test_svluti2_lane_zt_f16(svuint8_t zn) __arm_streaming __arm_shared_za __arm_preserves_za { + return svluti2_lane_zt_f16_x4(0, zn, 3); +} + +// CHECK-LABEL: @test_svluti2_lane_zt_bf16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call { , , , } @llvm.aarch64.sme.luti2.lane.zt.x4.nxv8bf16(i32 0, [[ZN:%.*]], i32 3) +// CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , , , } [[TMP0]], 0 +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( poison, [[TMP1]], i64 0) +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , , , } [[TMP0]], 1 +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP2]], [[TMP3]], i64 8) +// CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP0]], 2 +// CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP4]], [[TMP5]], i64 16) +// CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP0]], 3 +// CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP6]], [[TMP7]], i64 24) +// CHECK-NEXT: ret [[TMP8]] +// +// CPP-CHECK-LABEL: @_Z25test_svluti2_lane_zt_bf16u11__SVUint8_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call { , , , } @llvm.aarch64.sme.luti2.lane.zt.x4.nxv8bf16(i32 0, [[ZN:%.*]], i32 3) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , , , } [[TMP0]], 0 +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( poison, [[TMP1]], i64 0) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , , , } [[TMP0]], 1 +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP2]], [[TMP3]], i64 8) +// CPP-CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP0]], 2 +// CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP4]], [[TMP5]], i64 16) +// CPP-CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP0]], 3 +// CPP-CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP6]], [[TMP7]], i64 24) +// CPP-CHECK-NEXT: ret [[TMP8]] +// +svbfloat16x4_t test_svluti2_lane_zt_bf16(svuint8_t zn) __arm_streaming __arm_shared_za __arm_preserves_za { + return svluti2_lane_zt_bf16_x4(0, zn, 3); +} + +// CHECK-LABEL: @test_svluti2_lane_zt_u32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call { , , , } @llvm.aarch64.sme.luti2.lane.zt.x4.nxv4i32(i32 0, [[ZN:%.*]], i32 3) +// CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , , , } [[TMP0]], 0 +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv16i32.nxv4i32( poison, [[TMP1]], i64 0) +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , , , } [[TMP0]], 1 +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv16i32.nxv4i32( [[TMP2]], [[TMP3]], i64 4) +// CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP0]], 2 +// CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv16i32.nxv4i32( [[TMP4]], [[TMP5]], i64 8) +// CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP0]], 3 +// CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv16i32.nxv4i32( [[TMP6]], [[TMP7]], i64 12) +// CHECK-NEXT: ret [[TMP8]] +// +// CPP-CHECK-LABEL: @_Z24test_svluti2_lane_zt_u32u11__SVUint8_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call { , , , } @llvm.aarch64.sme.luti2.lane.zt.x4.nxv4i32(i32 0, [[ZN:%.*]], i32 3) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , , , } [[TMP0]], 0 +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv16i32.nxv4i32( poison, [[TMP1]], i64 0) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , , , } [[TMP0]], 1 +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv16i32.nxv4i32( [[TMP2]], [[TMP3]], i64 4) +// CPP-CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP0]], 2 +// CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv16i32.nxv4i32( [[TMP4]], [[TMP5]], i64 8) +// CPP-CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP0]], 3 +// CPP-CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv16i32.nxv4i32( [[TMP6]], [[TMP7]], i64 12) +// CPP-CHECK-NEXT: ret [[TMP8]] +// +svuint32x4_t test_svluti2_lane_zt_u32(svuint8_t zn) __arm_streaming __arm_shared_za __arm_preserves_za { + return svluti2_lane_zt_u32_x4(0, zn, 3); +} + +// CHECK-LABEL: @test_svluti2_lane_zt_s32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call { , , , } @llvm.aarch64.sme.luti2.lane.zt.x4.nxv4i32(i32 0, [[ZN:%.*]], i32 3) +// CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , , , } [[TMP0]], 0 +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv16i32.nxv4i32( poison, [[TMP1]], i64 0) +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , , , } [[TMP0]], 1 +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv16i32.nxv4i32( [[TMP2]], [[TMP3]], i64 4) +// CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP0]], 2 +// CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv16i32.nxv4i32( [[TMP4]], [[TMP5]], i64 8) +// CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP0]], 3 +// CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv16i32.nxv4i32( [[TMP6]], [[TMP7]], i64 12) +// CHECK-NEXT: ret [[TMP8]] +// +// CPP-CHECK-LABEL: @_Z24test_svluti2_lane_zt_s32u11__SVUint8_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call { , , , } @llvm.aarch64.sme.luti2.lane.zt.x4.nxv4i32(i32 0, [[ZN:%.*]], i32 3) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , , , } [[TMP0]], 0 +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv16i32.nxv4i32( poison, [[TMP1]], i64 0) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , , , } [[TMP0]], 1 +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv16i32.nxv4i32( [[TMP2]], [[TMP3]], i64 4) +// CPP-CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP0]], 2 +// CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv16i32.nxv4i32( [[TMP4]], [[TMP5]], i64 8) +// CPP-CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP0]], 3 +// CPP-CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv16i32.nxv4i32( [[TMP6]], [[TMP7]], i64 12) +// CPP-CHECK-NEXT: ret [[TMP8]] +// +svint32x4_t test_svluti2_lane_zt_s32(svuint8_t zn) __arm_streaming __arm_shared_za __arm_preserves_za { + return svluti2_lane_zt_s32_x4(0, zn, 3); +} + +// CHECK-LABEL: @test_svluti2_lane_zt_f32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call { , , , } @llvm.aarch64.sme.luti2.lane.zt.x4.nxv4f32(i32 0, [[ZN:%.*]], i32 3) +// CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , , , } [[TMP0]], 0 +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv16f32.nxv4f32( poison, [[TMP1]], i64 0) +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , , , } [[TMP0]], 1 +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv16f32.nxv4f32( [[TMP2]], [[TMP3]], i64 4) +// CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP0]], 2 +// CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv16f32.nxv4f32( [[TMP4]], [[TMP5]], i64 8) +// CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP0]], 3 +// CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv16f32.nxv4f32( [[TMP6]], [[TMP7]], i64 12) +// CHECK-NEXT: ret [[TMP8]] +// +// CPP-CHECK-LABEL: @_Z24test_svluti2_lane_zt_f32u11__SVUint8_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call { , , , } @llvm.aarch64.sme.luti2.lane.zt.x4.nxv4f32(i32 0, [[ZN:%.*]], i32 3) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , , , } [[TMP0]], 0 +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv16f32.nxv4f32( poison, [[TMP1]], i64 0) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , , , } [[TMP0]], 1 +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv16f32.nxv4f32( [[TMP2]], [[TMP3]], i64 4) +// CPP-CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP0]], 2 +// CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv16f32.nxv4f32( [[TMP4]], [[TMP5]], i64 8) +// CPP-CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP0]], 3 +// CPP-CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv16f32.nxv4f32( [[TMP6]], [[TMP7]], i64 12) +// CPP-CHECK-NEXT: ret [[TMP8]] +// +svfloat32x4_t test_svluti2_lane_zt_f32(svuint8_t zn) __arm_streaming __arm_shared_za __arm_preserves_za { + return svluti2_lane_zt_f32_x4(0, zn, 3); +} diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_luti4_lane_zt.c b/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_luti4_lane_zt.c new file mode 100644 index 0000000000000000000000000000000000000000..9815b0e825b3032dea589d4ea972b446e51b2974 --- /dev/null +++ b/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_luti4_lane_zt.c @@ -0,0 +1,137 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py + +// REQUIRES: aarch64-registered-target + +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +sme2 -S -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +sme2 -S -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +sme2 -S -disable-O0-optnone -Werror -Wall -o /dev/null %s + +#include + + +// CHECK-LABEL: @test_svluti4_lane_zt_u8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sme.luti4.lane.zt.nxv16i8(i32 0, [[ZN:%.*]], i32 7) +// CHECK-NEXT: ret [[TMP0]] +// +// CPP-CHECK-LABEL: @_Z23test_svluti4_lane_zt_u8u11__SVUint8_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sme.luti4.lane.zt.nxv16i8(i32 0, [[ZN:%.*]], i32 7) +// CPP-CHECK-NEXT: ret [[TMP0]] +// +svuint8_t test_svluti4_lane_zt_u8(svuint8_t zn) __arm_streaming __arm_shared_za __arm_preserves_za { + return svluti4_lane_zt_u8(0, zn, 7); +} + + +// CHECK-LABEL: @test_svluti4_lane_zt_s8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sme.luti4.lane.zt.nxv16i8(i32 0, [[ZN:%.*]], i32 7) +// CHECK-NEXT: ret [[TMP0]] +// +// CPP-CHECK-LABEL: @_Z23test_svluti4_lane_zt_s8u11__SVUint8_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sme.luti4.lane.zt.nxv16i8(i32 0, [[ZN:%.*]], i32 7) +// CPP-CHECK-NEXT: ret [[TMP0]] +// +svint8_t test_svluti4_lane_zt_s8(svuint8_t zn) __arm_streaming __arm_shared_za __arm_preserves_za { + return svluti4_lane_zt_s8(0, zn, 7); +} + +// CHECK-LABEL: @test_svluti4_lane_zt_u16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sme.luti4.lane.zt.nxv8i16(i32 0, [[ZN:%.*]], i32 7) +// CHECK-NEXT: ret [[TMP0]] +// +// CPP-CHECK-LABEL: @_Z24test_svluti4_lane_zt_u16u11__SVUint8_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sme.luti4.lane.zt.nxv8i16(i32 0, [[ZN:%.*]], i32 7) +// CPP-CHECK-NEXT: ret [[TMP0]] +// +svuint16_t test_svluti4_lane_zt_u16(svuint8_t zn) __arm_streaming __arm_shared_za __arm_preserves_za { + return svluti4_lane_zt_u16(0, zn, 7); +} + +// CHECK-LABEL: @test_svluti4_lane_zt_s16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sme.luti4.lane.zt.nxv8i16(i32 0, [[ZN:%.*]], i32 7) +// CHECK-NEXT: ret [[TMP0]] +// +// CPP-CHECK-LABEL: @_Z24test_svluti4_lane_zt_s16u11__SVUint8_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sme.luti4.lane.zt.nxv8i16(i32 0, [[ZN:%.*]], i32 7) +// CPP-CHECK-NEXT: ret [[TMP0]] +// +svint16_t test_svluti4_lane_zt_s16(svuint8_t zn) __arm_streaming __arm_shared_za __arm_preserves_za { + return svluti4_lane_zt_s16(0, zn, 7); +} + +// CHECK-LABEL: @test_svluti4_lane_zt_f16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sme.luti4.lane.zt.nxv8f16(i32 0, [[ZN:%.*]], i32 7) +// CHECK-NEXT: ret [[TMP0]] +// +// CPP-CHECK-LABEL: @_Z24test_svluti4_lane_zt_f16u11__SVUint8_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sme.luti4.lane.zt.nxv8f16(i32 0, [[ZN:%.*]], i32 7) +// CPP-CHECK-NEXT: ret [[TMP0]] +// +svfloat16_t test_svluti4_lane_zt_f16(svuint8_t zn) __arm_streaming __arm_shared_za __arm_preserves_za { + return svluti4_lane_zt_f16(0, zn, 7); +} + +// CHECK-LABEL: @test_svluti4_lane_zt_bf16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sme.luti4.lane.zt.nxv8bf16(i32 0, [[ZN:%.*]], i32 7) +// CHECK-NEXT: ret [[TMP0]] +// +// CPP-CHECK-LABEL: @_Z25test_svluti4_lane_zt_bf16u11__SVUint8_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sme.luti4.lane.zt.nxv8bf16(i32 0, [[ZN:%.*]], i32 7) +// CPP-CHECK-NEXT: ret [[TMP0]] +// +svbfloat16_t test_svluti4_lane_zt_bf16(svuint8_t zn) __arm_streaming __arm_shared_za __arm_preserves_za { + return svluti4_lane_zt_bf16(0, zn, 7); +} + +// CHECK-LABEL: @test_svluti4_lane_zt_u32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sme.luti4.lane.zt.nxv4i32(i32 0, [[ZN:%.*]], i32 7) +// CHECK-NEXT: ret [[TMP0]] +// +// CPP-CHECK-LABEL: @_Z24test_svluti4_lane_zt_u32u11__SVUint8_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sme.luti4.lane.zt.nxv4i32(i32 0, [[ZN:%.*]], i32 7) +// CPP-CHECK-NEXT: ret [[TMP0]] +// +svuint32_t test_svluti4_lane_zt_u32(svuint8_t zn) __arm_streaming __arm_shared_za __arm_preserves_za { + return svluti4_lane_zt_u32(0, zn, 7); +} + +// CHECK-LABEL: @test_svluti4_lane_zt_s32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sme.luti4.lane.zt.nxv4i32(i32 0, [[ZN:%.*]], i32 7) +// CHECK-NEXT: ret [[TMP0]] +// +// CPP-CHECK-LABEL: @_Z24test_svluti4_lane_zt_s32u11__SVUint8_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sme.luti4.lane.zt.nxv4i32(i32 0, [[ZN:%.*]], i32 7) +// CPP-CHECK-NEXT: ret [[TMP0]] +// +svint32_t test_svluti4_lane_zt_s32(svuint8_t zn) __arm_streaming __arm_shared_za __arm_preserves_za { + return svluti4_lane_zt_s32(0, zn, 7); +} + +// CHECK-LABEL: @test_svluti4_lane_zt_f32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sme.luti4.lane.zt.nxv4f32(i32 0, [[ZN:%.*]], i32 7) +// CHECK-NEXT: ret [[TMP0]] +// +// CPP-CHECK-LABEL: @_Z24test_svluti4_lane_zt_f32u11__SVUint8_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sme.luti4.lane.zt.nxv4f32(i32 0, [[ZN:%.*]], i32 7) +// CPP-CHECK-NEXT: ret [[TMP0]] +// +svfloat32_t test_svluti4_lane_zt_f32(svuint8_t zn) __arm_streaming __arm_shared_za __arm_preserves_za { + return svluti4_lane_zt_f32(0, zn, 7); +} diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_luti4_lane_zt_x2.c b/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_luti4_lane_zt_x2.c new file mode 100644 index 0000000000000000000000000000000000000000..4c181dd9123c5684ac80e40c8632f48e1c68ce46 --- /dev/null +++ b/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_luti4_lane_zt_x2.c @@ -0,0 +1,209 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py + +// REQUIRES: aarch64-registered-target + +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +sme2 -S -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +sme2 -S -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +sme2 -S -disable-O0-optnone -Werror -Wall -o /dev/null %s + +#include + +// CHECK-LABEL: @test_svluti4_lane_zt_u8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call { , } @llvm.aarch64.sme.luti4.lane.zt.x2.nxv16i8(i32 0, [[ZN:%.*]], i32 3) +// CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv32i8.nxv16i8( poison, [[TMP1]], i64 0) +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP0]], 1 +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv32i8.nxv16i8( [[TMP2]], [[TMP3]], i64 16) +// CHECK-NEXT: ret [[TMP4]] +// +// CPP-CHECK-LABEL: @_Z23test_svluti4_lane_zt_u8u11__SVUint8_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call { , } @llvm.aarch64.sme.luti4.lane.zt.x2.nxv16i8(i32 0, [[ZN:%.*]], i32 3) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv32i8.nxv16i8( poison, [[TMP1]], i64 0) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP0]], 1 +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv32i8.nxv16i8( [[TMP2]], [[TMP3]], i64 16) +// CPP-CHECK-NEXT: ret [[TMP4]] +// +svuint8x2_t test_svluti4_lane_zt_u8(svuint8_t zn) __arm_streaming __arm_shared_za __arm_preserves_za { + return svluti4_lane_zt_u8_x2(0, zn, 3); +} + + +// CHECK-LABEL: @test_svluti4_lane_zt_s8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call { , } @llvm.aarch64.sme.luti4.lane.zt.x2.nxv16i8(i32 0, [[ZN:%.*]], i32 3) +// CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv32i8.nxv16i8( poison, [[TMP1]], i64 0) +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP0]], 1 +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv32i8.nxv16i8( [[TMP2]], [[TMP3]], i64 16) +// CHECK-NEXT: ret [[TMP4]] +// +// CPP-CHECK-LABEL: @_Z23test_svluti4_lane_zt_s8u11__SVUint8_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call { , } @llvm.aarch64.sme.luti4.lane.zt.x2.nxv16i8(i32 0, [[ZN:%.*]], i32 3) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv32i8.nxv16i8( poison, [[TMP1]], i64 0) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP0]], 1 +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv32i8.nxv16i8( [[TMP2]], [[TMP3]], i64 16) +// CPP-CHECK-NEXT: ret [[TMP4]] +// +svint8x2_t test_svluti4_lane_zt_s8(svuint8_t zn) __arm_streaming __arm_shared_za __arm_preserves_za { + return svluti4_lane_zt_s8_x2(0, zn, 3); +} + +// CHECK-LABEL: @test_svluti4_lane_zt_u16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call { , } @llvm.aarch64.sme.luti4.lane.zt.x2.nxv8i16(i32 0, [[ZN:%.*]], i32 3) +// CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv16i16.nxv8i16( poison, [[TMP1]], i64 0) +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP0]], 1 +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv16i16.nxv8i16( [[TMP2]], [[TMP3]], i64 8) +// CHECK-NEXT: ret [[TMP4]] +// +// CPP-CHECK-LABEL: @_Z24test_svluti4_lane_zt_u16u11__SVUint8_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call { , } @llvm.aarch64.sme.luti4.lane.zt.x2.nxv8i16(i32 0, [[ZN:%.*]], i32 3) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv16i16.nxv8i16( poison, [[TMP1]], i64 0) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP0]], 1 +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv16i16.nxv8i16( [[TMP2]], [[TMP3]], i64 8) +// CPP-CHECK-NEXT: ret [[TMP4]] +// +svuint16x2_t test_svluti4_lane_zt_u16(svuint8_t zn) __arm_streaming __arm_shared_za __arm_preserves_za { + return svluti4_lane_zt_u16_x2(0, zn, 3); +} + + +// CHECK-LABEL: @test_svluti4_lane_zt_s16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call { , } @llvm.aarch64.sme.luti4.lane.zt.x2.nxv8i16(i32 0, [[ZN:%.*]], i32 3) +// CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv16i16.nxv8i16( poison, [[TMP1]], i64 0) +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP0]], 1 +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv16i16.nxv8i16( [[TMP2]], [[TMP3]], i64 8) +// CHECK-NEXT: ret [[TMP4]] +// +// CPP-CHECK-LABEL: @_Z24test_svluti4_lane_zt_s16u11__SVUint8_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call { , } @llvm.aarch64.sme.luti4.lane.zt.x2.nxv8i16(i32 0, [[ZN:%.*]], i32 3) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv16i16.nxv8i16( poison, [[TMP1]], i64 0) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP0]], 1 +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv16i16.nxv8i16( [[TMP2]], [[TMP3]], i64 8) +// CPP-CHECK-NEXT: ret [[TMP4]] +// +svint16x2_t test_svluti4_lane_zt_s16(svuint8_t zn) __arm_streaming __arm_shared_za __arm_preserves_za { + return svluti4_lane_zt_s16_x2(0, zn, 3); +} + +// CHECK-LABEL: @test_svluti4_lane_zt_f16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call { , } @llvm.aarch64.sme.luti4.lane.zt.x2.nxv8f16(i32 0, [[ZN:%.*]], i32 3) +// CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv16f16.nxv8f16( poison, [[TMP1]], i64 0) +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP0]], 1 +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv16f16.nxv8f16( [[TMP2]], [[TMP3]], i64 8) +// CHECK-NEXT: ret [[TMP4]] +// +// CPP-CHECK-LABEL: @_Z24test_svluti4_lane_zt_f16u11__SVUint8_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call { , } @llvm.aarch64.sme.luti4.lane.zt.x2.nxv8f16(i32 0, [[ZN:%.*]], i32 3) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv16f16.nxv8f16( poison, [[TMP1]], i64 0) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP0]], 1 +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv16f16.nxv8f16( [[TMP2]], [[TMP3]], i64 8) +// CPP-CHECK-NEXT: ret [[TMP4]] +// +svfloat16x2_t test_svluti4_lane_zt_f16(svuint8_t zn) __arm_streaming __arm_shared_za __arm_preserves_za { + return svluti4_lane_zt_f16_x2(0, zn, 3); +} + +// CHECK-LABEL: @test_svluti4_lane_zt_bf16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call { , } @llvm.aarch64.sme.luti4.lane.zt.x2.nxv8bf16(i32 0, [[ZN:%.*]], i32 3) +// CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( poison, [[TMP1]], i64 0) +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP0]], 1 +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( [[TMP2]], [[TMP3]], i64 8) +// CHECK-NEXT: ret [[TMP4]] +// +// CPP-CHECK-LABEL: @_Z25test_svluti4_lane_zt_bf16u11__SVUint8_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call { , } @llvm.aarch64.sme.luti4.lane.zt.x2.nxv8bf16(i32 0, [[ZN:%.*]], i32 3) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( poison, [[TMP1]], i64 0) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP0]], 1 +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv16bf16.nxv8bf16( [[TMP2]], [[TMP3]], i64 8) +// CPP-CHECK-NEXT: ret [[TMP4]] +// +svbfloat16x2_t test_svluti4_lane_zt_bf16(svuint8_t zn) __arm_streaming __arm_shared_za __arm_preserves_za { + return svluti4_lane_zt_bf16_x2(0, zn, 3); +} + +// CHECK-LABEL: @test_svluti4_lane_zt_u32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call { , } @llvm.aarch64.sme.luti4.lane.zt.x2.nxv4i32(i32 0, [[ZN:%.*]], i32 3) +// CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv8i32.nxv4i32( poison, [[TMP1]], i64 0) +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP0]], 1 +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv8i32.nxv4i32( [[TMP2]], [[TMP3]], i64 4) +// CHECK-NEXT: ret [[TMP4]] +// +// CPP-CHECK-LABEL: @_Z24test_svluti4_lane_zt_u32u11__SVUint8_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call { , } @llvm.aarch64.sme.luti4.lane.zt.x2.nxv4i32(i32 0, [[ZN:%.*]], i32 3) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv8i32.nxv4i32( poison, [[TMP1]], i64 0) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP0]], 1 +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv8i32.nxv4i32( [[TMP2]], [[TMP3]], i64 4) +// CPP-CHECK-NEXT: ret [[TMP4]] +// +svuint32x2_t test_svluti4_lane_zt_u32(svuint8_t zn) __arm_streaming __arm_shared_za __arm_preserves_za { + return svluti4_lane_zt_u32_x2(0, zn, 3); +} + +// CHECK-LABEL: @test_svluti4_lane_zt_s32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call { , } @llvm.aarch64.sme.luti4.lane.zt.x2.nxv4i32(i32 0, [[ZN:%.*]], i32 3) +// CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv8i32.nxv4i32( poison, [[TMP1]], i64 0) +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP0]], 1 +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv8i32.nxv4i32( [[TMP2]], [[TMP3]], i64 4) +// CHECK-NEXT: ret [[TMP4]] +// +// CPP-CHECK-LABEL: @_Z24test_svluti4_lane_zt_s32u11__SVUint8_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call { , } @llvm.aarch64.sme.luti4.lane.zt.x2.nxv4i32(i32 0, [[ZN:%.*]], i32 3) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv8i32.nxv4i32( poison, [[TMP1]], i64 0) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP0]], 1 +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv8i32.nxv4i32( [[TMP2]], [[TMP3]], i64 4) +// CPP-CHECK-NEXT: ret [[TMP4]] +// +svint32x2_t test_svluti4_lane_zt_s32(svuint8_t zn) __arm_streaming __arm_shared_za __arm_preserves_za { + return svluti4_lane_zt_s32_x2(0, zn, 3); +} + +// CHECK-LABEL: @test_svluti4_lane_zt_f32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call { , } @llvm.aarch64.sme.luti4.lane.zt.x2.nxv4f32(i32 0, [[ZN:%.*]], i32 3) +// CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv8f32.nxv4f32( poison, [[TMP1]], i64 0) +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP0]], 1 +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv8f32.nxv4f32( [[TMP2]], [[TMP3]], i64 4) +// CHECK-NEXT: ret [[TMP4]] +// +// CPP-CHECK-LABEL: @_Z24test_svluti4_lane_zt_f32u11__SVUint8_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call { , } @llvm.aarch64.sme.luti4.lane.zt.x2.nxv4f32(i32 0, [[ZN:%.*]], i32 3) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv8f32.nxv4f32( poison, [[TMP1]], i64 0) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP0]], 1 +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv8f32.nxv4f32( [[TMP2]], [[TMP3]], i64 4) +// CPP-CHECK-NEXT: ret [[TMP4]] +// +svfloat32x2_t test_svluti4_lane_zt_f32(svuint8_t zn) __arm_streaming __arm_shared_za __arm_preserves_za { + return svluti4_lane_zt_f32_x2(0, zn, 3); +} diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_luti4_lane_zt_x4.c b/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_luti4_lane_zt_x4.c new file mode 100644 index 0000000000000000000000000000000000000000..9baccef888d5840387eba399014a496d3a447f93 --- /dev/null +++ b/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_luti4_lane_zt_x4.c @@ -0,0 +1,233 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 2 + +// REQUIRES: aarch64-registered-target + +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme2 -target-feature +sve -S -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme2 -target-feature +sve -S -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme2 -target-feature +sve -S -disable-O0-optnone -Werror -Wall -o /dev/null %s + +#include + +// CHECK-LABEL: define dso_local @test_svluti4_lane_zt_u16 +// CHECK-SAME: ( [[ZN:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call { , , , } @llvm.aarch64.sme.luti4.lane.zt.x4.nxv8i16(i32 0, [[ZN]], i32 1) +// CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , , , } [[TMP0]], 0 +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv32i16.nxv8i16( poison, [[TMP1]], i64 0) +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , , , } [[TMP0]], 1 +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv32i16.nxv8i16( [[TMP2]], [[TMP3]], i64 8) +// CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP0]], 2 +// CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv32i16.nxv8i16( [[TMP4]], [[TMP5]], i64 16) +// CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP0]], 3 +// CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv32i16.nxv8i16( [[TMP6]], [[TMP7]], i64 24) +// CHECK-NEXT: ret [[TMP8]] +// +// CPP-CHECK-LABEL: define dso_local @_Z24test_svluti4_lane_zt_u16u11__SVUint8_t +// CPP-CHECK-SAME: ( [[ZN:%.*]]) #[[ATTR0:[0-9]+]] { +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call { , , , } @llvm.aarch64.sme.luti4.lane.zt.x4.nxv8i16(i32 0, [[ZN]], i32 1) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , , , } [[TMP0]], 0 +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv32i16.nxv8i16( poison, [[TMP1]], i64 0) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , , , } [[TMP0]], 1 +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv32i16.nxv8i16( [[TMP2]], [[TMP3]], i64 8) +// CPP-CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP0]], 2 +// CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv32i16.nxv8i16( [[TMP4]], [[TMP5]], i64 16) +// CPP-CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP0]], 3 +// CPP-CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv32i16.nxv8i16( [[TMP6]], [[TMP7]], i64 24) +// CPP-CHECK-NEXT: ret [[TMP8]] +// +svuint16x4_t test_svluti4_lane_zt_u16(svuint8_t zn) __arm_streaming __arm_shared_za __arm_preserves_za { + return svluti4_lane_zt_u16_x4(0, zn, 1); +} + +// CHECK-LABEL: define dso_local @test_svluti4_lane_zt_f16 +// CHECK-SAME: ( [[ZN:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call { , , , } @llvm.aarch64.sme.luti4.lane.zt.x4.nxv8f16(i32 0, [[ZN]], i32 1) +// CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , , , } [[TMP0]], 0 +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv32f16.nxv8f16( poison, [[TMP1]], i64 0) +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , , , } [[TMP0]], 1 +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv32f16.nxv8f16( [[TMP2]], [[TMP3]], i64 8) +// CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP0]], 2 +// CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv32f16.nxv8f16( [[TMP4]], [[TMP5]], i64 16) +// CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP0]], 3 +// CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv32f16.nxv8f16( [[TMP6]], [[TMP7]], i64 24) +// CHECK-NEXT: ret [[TMP8]] +// +// CPP-CHECK-LABEL: define dso_local @_Z24test_svluti4_lane_zt_f16u11__SVUint8_t +// CPP-CHECK-SAME: ( [[ZN:%.*]]) #[[ATTR0]] { +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call { , , , } @llvm.aarch64.sme.luti4.lane.zt.x4.nxv8f16(i32 0, [[ZN]], i32 1) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , , , } [[TMP0]], 0 +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv32f16.nxv8f16( poison, [[TMP1]], i64 0) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , , , } [[TMP0]], 1 +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv32f16.nxv8f16( [[TMP2]], [[TMP3]], i64 8) +// CPP-CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP0]], 2 +// CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv32f16.nxv8f16( [[TMP4]], [[TMP5]], i64 16) +// CPP-CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP0]], 3 +// CPP-CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv32f16.nxv8f16( [[TMP6]], [[TMP7]], i64 24) +// CPP-CHECK-NEXT: ret [[TMP8]] +// +svfloat16x4_t test_svluti4_lane_zt_f16(svuint8_t zn) __arm_streaming __arm_shared_za __arm_preserves_za { + return svluti4_lane_zt_f16_x4(0, zn, 1); +} + +// CHECK-LABEL: define dso_local @test_svluti4_lane_zt_bf16 +// CHECK-SAME: ( [[ZN:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call { , , , } @llvm.aarch64.sme.luti4.lane.zt.x4.nxv8bf16(i32 0, [[ZN]], i32 1) +// CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , , , } [[TMP0]], 0 +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( poison, [[TMP1]], i64 0) +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , , , } [[TMP0]], 1 +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP2]], [[TMP3]], i64 8) +// CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP0]], 2 +// CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP4]], [[TMP5]], i64 16) +// CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP0]], 3 +// CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP6]], [[TMP7]], i64 24) +// CHECK-NEXT: ret [[TMP8]] +// +// CPP-CHECK-LABEL: define dso_local @_Z25test_svluti4_lane_zt_bf16u11__SVUint8_t +// CPP-CHECK-SAME: ( [[ZN:%.*]]) #[[ATTR0]] { +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call { , , , } @llvm.aarch64.sme.luti4.lane.zt.x4.nxv8bf16(i32 0, [[ZN]], i32 1) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , , , } [[TMP0]], 0 +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( poison, [[TMP1]], i64 0) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , , , } [[TMP0]], 1 +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP2]], [[TMP3]], i64 8) +// CPP-CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP0]], 2 +// CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP4]], [[TMP5]], i64 16) +// CPP-CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP0]], 3 +// CPP-CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv32bf16.nxv8bf16( [[TMP6]], [[TMP7]], i64 24) +// CPP-CHECK-NEXT: ret [[TMP8]] +// +svbfloat16x4_t test_svluti4_lane_zt_bf16(svuint8_t zn) __arm_streaming __arm_shared_za __arm_preserves_za { + return svluti4_lane_zt_bf16_x4(0, zn, 1); +} + +// CHECK-LABEL: define dso_local @test_svluti4_lane_zt_s16 +// CHECK-SAME: ( [[ZN:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call { , , , } @llvm.aarch64.sme.luti4.lane.zt.x4.nxv8i16(i32 0, [[ZN]], i32 1) +// CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , , , } [[TMP0]], 0 +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv32i16.nxv8i16( poison, [[TMP1]], i64 0) +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , , , } [[TMP0]], 1 +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv32i16.nxv8i16( [[TMP2]], [[TMP3]], i64 8) +// CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP0]], 2 +// CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv32i16.nxv8i16( [[TMP4]], [[TMP5]], i64 16) +// CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP0]], 3 +// CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv32i16.nxv8i16( [[TMP6]], [[TMP7]], i64 24) +// CHECK-NEXT: ret [[TMP8]] +// +// CPP-CHECK-LABEL: define dso_local @_Z24test_svluti4_lane_zt_s16u11__SVUint8_t +// CPP-CHECK-SAME: ( [[ZN:%.*]]) #[[ATTR0]] { +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call { , , , } @llvm.aarch64.sme.luti4.lane.zt.x4.nxv8i16(i32 0, [[ZN]], i32 1) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , , , } [[TMP0]], 0 +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv32i16.nxv8i16( poison, [[TMP1]], i64 0) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , , , } [[TMP0]], 1 +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv32i16.nxv8i16( [[TMP2]], [[TMP3]], i64 8) +// CPP-CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP0]], 2 +// CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv32i16.nxv8i16( [[TMP4]], [[TMP5]], i64 16) +// CPP-CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP0]], 3 +// CPP-CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv32i16.nxv8i16( [[TMP6]], [[TMP7]], i64 24) +// CPP-CHECK-NEXT: ret [[TMP8]] +// +svint16x4_t test_svluti4_lane_zt_s16(svuint8_t zn) __arm_streaming __arm_shared_za __arm_preserves_za { + return svluti4_lane_zt_s16_x4(0, zn, 1); +} + +// CHECK-LABEL: define dso_local @test_svluti4_lane_zt_u32 +// CHECK-SAME: ( [[ZN:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call { , , , } @llvm.aarch64.sme.luti4.lane.zt.x4.nxv4i32(i32 0, [[ZN]], i32 1) +// CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , , , } [[TMP0]], 0 +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv16i32.nxv4i32( poison, [[TMP1]], i64 0) +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , , , } [[TMP0]], 1 +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv16i32.nxv4i32( [[TMP2]], [[TMP3]], i64 4) +// CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP0]], 2 +// CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv16i32.nxv4i32( [[TMP4]], [[TMP5]], i64 8) +// CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP0]], 3 +// CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv16i32.nxv4i32( [[TMP6]], [[TMP7]], i64 12) +// CHECK-NEXT: ret [[TMP8]] +// +// CPP-CHECK-LABEL: define dso_local @_Z24test_svluti4_lane_zt_u32u11__SVUint8_t +// CPP-CHECK-SAME: ( [[ZN:%.*]]) #[[ATTR0]] { +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call { , , , } @llvm.aarch64.sme.luti4.lane.zt.x4.nxv4i32(i32 0, [[ZN]], i32 1) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , , , } [[TMP0]], 0 +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv16i32.nxv4i32( poison, [[TMP1]], i64 0) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , , , } [[TMP0]], 1 +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv16i32.nxv4i32( [[TMP2]], [[TMP3]], i64 4) +// CPP-CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP0]], 2 +// CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv16i32.nxv4i32( [[TMP4]], [[TMP5]], i64 8) +// CPP-CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP0]], 3 +// CPP-CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv16i32.nxv4i32( [[TMP6]], [[TMP7]], i64 12) +// CPP-CHECK-NEXT: ret [[TMP8]] +// +svuint32x4_t test_svluti4_lane_zt_u32(svuint8_t zn) __arm_streaming __arm_shared_za __arm_preserves_za { + return svluti4_lane_zt_u32_x4(0, zn, 1); +} + +// CHECK-LABEL: define dso_local @test_svluti4_lane_zt_s32 +// CHECK-SAME: ( [[ZN:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call { , , , } @llvm.aarch64.sme.luti4.lane.zt.x4.nxv4i32(i32 0, [[ZN]], i32 1) +// CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , , , } [[TMP0]], 0 +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv16i32.nxv4i32( poison, [[TMP1]], i64 0) +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , , , } [[TMP0]], 1 +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv16i32.nxv4i32( [[TMP2]], [[TMP3]], i64 4) +// CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP0]], 2 +// CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv16i32.nxv4i32( [[TMP4]], [[TMP5]], i64 8) +// CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP0]], 3 +// CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv16i32.nxv4i32( [[TMP6]], [[TMP7]], i64 12) +// CHECK-NEXT: ret [[TMP8]] +// +// CPP-CHECK-LABEL: define dso_local @_Z24test_svluti4_lane_zt_s32u11__SVUint8_t +// CPP-CHECK-SAME: ( [[ZN:%.*]]) #[[ATTR0]] { +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call { , , , } @llvm.aarch64.sme.luti4.lane.zt.x4.nxv4i32(i32 0, [[ZN]], i32 1) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , , , } [[TMP0]], 0 +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv16i32.nxv4i32( poison, [[TMP1]], i64 0) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , , , } [[TMP0]], 1 +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv16i32.nxv4i32( [[TMP2]], [[TMP3]], i64 4) +// CPP-CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP0]], 2 +// CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv16i32.nxv4i32( [[TMP4]], [[TMP5]], i64 8) +// CPP-CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP0]], 3 +// CPP-CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv16i32.nxv4i32( [[TMP6]], [[TMP7]], i64 12) +// CPP-CHECK-NEXT: ret [[TMP8]] +// +svint32x4_t test_svluti4_lane_zt_s32(svuint8_t zn) __arm_streaming __arm_shared_za __arm_preserves_za { + return svluti4_lane_zt_s32_x4(0, zn, 1); +} + +// CHECK-LABEL: define dso_local @test_svluti4_lane_zt_f32 +// CHECK-SAME: ( [[ZN:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call { , , , } @llvm.aarch64.sme.luti4.lane.zt.x4.nxv4f32(i32 0, [[ZN]], i32 1) +// CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , , , } [[TMP0]], 0 +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv16f32.nxv4f32( poison, [[TMP1]], i64 0) +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , , , } [[TMP0]], 1 +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv16f32.nxv4f32( [[TMP2]], [[TMP3]], i64 4) +// CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP0]], 2 +// CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv16f32.nxv4f32( [[TMP4]], [[TMP5]], i64 8) +// CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP0]], 3 +// CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv16f32.nxv4f32( [[TMP6]], [[TMP7]], i64 12) +// CHECK-NEXT: ret [[TMP8]] +// +// CPP-CHECK-LABEL: define dso_local @_Z24test_svluti4_lane_zt_f32u11__SVUint8_t +// CPP-CHECK-SAME: ( [[ZN:%.*]]) #[[ATTR0]] { +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call { , , , } @llvm.aarch64.sme.luti4.lane.zt.x4.nxv4f32(i32 0, [[ZN]], i32 1) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , , , } [[TMP0]], 0 +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv16f32.nxv4f32( poison, [[TMP1]], i64 0) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , , , } [[TMP0]], 1 +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv16f32.nxv4f32( [[TMP2]], [[TMP3]], i64 4) +// CPP-CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP0]], 2 +// CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv16f32.nxv4f32( [[TMP4]], [[TMP5]], i64 8) +// CPP-CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP0]], 3 +// CPP-CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv16f32.nxv4f32( [[TMP6]], [[TMP7]], i64 12) +// CPP-CHECK-NEXT: ret [[TMP8]] +// +svfloat32x4_t test_svluti4_lane_zt_f32(svuint8_t zn) __arm_streaming __arm_shared_za __arm_preserves_za { + return svluti4_lane_zt_f32_x4(0, zn, 1); +} diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_reinterpret_svcount_svbool.c b/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_reinterpret_svcount_svbool.c new file mode 100644 index 0000000000000000000000000000000000000000..82b30e8bbe9b93a0f7ddb71576f6ebe0f65df338 --- /dev/null +++ b/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_reinterpret_svcount_svbool.c @@ -0,0 +1,47 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py + +// REQUIRES: aarch64-registered-target + +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +sme2 -S -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +sme2 -S -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK +// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +sme2 -S -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s +// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +sme2 -S -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK + +#include + +#ifdef SVE_OVERLOADED_FORMS +// A simple used,unused... macro, long enough to represent any SVE builtin.§ +#define SVE_ACLE_FUNC(A1,A2_UNUSED,A3,A4_UNUSED) A1##A3 +#else +#define SVE_ACLE_FUNC(A1,A2,A3,A4) A1##A2##A3##A4 +#endif + +// CHECK-LABEL: @test_svreinterpret_svbool_svcnt( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.to.svbool.taarch64.svcountt(target("aarch64.svcount") [[CNT:%.*]]) +// CHECK-NEXT: ret [[TMP0]] +// +// CPP-CHECK-LABEL: @_Z31test_svreinterpret_svbool_svcntu11__SVCount_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.to.svbool.taarch64.svcountt(target("aarch64.svcount") [[CNT:%.*]]) +// CPP-CHECK-NEXT: ret [[TMP0]] +// +svbool_t test_svreinterpret_svbool_svcnt(svcount_t cnt) __arm_streaming_compatible +{ + return SVE_ACLE_FUNC(svreinterpret,_b,,)(cnt); +} + +// CHECK-LABEL: @test_svreinterpret_svcnt_svbool( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call target("aarch64.svcount") @llvm.aarch64.sve.convert.from.svbool.taarch64.svcountt( [[PG:%.*]]) +// CHECK-NEXT: ret target("aarch64.svcount") [[TMP0]] +// +// CPP-CHECK-LABEL: @_Z31test_svreinterpret_svcnt_svboolu10__SVBool_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call target("aarch64.svcount") @llvm.aarch64.sve.convert.from.svbool.taarch64.svcountt( [[PG:%.*]]) +// CPP-CHECK-NEXT: ret target("aarch64.svcount") [[TMP0]] +// +svcount_t test_svreinterpret_svcnt_svbool(svbool_t pg) __arm_streaming_compatible +{ + return SVE_ACLE_FUNC(svreinterpret,_c,,)(pg); +} diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_unpkx2.c b/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_unpkx2.c new file mode 100644 index 0000000000000000000000000000000000000000..2f427689323b482d11a2e76d4cc6d1ecd3bca9e7 --- /dev/null +++ b/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_unpkx2.c @@ -0,0 +1,150 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py + +// REQUIRES: aarch64-registered-target + +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +sme2 -S -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +sme2 -S -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK +// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +sme2 -S -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s +// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +sme2 -S -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +sme2 -target-feature -S -disable-O0-optnone -Werror -Wall -o /dev/null %s +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +sme2 -S -disable-O0-optnone -Werror -Wall -o /dev/null %s +#include + +#ifdef SVE_OVERLOADED_FORMS +// A simple used,unused... macro, long enough to represent any SVE builtin. +#define SVE_ACLE_FUNC(A1,A2_UNUSED) A1 +#else +#define SVE_ACLE_FUNC(A1,A2) A1##A2 +#endif + +// CHECK-LABEL: @test_svunpk_s16_x2( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call { , } @llvm.aarch64.sve.sunpk.x2.nxv8i16( [[ZN:%.*]]) +// CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv16i16.nxv8i16( poison, [[TMP1]], i64 0) +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP0]], 1 +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv16i16.nxv8i16( [[TMP2]], [[TMP3]], i64 8) +// CHECK-NEXT: ret [[TMP4]] +// +// CPP-CHECK-LABEL: @_Z18test_svunpk_s16_x2u10__SVInt8_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call { , } @llvm.aarch64.sve.sunpk.x2.nxv8i16( [[ZN:%.*]]) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv16i16.nxv8i16( poison, [[TMP1]], i64 0) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP0]], 1 +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv16i16.nxv8i16( [[TMP2]], [[TMP3]], i64 8) +// CPP-CHECK-NEXT: ret [[TMP4]] +// +svint16x2_t test_svunpk_s16_x2(svint8_t zn) __arm_streaming { + return SVE_ACLE_FUNC(svunpk_s16,_s8_x2)(zn); +} + +// CHECK-LABEL: @test_svunpk_u16_x2( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call { , } @llvm.aarch64.sve.uunpk.x2.nxv8i16( [[ZN:%.*]]) +// CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv16i16.nxv8i16( poison, [[TMP1]], i64 0) +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP0]], 1 +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv16i16.nxv8i16( [[TMP2]], [[TMP3]], i64 8) +// CHECK-NEXT: ret [[TMP4]] +// +// CPP-CHECK-LABEL: @_Z18test_svunpk_u16_x2u11__SVUint8_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call { , } @llvm.aarch64.sve.uunpk.x2.nxv8i16( [[ZN:%.*]]) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv16i16.nxv8i16( poison, [[TMP1]], i64 0) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP0]], 1 +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv16i16.nxv8i16( [[TMP2]], [[TMP3]], i64 8) +// CPP-CHECK-NEXT: ret [[TMP4]] +// +svuint16x2_t test_svunpk_u16_x2(svuint8_t zn) __arm_streaming { + return SVE_ACLE_FUNC(svunpk_u16,_u8_x2)(zn); +} + +// CHECK-LABEL: @test_svunpk_s32_x2( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call { , } @llvm.aarch64.sve.sunpk.x2.nxv4i32( [[ZN:%.*]]) +// CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv8i32.nxv4i32( poison, [[TMP1]], i64 0) +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP0]], 1 +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv8i32.nxv4i32( [[TMP2]], [[TMP3]], i64 4) +// CHECK-NEXT: ret [[TMP4]] +// +// CPP-CHECK-LABEL: @_Z18test_svunpk_s32_x2u11__SVInt16_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call { , } @llvm.aarch64.sve.sunpk.x2.nxv4i32( [[ZN:%.*]]) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv8i32.nxv4i32( poison, [[TMP1]], i64 0) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP0]], 1 +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv8i32.nxv4i32( [[TMP2]], [[TMP3]], i64 4) +// CPP-CHECK-NEXT: ret [[TMP4]] +// +svint32x2_t test_svunpk_s32_x2(svint16_t zn) __arm_streaming { + return SVE_ACLE_FUNC(svunpk_s32,_s16_x2)(zn); +} + +// CHECK-LABEL: @test_svunpk_u32_x2( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call { , } @llvm.aarch64.sve.uunpk.x2.nxv4i32( [[ZN:%.*]]) +// CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv8i32.nxv4i32( poison, [[TMP1]], i64 0) +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP0]], 1 +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv8i32.nxv4i32( [[TMP2]], [[TMP3]], i64 4) +// CHECK-NEXT: ret [[TMP4]] +// +// CPP-CHECK-LABEL: @_Z18test_svunpk_u32_x2u12__SVUint16_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call { , } @llvm.aarch64.sve.uunpk.x2.nxv4i32( [[ZN:%.*]]) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv8i32.nxv4i32( poison, [[TMP1]], i64 0) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP0]], 1 +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv8i32.nxv4i32( [[TMP2]], [[TMP3]], i64 4) +// CPP-CHECK-NEXT: ret [[TMP4]] +// +svuint32x2_t test_svunpk_u32_x2(svuint16_t zn) __arm_streaming { + return SVE_ACLE_FUNC(svunpk_u32,_u16_x2)(zn); +} + +// CHECK-LABEL: @test_svunpk_s64_x2( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call { , } @llvm.aarch64.sve.sunpk.x2.nxv2i64( [[ZN:%.*]]) +// CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv4i64.nxv2i64( poison, [[TMP1]], i64 0) +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP0]], 1 +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv4i64.nxv2i64( [[TMP2]], [[TMP3]], i64 2) +// CHECK-NEXT: ret [[TMP4]] +// +// CPP-CHECK-LABEL: @_Z18test_svunpk_s64_x2u11__SVInt32_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call { , } @llvm.aarch64.sve.sunpk.x2.nxv2i64( [[ZN:%.*]]) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv4i64.nxv2i64( poison, [[TMP1]], i64 0) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP0]], 1 +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv4i64.nxv2i64( [[TMP2]], [[TMP3]], i64 2) +// CPP-CHECK-NEXT: ret [[TMP4]] +// +svint64x2_t test_svunpk_s64_x2(svint32_t zn) __arm_streaming { + return SVE_ACLE_FUNC(svunpk_s64,_s32_x2)(zn); +} + +// CHECK-LABEL: @test_svunpk_u64_x2( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call { , } @llvm.aarch64.sve.uunpk.x2.nxv2i64( [[ZN:%.*]]) +// CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv4i64.nxv2i64( poison, [[TMP1]], i64 0) +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP0]], 1 +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv4i64.nxv2i64( [[TMP2]], [[TMP3]], i64 2) +// CHECK-NEXT: ret [[TMP4]] +// +// CPP-CHECK-LABEL: @_Z18test_svunpk_u64_x2u12__SVUint32_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call { , } @llvm.aarch64.sve.uunpk.x2.nxv2i64( [[ZN:%.*]]) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv4i64.nxv2i64( poison, [[TMP1]], i64 0) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP0]], 1 +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv4i64.nxv2i64( [[TMP2]], [[TMP3]], i64 2) +// CPP-CHECK-NEXT: ret [[TMP4]] +// +svuint64x2_t test_svunpk_u64_x2(svuint32_t zn) __arm_streaming { + return SVE_ACLE_FUNC(svunpk_u64,_u32_x2)(zn); +} diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_unpkx4.c b/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_unpkx4.c new file mode 100644 index 0000000000000000000000000000000000000000..cdcc62d5405e6e623a62249d489d5232199d4155 --- /dev/null +++ b/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_unpkx4.c @@ -0,0 +1,222 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py + +// REQUIRES: aarch64-registered-target + +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +sme2 -S -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +sme2 -S -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK +// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +sme2 -S -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s +// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +sme2 -S -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +sme2 -target-feature -S -disable-O0-optnone -Werror -Wall -o /dev/null %s +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +sme2 -S -disable-O0-optnone -Werror -Wall -o /dev/null %s +#include + +#ifdef SVE_OVERLOADED_FORMS +// A simple used,unused... macro, long enough to represent any SVE builtin. +#define SVE_ACLE_FUNC(A1,A2_UNUSED) A1 +#else +#define SVE_ACLE_FUNC(A1,A2) A1##A2 +#endif + +// CHECK-LABEL: @test_svunpk_s16_x4( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv16i8.nxv32i8( [[ZN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv16i8.nxv32i8( [[ZN]], i64 16) +// CHECK-NEXT: [[TMP2:%.*]] = tail call { , , , } @llvm.aarch64.sve.sunpk.x4.nxv8i16( [[TMP0]], [[TMP1]]) +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , , , } [[TMP2]], 0 +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv32i16.nxv8i16( poison, [[TMP3]], i64 0) +// CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP2]], 1 +// CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv32i16.nxv8i16( [[TMP4]], [[TMP5]], i64 8) +// CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP2]], 2 +// CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv32i16.nxv8i16( [[TMP6]], [[TMP7]], i64 16) +// CHECK-NEXT: [[TMP9:%.*]] = extractvalue { , , , } [[TMP2]], 3 +// CHECK-NEXT: [[TMP10:%.*]] = tail call @llvm.vector.insert.nxv32i16.nxv8i16( [[TMP8]], [[TMP9]], i64 24) +// CHECK-NEXT: ret [[TMP10]] +// +// CPP-CHECK-LABEL: @_Z18test_svunpk_s16_x410svint8x2_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv16i8.nxv32i8( [[ZN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv16i8.nxv32i8( [[ZN]], i64 16) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call { , , , } @llvm.aarch64.sve.sunpk.x4.nxv8i16( [[TMP0]], [[TMP1]]) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , , , } [[TMP2]], 0 +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv32i16.nxv8i16( poison, [[TMP3]], i64 0) +// CPP-CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP2]], 1 +// CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv32i16.nxv8i16( [[TMP4]], [[TMP5]], i64 8) +// CPP-CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP2]], 2 +// CPP-CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv32i16.nxv8i16( [[TMP6]], [[TMP7]], i64 16) +// CPP-CHECK-NEXT: [[TMP9:%.*]] = extractvalue { , , , } [[TMP2]], 3 +// CPP-CHECK-NEXT: [[TMP10:%.*]] = tail call @llvm.vector.insert.nxv32i16.nxv8i16( [[TMP8]], [[TMP9]], i64 24) +// CPP-CHECK-NEXT: ret [[TMP10]] +// +svint16x4_t test_svunpk_s16_x4(svint8x2_t zn) __arm_streaming { + return SVE_ACLE_FUNC(svunpk_s16,_s8_x4)(zn); +} + +// CHECK-LABEL: @test_svunpk_u16_x4( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv16i8.nxv32i8( [[ZN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv16i8.nxv32i8( [[ZN]], i64 16) +// CHECK-NEXT: [[TMP2:%.*]] = tail call { , , , } @llvm.aarch64.sve.uunpk.x4.nxv8i16( [[TMP0]], [[TMP1]]) +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , , , } [[TMP2]], 0 +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv32i16.nxv8i16( poison, [[TMP3]], i64 0) +// CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP2]], 1 +// CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv32i16.nxv8i16( [[TMP4]], [[TMP5]], i64 8) +// CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP2]], 2 +// CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv32i16.nxv8i16( [[TMP6]], [[TMP7]], i64 16) +// CHECK-NEXT: [[TMP9:%.*]] = extractvalue { , , , } [[TMP2]], 3 +// CHECK-NEXT: [[TMP10:%.*]] = tail call @llvm.vector.insert.nxv32i16.nxv8i16( [[TMP8]], [[TMP9]], i64 24) +// CHECK-NEXT: ret [[TMP10]] +// +// CPP-CHECK-LABEL: @_Z18test_svunpk_u16_x411svuint8x2_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv16i8.nxv32i8( [[ZN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv16i8.nxv32i8( [[ZN]], i64 16) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call { , , , } @llvm.aarch64.sve.uunpk.x4.nxv8i16( [[TMP0]], [[TMP1]]) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , , , } [[TMP2]], 0 +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv32i16.nxv8i16( poison, [[TMP3]], i64 0) +// CPP-CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP2]], 1 +// CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv32i16.nxv8i16( [[TMP4]], [[TMP5]], i64 8) +// CPP-CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP2]], 2 +// CPP-CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv32i16.nxv8i16( [[TMP6]], [[TMP7]], i64 16) +// CPP-CHECK-NEXT: [[TMP9:%.*]] = extractvalue { , , , } [[TMP2]], 3 +// CPP-CHECK-NEXT: [[TMP10:%.*]] = tail call @llvm.vector.insert.nxv32i16.nxv8i16( [[TMP8]], [[TMP9]], i64 24) +// CPP-CHECK-NEXT: ret [[TMP10]] +// +svuint16x4_t test_svunpk_u16_x4(svuint8x2_t zn) __arm_streaming { + return SVE_ACLE_FUNC(svunpk_u16,_u8_x4)(zn); +} + +// CHECK-LABEL: @test_svunpk_s32_x4( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8i16.nxv16i16( [[ZN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8i16.nxv16i16( [[ZN]], i64 8) +// CHECK-NEXT: [[TMP2:%.*]] = tail call { , , , } @llvm.aarch64.sve.sunpk.x4.nxv4i32( [[TMP0]], [[TMP1]]) +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , , , } [[TMP2]], 0 +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv16i32.nxv4i32( poison, [[TMP3]], i64 0) +// CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP2]], 1 +// CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv16i32.nxv4i32( [[TMP4]], [[TMP5]], i64 4) +// CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP2]], 2 +// CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv16i32.nxv4i32( [[TMP6]], [[TMP7]], i64 8) +// CHECK-NEXT: [[TMP9:%.*]] = extractvalue { , , , } [[TMP2]], 3 +// CHECK-NEXT: [[TMP10:%.*]] = tail call @llvm.vector.insert.nxv16i32.nxv4i32( [[TMP8]], [[TMP9]], i64 12) +// CHECK-NEXT: ret [[TMP10]] +// +// CPP-CHECK-LABEL: @_Z18test_svunpk_s32_x411svint16x2_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8i16.nxv16i16( [[ZN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8i16.nxv16i16( [[ZN]], i64 8) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call { , , , } @llvm.aarch64.sve.sunpk.x4.nxv4i32( [[TMP0]], [[TMP1]]) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , , , } [[TMP2]], 0 +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv16i32.nxv4i32( poison, [[TMP3]], i64 0) +// CPP-CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP2]], 1 +// CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv16i32.nxv4i32( [[TMP4]], [[TMP5]], i64 4) +// CPP-CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP2]], 2 +// CPP-CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv16i32.nxv4i32( [[TMP6]], [[TMP7]], i64 8) +// CPP-CHECK-NEXT: [[TMP9:%.*]] = extractvalue { , , , } [[TMP2]], 3 +// CPP-CHECK-NEXT: [[TMP10:%.*]] = tail call @llvm.vector.insert.nxv16i32.nxv4i32( [[TMP8]], [[TMP9]], i64 12) +// CPP-CHECK-NEXT: ret [[TMP10]] +// +svint32x4_t test_svunpk_s32_x4(svint16x2_t zn) __arm_streaming { + return SVE_ACLE_FUNC(svunpk_s32,_s16_x4)(zn); +} + +// CHECK-LABEL: @test_svunpk_u32_x4( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8i16.nxv16i16( [[ZN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8i16.nxv16i16( [[ZN]], i64 8) +// CHECK-NEXT: [[TMP2:%.*]] = tail call { , , , } @llvm.aarch64.sve.uunpk.x4.nxv4i32( [[TMP0]], [[TMP1]]) +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , , , } [[TMP2]], 0 +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv16i32.nxv4i32( poison, [[TMP3]], i64 0) +// CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP2]], 1 +// CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv16i32.nxv4i32( [[TMP4]], [[TMP5]], i64 4) +// CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP2]], 2 +// CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv16i32.nxv4i32( [[TMP6]], [[TMP7]], i64 8) +// CHECK-NEXT: [[TMP9:%.*]] = extractvalue { , , , } [[TMP2]], 3 +// CHECK-NEXT: [[TMP10:%.*]] = tail call @llvm.vector.insert.nxv16i32.nxv4i32( [[TMP8]], [[TMP9]], i64 12) +// CHECK-NEXT: ret [[TMP10]] +// +// CPP-CHECK-LABEL: @_Z18test_svunpk_u32_x412svuint16x2_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv8i16.nxv16i16( [[ZN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv8i16.nxv16i16( [[ZN]], i64 8) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call { , , , } @llvm.aarch64.sve.uunpk.x4.nxv4i32( [[TMP0]], [[TMP1]]) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , , , } [[TMP2]], 0 +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv16i32.nxv4i32( poison, [[TMP3]], i64 0) +// CPP-CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP2]], 1 +// CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv16i32.nxv4i32( [[TMP4]], [[TMP5]], i64 4) +// CPP-CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP2]], 2 +// CPP-CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv16i32.nxv4i32( [[TMP6]], [[TMP7]], i64 8) +// CPP-CHECK-NEXT: [[TMP9:%.*]] = extractvalue { , , , } [[TMP2]], 3 +// CPP-CHECK-NEXT: [[TMP10:%.*]] = tail call @llvm.vector.insert.nxv16i32.nxv4i32( [[TMP8]], [[TMP9]], i64 12) +// CPP-CHECK-NEXT: ret [[TMP10]] +// +svuint32x4_t test_svunpk_u32_x4(svuint16x2_t zn) __arm_streaming { + return SVE_ACLE_FUNC(svunpk_u32,_u16_x4)(zn); +} + +// CHECK-LABEL: @test_svunpk_s64_x4( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv8i32( [[ZN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv8i32( [[ZN]], i64 4) +// CHECK-NEXT: [[TMP2:%.*]] = tail call { , , , } @llvm.aarch64.sve.sunpk.x4.nxv2i64( [[TMP0]], [[TMP1]]) +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , , , } [[TMP2]], 0 +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv8i64.nxv2i64( poison, [[TMP3]], i64 0) +// CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP2]], 1 +// CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv8i64.nxv2i64( [[TMP4]], [[TMP5]], i64 2) +// CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP2]], 2 +// CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv8i64.nxv2i64( [[TMP6]], [[TMP7]], i64 4) +// CHECK-NEXT: [[TMP9:%.*]] = extractvalue { , , , } [[TMP2]], 3 +// CHECK-NEXT: [[TMP10:%.*]] = tail call @llvm.vector.insert.nxv8i64.nxv2i64( [[TMP8]], [[TMP9]], i64 6) +// CHECK-NEXT: ret [[TMP10]] +// +// CPP-CHECK-LABEL: @_Z18test_svunpk_s64_x411svint32x2_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv8i32( [[ZN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv8i32( [[ZN]], i64 4) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call { , , , } @llvm.aarch64.sve.sunpk.x4.nxv2i64( [[TMP0]], [[TMP1]]) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , , , } [[TMP2]], 0 +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv8i64.nxv2i64( poison, [[TMP3]], i64 0) +// CPP-CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP2]], 1 +// CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv8i64.nxv2i64( [[TMP4]], [[TMP5]], i64 2) +// CPP-CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP2]], 2 +// CPP-CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv8i64.nxv2i64( [[TMP6]], [[TMP7]], i64 4) +// CPP-CHECK-NEXT: [[TMP9:%.*]] = extractvalue { , , , } [[TMP2]], 3 +// CPP-CHECK-NEXT: [[TMP10:%.*]] = tail call @llvm.vector.insert.nxv8i64.nxv2i64( [[TMP8]], [[TMP9]], i64 6) +// CPP-CHECK-NEXT: ret [[TMP10]] +// +svint64x4_t test_svunpk_s64_x4(svint32x2_t zn) __arm_streaming { + return SVE_ACLE_FUNC(svunpk_s64,_s32_x4)(zn); +} + +// CHECK-LABEL: @test_svunpk_u64_x4( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv8i32( [[ZN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv8i32( [[ZN]], i64 4) +// CHECK-NEXT: [[TMP2:%.*]] = tail call { , , , } @llvm.aarch64.sve.uunpk.x4.nxv2i64( [[TMP0]], [[TMP1]]) +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , , , } [[TMP2]], 0 +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv8i64.nxv2i64( poison, [[TMP3]], i64 0) +// CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP2]], 1 +// CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv8i64.nxv2i64( [[TMP4]], [[TMP5]], i64 2) +// CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP2]], 2 +// CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv8i64.nxv2i64( [[TMP6]], [[TMP7]], i64 4) +// CHECK-NEXT: [[TMP9:%.*]] = extractvalue { , , , } [[TMP2]], 3 +// CHECK-NEXT: [[TMP10:%.*]] = tail call @llvm.vector.insert.nxv8i64.nxv2i64( [[TMP8]], [[TMP9]], i64 6) +// CHECK-NEXT: ret [[TMP10]] +// +// CPP-CHECK-LABEL: @_Z18test_svunpk_u64_x412svuint32x2_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv8i32( [[ZN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv8i32( [[ZN]], i64 4) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call { , , , } @llvm.aarch64.sve.uunpk.x4.nxv2i64( [[TMP0]], [[TMP1]]) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , , , } [[TMP2]], 0 +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv8i64.nxv2i64( poison, [[TMP3]], i64 0) +// CPP-CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP2]], 1 +// CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv8i64.nxv2i64( [[TMP4]], [[TMP5]], i64 2) +// CPP-CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP2]], 2 +// CPP-CHECK-NEXT: [[TMP8:%.*]] = tail call @llvm.vector.insert.nxv8i64.nxv2i64( [[TMP6]], [[TMP7]], i64 4) +// CPP-CHECK-NEXT: [[TMP9:%.*]] = extractvalue { , , , } [[TMP2]], 3 +// CPP-CHECK-NEXT: [[TMP10:%.*]] = tail call @llvm.vector.insert.nxv8i64.nxv2i64( [[TMP8]], [[TMP9]], i64 6) +// CPP-CHECK-NEXT: ret [[TMP10]] +// +svuint64x4_t test_svunpk_u64_x4(svuint32x2_t zn) __arm_streaming { + return SVE_ACLE_FUNC(svunpk_u64,_u32_x4)(zn); +} diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_vector_qrshr.c b/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_vector_qrshr.c new file mode 100644 index 0000000000000000000000000000000000000000..50cac4888789461261e627581164af3aaeb6ff12 --- /dev/null +++ b/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_vector_qrshr.c @@ -0,0 +1,343 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// REQUIRES: aarch64-registered-target + +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +sme2 -S -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -passes=mem2reg,instcombine,tailcallelim | FileCheck %s +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +sme2 -S -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s | opt -S -passes=mem2reg,instcombine,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK +// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +sme2 -S -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -passes=mem2reg,instcombine,tailcallelim | FileCheck %s +// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +sme2 -S -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s | opt -S -passes=mem2reg,instcombine,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +sme2 -target-feature +sme-f64f64 -S -disable-O0-optnone -Werror -Wall -o /dev/null %s + +#include + +#ifdef SVE_OVERLOADED_FORMS +// A simple used,unused... macro, long enough to represent any SVE builtin. +#define SVE_ACLE_FUNC(A1,A2_UNUSED,A3,A4_UNUSED,A5) A1##A3##A5 +#else +#define SVE_ACLE_FUNC(A1,A2,A3,A4,A5) A1##A2##A3##A4##A5 +#endif + +// SVQRSHR + +// CHECK-LABEL: @test_svsqrshr_u16_u32_x4( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv8i32( [[ZN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv8i32( [[ZN]], i64 4) +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.aarch64.sve.uqrshr.x2.nxv4i32( [[TMP0]], [[TMP1]], i32 16) +// CHECK-NEXT: ret [[TMP2]] +// +// CPP-CHECK-LABEL: @_Z24test_svsqrshr_u16_u32_x412svuint32x2_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv8i32( [[ZN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv8i32( [[ZN]], i64 4) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.aarch64.sve.uqrshr.x2.nxv4i32( [[TMP0]], [[TMP1]], i32 16) +// CPP-CHECK-NEXT: ret [[TMP2]] +// +svuint16_t test_svsqrshr_u16_u32_x4(svuint32x2_t zn) __arm_streaming { + return SVE_ACLE_FUNC(svqrshr,_n,_u16,_u32_x2,)(zn, 16); +} + +// CHECK-LABEL: @test_svsqrshr_s16_s32_x4( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv8i32( [[ZN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv8i32( [[ZN]], i64 4) +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.aarch64.sve.sqrshr.x2.nxv4i32( [[TMP0]], [[TMP1]], i32 16) +// CHECK-NEXT: ret [[TMP2]] +// +// CPP-CHECK-LABEL: @_Z24test_svsqrshr_s16_s32_x411svint32x2_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv8i32( [[ZN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv8i32( [[ZN]], i64 4) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.aarch64.sve.sqrshr.x2.nxv4i32( [[TMP0]], [[TMP1]], i32 16) +// CPP-CHECK-NEXT: ret [[TMP2]] +// +svint16_t test_svsqrshr_s16_s32_x4(svint32x2_t zn) __arm_streaming { + return SVE_ACLE_FUNC(svqrshr,_n,_s16,_s32_x2,)(zn, 16); +} + +// CHECK-LABEL: @test_svsqrshr_u8_u32_x4( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 4) +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 8) +// CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 12) +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.aarch64.sve.uqrshr.x4.nxv4i32( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]], i32 8) +// CHECK-NEXT: ret [[TMP4]] +// +// CPP-CHECK-LABEL: @_Z23test_svsqrshr_u8_u32_x412svuint32x4_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 4) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 8) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 12) +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.aarch64.sve.uqrshr.x4.nxv4i32( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]], i32 8) +// CPP-CHECK-NEXT: ret [[TMP4]] +// +svuint8_t test_svsqrshr_u8_u32_x4(svuint32x4_t zn) __arm_streaming { + return SVE_ACLE_FUNC(svqrshr,_n,_u8,_u32_x4,)(zn, 8); +} + +// CHECK-LABEL: @test_svsqrshr_s8_s32_x4( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 4) +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 8) +// CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 12) +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.aarch64.sve.sqrshr.x4.nxv4i32( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]], i32 8) +// CHECK-NEXT: ret [[TMP4]] +// +// CPP-CHECK-LABEL: @_Z23test_svsqrshr_s8_s32_x411svint32x4_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 4) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 8) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 12) +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.aarch64.sve.sqrshr.x4.nxv4i32( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]], i32 8) +// CPP-CHECK-NEXT: ret [[TMP4]] +// +svint8_t test_svsqrshr_s8_s32_x4(svint32x4_t zn) __arm_streaming { + return SVE_ACLE_FUNC(svqrshr,_n,_s8,_s32_x4,)(zn, 8); +} + +// CHECK-LABEL: @test_svsqrshr_u16_u64_x4( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 2) +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 4) +// CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 6) +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.aarch64.sve.uqrshr.x4.nxv2i64( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]], i32 16) +// CHECK-NEXT: ret [[TMP4]] +// +// CPP-CHECK-LABEL: @_Z24test_svsqrshr_u16_u64_x412svuint64x4_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 2) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 4) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 6) +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.aarch64.sve.uqrshr.x4.nxv2i64( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]], i32 16) +// CPP-CHECK-NEXT: ret [[TMP4]] +// +svuint16_t test_svsqrshr_u16_u64_x4(svuint64x4_t zn) __arm_streaming { + return SVE_ACLE_FUNC(svqrshr,_n,_u16,_u64_x4,)(zn, 16); +} + +// CHECK-LABEL: @test_svsqrshr_s16_s64_x4( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 2) +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 4) +// CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 6) +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.aarch64.sve.sqrshr.x4.nxv2i64( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]], i32 16) +// CHECK-NEXT: ret [[TMP4]] +// +// CPP-CHECK-LABEL: @_Z24test_svsqrshr_s16_s64_x411svint64x4_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 2) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 4) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 6) +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.aarch64.sve.sqrshr.x4.nxv2i64( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]], i32 16) +// CPP-CHECK-NEXT: ret [[TMP4]] +// +svint16_t test_svsqrshr_s16_s64_x4(svint64x4_t zn) __arm_streaming { + return SVE_ACLE_FUNC(svqrshr,_n,_s16,_s64_x4,)(zn, 16); +} + +// SVQRSHRN + +// CHECK-LABEL: @test_svsqrshrn_u8_u32_x4( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 4) +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 8) +// CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 12) +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.aarch64.sve.uqrshrn.x4.nxv4i32( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]], i32 8) +// CHECK-NEXT: ret [[TMP4]] +// +// CPP-CHECK-LABEL: @_Z24test_svsqrshrn_u8_u32_x412svuint32x4_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 4) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 8) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 12) +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.aarch64.sve.uqrshrn.x4.nxv4i32( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]], i32 8) +// CPP-CHECK-NEXT: ret [[TMP4]] +// +svuint8_t test_svsqrshrn_u8_u32_x4(svuint32x4_t zn) __arm_streaming { + return SVE_ACLE_FUNC(svqrshrn,_n,_u8,_u32_x4,)(zn, 8); +} + +// CHECK-LABEL: @test_svsqrshrn_s8_s32_x4( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 4) +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 8) +// CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 12) +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.aarch64.sve.sqrshrn.x4.nxv4i32( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]], i32 8) +// CHECK-NEXT: ret [[TMP4]] +// +// CPP-CHECK-LABEL: @_Z24test_svsqrshrn_s8_s32_x411svint32x4_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 4) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 8) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 12) +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.aarch64.sve.sqrshrn.x4.nxv4i32( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]], i32 8) +// CPP-CHECK-NEXT: ret [[TMP4]] +// +svint8_t test_svsqrshrn_s8_s32_x4(svint32x4_t zn) __arm_streaming { + return SVE_ACLE_FUNC(svqrshrn,_n,_s8,_s32_x4,)(zn, 8); +} + +// CHECK-LABEL: @test_svsqrshrn_u16_u64_x4( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 2) +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 4) +// CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 6) +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.aarch64.sve.uqrshrn.x4.nxv2i64( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]], i32 16) +// CHECK-NEXT: ret [[TMP4]] +// +// CPP-CHECK-LABEL: @_Z25test_svsqrshrn_u16_u64_x412svuint64x4_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 2) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 4) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 6) +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.aarch64.sve.uqrshrn.x4.nxv2i64( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]], i32 16) +// CPP-CHECK-NEXT: ret [[TMP4]] +// +svuint16_t test_svsqrshrn_u16_u64_x4(svuint64x4_t zn) __arm_streaming { + return SVE_ACLE_FUNC(svqrshrn,_n,_u16,_u64_x4,)(zn, 16); +} + +// CHECK-LABEL: @test_svsqrshrn_s16_s64_x4( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 2) +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 4) +// CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 6) +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.aarch64.sve.sqrshrn.x4.nxv2i64( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]], i32 16) +// CHECK-NEXT: ret [[TMP4]] +// +// CPP-CHECK-LABEL: @_Z25test_svsqrshrn_s16_s64_x411svint64x4_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 2) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 4) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 6) +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.aarch64.sve.sqrshrn.x4.nxv2i64( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]], i32 16) +// CPP-CHECK-NEXT: ret [[TMP4]] +// +svint16_t test_svsqrshrn_s16_s64_x4(svint64x4_t zn) __arm_streaming { + return SVE_ACLE_FUNC(svqrshrn,_n,_s16,_s64_x4,)(zn, 16); +} + +// SVSQRSHRU + +// CHECK-LABEL: @test_svsvqrshru_u16_s32_x2( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv8i32( [[ZN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv8i32( [[ZN]], i64 4) +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.aarch64.sve.sqrshru.x2.nxv4i32( [[TMP0]], [[TMP1]], i32 16) +// CHECK-NEXT: ret [[TMP2]] +// +// CPP-CHECK-LABEL: @_Z26test_svsvqrshru_u16_s32_x211svint32x2_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv8i32( [[ZN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv8i32( [[ZN]], i64 4) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.aarch64.sve.sqrshru.x2.nxv4i32( [[TMP0]], [[TMP1]], i32 16) +// CPP-CHECK-NEXT: ret [[TMP2]] +// +svuint16_t test_svsvqrshru_u16_s32_x2(svint32x2_t zn) __arm_streaming { + return SVE_ACLE_FUNC(svqrshru,_n,_u16,_s32_x2,)(zn, 16); +} + +// CHECK-LABEL: @test_svsqrshru_u8_s32_x4( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 4) +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 8) +// CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 12) +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.aarch64.sve.sqrshru.x4.nxv4i32( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]], i32 8) +// CHECK-NEXT: ret [[TMP4]] +// +// CPP-CHECK-LABEL: @_Z24test_svsqrshru_u8_s32_x411svint32x4_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 4) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 8) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 12) +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.aarch64.sve.sqrshru.x4.nxv4i32( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]], i32 8) +// CPP-CHECK-NEXT: ret [[TMP4]] +// +svuint8_t test_svsqrshru_u8_s32_x4(svint32x4_t zn) __arm_streaming { + return SVE_ACLE_FUNC(svqrshru,_n,_u8,_s32_x4,)(zn, 8); +} + +// CHECK-LABEL: @test_svsqrshru_u16_s64_x4( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 2) +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 4) +// CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 6) +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.aarch64.sve.sqrshru.x4.nxv2i64( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]], i32 16) +// CHECK-NEXT: ret [[TMP4]] +// +// CPP-CHECK-LABEL: @_Z25test_svsqrshru_u16_s64_x411svint64x4_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 2) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 4) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 6) +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.aarch64.sve.sqrshru.x4.nxv2i64( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]], i32 16) +// CPP-CHECK-NEXT: ret [[TMP4]] +// +svuint16_t test_svsqrshru_u16_s64_x4(svint64x4_t zn) __arm_streaming { + return SVE_ACLE_FUNC(svqrshru,_n,_u16,_s64_x4,)(zn, 16); +} + +// SQRSHRUN x 4 + +// CHECK-LABEL: @test_svsqrshrun_u8_s32_x4( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 4) +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 8) +// CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 12) +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.aarch64.sve.sqrshrun.x4.nxv4i32( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]], i32 32) +// CHECK-NEXT: ret [[TMP4]] +// +// CPP-CHECK-LABEL: @_Z25test_svsqrshrun_u8_s32_x411svint32x4_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 4) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 8) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 12) +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.aarch64.sve.sqrshrun.x4.nxv4i32( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]], i32 32) +// CPP-CHECK-NEXT: ret [[TMP4]] +// +svuint8_t test_svsqrshrun_u8_s32_x4(svint32x4_t zn) __arm_streaming { + return SVE_ACLE_FUNC(svqrshrun,_n,_u8,_s32_x4,)(zn, 32); +} + +// CHECK-LABEL: @test_svsqrshrun_u16_s64_x4( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 2) +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 4) +// CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 6) +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.aarch64.sve.sqrshrun.x4.nxv2i64( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]], i32 64) +// CHECK-NEXT: ret [[TMP4]] +// +// CPP-CHECK-LABEL: @_Z26test_svsqrshrun_u16_s64_x411svint64x4_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 2) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 4) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv2i64.nxv8i64( [[ZN]], i64 6) +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.aarch64.sve.sqrshrun.x4.nxv2i64( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]], i32 64) +// CPP-CHECK-NEXT: ret [[TMP4]] +// +svuint16_t test_svsqrshrun_u16_s64_x4(svint64x4_t zn) __arm_streaming { + return SVE_ACLE_FUNC(svqrshrun,_n,_u16,_s64_x4,)(zn, 64); +} diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_create2_bool.c b/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_create2_bool.c new file mode 100644 index 0000000000000000000000000000000000000000..eb5a19b1d9d326e1a8c3f578a731bbbeee40da82 --- /dev/null +++ b/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_create2_bool.c @@ -0,0 +1,38 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve2p1 -S -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s \ +// RUN: | opt -S -passes=mem2reg,tailcallelim | FileCheck %s +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve2p1 -S -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s \ +// RUN: | opt -S -passes=mem2reg,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK +// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sve2p1 -S -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s \ +// RUN: | opt -S -passes=mem2reg,tailcallelim | FileCheck %s +// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sve2p1 -S -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s\ +// RUN: | opt -S -passes=mem2reg,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve2p1 -S -disable-O0-optnone -Werror -Wall -o /dev/null %s + +// REQUIRES: aarch64-registered-target + +#include + +#ifdef SVE_OVERLOADED_FORMS +// A simple used,unused... macro, long enough to represent any SVE builtin. +#define SVE_ACLE_FUNC(A1,A2_UNUSED,A3,A4_UNUSED) A1##A3 +#else +#define SVE_ACLE_FUNC(A1,A2,A3,A4) A1##A2##A3##A4 +#endif + +// CHECK-LABEL: @test_svcreate2_s8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.insert.nxv32i1.nxv16i1( poison, [[X0:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.insert.nxv32i1.nxv16i1( [[TMP0]], [[X1:%.*]], i64 16) +// CHECK-NEXT: ret [[TMP1]] +// +// CPP-CHECK-LABEL: @_Z17test_svcreate2_s8u10__SVBool_tS_( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.insert.nxv32i1.nxv16i1( poison, [[X0:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.insert.nxv32i1.nxv16i1( [[TMP0]], [[X1:%.*]], i64 16) +// CPP-CHECK-NEXT: ret [[TMP1]] +// +svboolx2_t test_svcreate2_s8(svbool_t x0, svbool_t x1) +{ + return SVE_ACLE_FUNC(svcreate2,_b8,,)(x0, x1); +} diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_create4_bool.c b/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_create4_bool.c new file mode 100644 index 0000000000000000000000000000000000000000..3f99ee6e79c0769efe3fa22918bc123cc72b7442 --- /dev/null +++ b/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_create4_bool.c @@ -0,0 +1,42 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve2p1 -S -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s \ +// RUN: | opt -S -passes=mem2reg,tailcallelim | FileCheck %s +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve2p1 -S -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s \ +// RUN: | opt -S -passes=mem2reg,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK +// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sve2p1 -S -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s \ +// RUN: | opt -S -passes=mem2reg,tailcallelim | FileCheck %s +// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sve2p1 -S -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s\ +// RUN: | opt -S -passes=mem2reg,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve2p1 -S -disable-O0-optnone -Werror -Wall -o /dev/null %s + +// REQUIRES: aarch64-registered-target + +#include + +#ifdef SVE_OVERLOADED_FORMS +// A simple used,unused... macro, long enough to represent any SVE builtin. +#define SVE_ACLE_FUNC(A1,A2_UNUSED,A3,A4_UNUSED) A1##A3 +#else +#define SVE_ACLE_FUNC(A1,A2,A3,A4) A1##A2##A3##A4 +#endif + +// CHECK-LABEL: @test_svcreate4_b8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.insert.nxv64i1.nxv16i1( poison, [[X0:%.*]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.insert.nxv64i1.nxv16i1( [[TMP0]], [[X1:%.*]], i64 16) +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv64i1.nxv16i1( [[TMP1]], [[X2:%.*]], i64 32) +// CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.insert.nxv64i1.nxv16i1( [[TMP2]], [[X4:%.*]], i64 48) +// CHECK-NEXT: ret [[TMP3]] +// +// CPP-CHECK-LABEL: @_Z17test_svcreate4_b8u10__SVBool_tS_S_S_( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.insert.nxv64i1.nxv16i1( poison, [[X0:%.*]], i64 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.insert.nxv64i1.nxv16i1( [[TMP0]], [[X1:%.*]], i64 16) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv64i1.nxv16i1( [[TMP1]], [[X2:%.*]], i64 32) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.insert.nxv64i1.nxv16i1( [[TMP2]], [[X4:%.*]], i64 48) +// CPP-CHECK-NEXT: ret [[TMP3]] +// +svboolx4_t test_svcreate4_b8(svbool_t x0, svbool_t x1, svbool_t x2, svbool_t x4) +{ + return SVE_ACLE_FUNC(svcreate4,_b8,,)(x0, x1, x2, x4); +} diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_get2_bool.c b/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_get2_bool.c new file mode 100644 index 0000000000000000000000000000000000000000..5d38f72b34b164c7b2ebfbd8cd7dfe81ec6510db --- /dev/null +++ b/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_get2_bool.c @@ -0,0 +1,49 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve2p1 -S -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s \ +// RUN: | opt -S -passes=mem2reg,tailcallelim | FileCheck %s +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve2p1 -S -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s \ +// RUN: | opt -S -passes=mem2reg,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK +// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sve2p1 -S -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s \ +// RUN: | opt -S -passes=mem2reg,tailcallelim | FileCheck %s +// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sve2p1 -S -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s\ +// RUN: | opt -S -passes=mem2reg,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve2p1 -S -disable-O0-optnone -Werror -Wall -o /dev/null %s +// REQUIRES: aarch64-registered-target +#include + +#ifdef SVE_OVERLOADED_FORMS +// A simple used,unused... macro, long enough to represent any SVE builtin. +#define SVE_ACLE_FUNC(A1,A2_UNUSED,A3,A4_UNUSED) A1##A3 +#else +#define SVE_ACLE_FUNC(A1,A2,A3,A4) A1##A2##A3##A4 +#endif + +// CHECK-LABEL: @test_svget2_b8_0( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv16i1.nxv32i1( [[TUPLE:%.*]], i64 0) +// CHECK-NEXT: ret [[TMP0]] +// +// CPP-CHECK-LABEL: @_Z16test_svget2_b8_010svboolx2_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv16i1.nxv32i1( [[TUPLE:%.*]], i64 0) +// CPP-CHECK-NEXT: ret [[TMP0]] +// +svbool_t test_svget2_b8_0(svboolx2_t tuple) +{ + return SVE_ACLE_FUNC(svget2,_b8,,)(tuple, 0); +} + +// CHECK-LABEL: @test_svget2_b8_1( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv16i1.nxv32i1( [[TUPLE:%.*]], i64 16) +// CHECK-NEXT: ret [[TMP0]] +// +// CPP-CHECK-LABEL: @_Z16test_svget2_b8_110svboolx2_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv16i1.nxv32i1( [[TUPLE:%.*]], i64 16) +// CPP-CHECK-NEXT: ret [[TMP0]] +// +svbool_t test_svget2_b8_1(svboolx2_t tuple) +{ + return SVE_ACLE_FUNC(svget2,_b8,,)(tuple, 1); +} diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_get4_bool.c b/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_get4_bool.c new file mode 100644 index 0000000000000000000000000000000000000000..821a5be3254ebad4fafc8c3bd532783568d574dd --- /dev/null +++ b/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_get4_bool.c @@ -0,0 +1,72 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve2p1 -S -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s \ +// RUN: | opt -S -passes=mem2reg,tailcallelim | FileCheck %s +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve2p1 -S -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s \ +// RUN: | opt -S -passes=mem2reg,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK +// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sve2p1 -S -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s \ +// RUN: | opt -S -passes=mem2reg,tailcallelim | FileCheck %s +// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sve2p1 -S -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s\ +// RUN: | opt -S -passes=mem2reg,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve2p1 -S -disable-O0-optnone -Werror -Wall -o /dev/null %s + +// REQUIRES: aarch64-registered-target + +#include + +#ifdef SVE_OVERLOADED_FORMS +// A simple used,unused... macro, long enough to represent any SVE builtin. +#define SVE_ACLE_FUNC(A1,A2_UNUSED,A3,A4_UNUSED) A1##A3 +#else +#define SVE_ACLE_FUNC(A1,A2,A3,A4) A1##A2##A3##A4 +#endif + +// NOTE: For these tests clang converts the struct parameter into +// several parameters, one for each member of the original struct. +// CHECK-LABEL: @test_svget4_b8_0( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv16i1.nxv64i1( [[TUPLE:%.*]], i64 0) +// CHECK-NEXT: ret [[TMP0]] +// +// CPP-CHECK-LABEL: @_Z16test_svget4_b8_010svboolx4_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv16i1.nxv64i1( [[TUPLE:%.*]], i64 0) +// CPP-CHECK-NEXT: ret [[TMP0]] +// +svbool_t test_svget4_b8_0(svboolx4_t tuple) +{ + return SVE_ACLE_FUNC(svget4,_b8,,)(tuple, 0); +} + +// NOTE: For these tests clang converts the struct parameter into +// several parameters, one for each member of the original struct. +// CHECK-LABEL: @test_svget4_b8_1( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv16i1.nxv64i1( [[TUPLE:%.*]], i64 16) +// CHECK-NEXT: ret [[TMP0]] +// +// CPP-CHECK-LABEL: @_Z16test_svget4_b8_110svboolx4_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv16i1.nxv64i1( [[TUPLE:%.*]], i64 16) +// CPP-CHECK-NEXT: ret [[TMP0]] +// +svbool_t test_svget4_b8_1(svboolx4_t tuple) +{ + return SVE_ACLE_FUNC(svget4,_b8,,)(tuple, 1); +} + +// NOTE: For these tests clang converts the struct parameter into +// several parameters, one for each member of the original struct. +// CHECK-LABEL: @test_svget4_b8_3( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv16i1.nxv64i1( [[TUPLE:%.*]], i64 48) +// CHECK-NEXT: ret [[TMP0]] +// +// CPP-CHECK-LABEL: @_Z16test_svget4_b8_310svboolx4_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv16i1.nxv64i1( [[TUPLE:%.*]], i64 48) +// CPP-CHECK-NEXT: ret [[TMP0]] +// +svbool_t test_svget4_b8_3(svboolx4_t tuple) +{ + return SVE_ACLE_FUNC(svget4,_b8,,)(tuple, 3); +} diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_pext.c b/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_pext.c index fe15d5a9db81f2f0f8956751908696e873cd9a44..a3206029019c3dd1da3b206b4aee4efd0e7af9c4 100644 --- a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_pext.c +++ b/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_pext.c @@ -1,10 +1,17 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py // REQUIRES: aarch64-registered-target +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -DTEST_SME2 -target-feature +sve -target-feature +sme2 -S -O1 -Werror -emit-llvm -o - %s | FileCheck %s // RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve2p1 -S -O1 -Werror -emit-llvm -o - %s | FileCheck %s -// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve2p1 -S -O1 -Werror -emit-llvm -o - -x c++ %s | FileCheck %s -check-prefix=CPP-CHECK +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve2p1 -S -disable-O0-optnone -Werror -Wall -o /dev/null %s #include +#ifndef TEST_SME2 +#define ATTR +#else +#define ATTR __arm_streaming +#endif + // CHECK-LABEL: @test_svpext_lane_c8_0( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.pext.nxv16i1(target("aarch64.svcount") [[C:%.*]], i32 0) @@ -15,7 +22,7 @@ // CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.pext.nxv16i1(target("aarch64.svcount") [[C:%.*]], i32 0) // CPP-CHECK-NEXT: ret [[TMP0]] // -svbool_t test_svpext_lane_c8_0(svcount_t c) { +svbool_t test_svpext_lane_c8_0(svcount_t c) ATTR { return svpext_lane_c8(c, 0); } @@ -29,7 +36,7 @@ svbool_t test_svpext_lane_c8_0(svcount_t c) { // CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.pext.nxv16i1(target("aarch64.svcount") [[C:%.*]], i32 3) // CPP-CHECK-NEXT: ret [[TMP0]] // -svbool_t test_svpext_lane_c8_3(svcount_t c) { +svbool_t test_svpext_lane_c8_3(svcount_t c) ATTR { return svpext_lane_c8(c, 3); } @@ -45,7 +52,7 @@ svbool_t test_svpext_lane_c8_3(svcount_t c) { // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.convert.to.svbool.nxv8i1( [[TMP0]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svbool_t test_svpext_lane_c16_0(svcount_t c) { +svbool_t test_svpext_lane_c16_0(svcount_t c) ATTR { return svpext_lane_c16(c, 0); } @@ -61,7 +68,7 @@ svbool_t test_svpext_lane_c16_0(svcount_t c) { // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.convert.to.svbool.nxv8i1( [[TMP0]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svbool_t test_svpext_lane_c16_3(svcount_t c) { +svbool_t test_svpext_lane_c16_3(svcount_t c) ATTR { return svpext_lane_c16(c, 3); } @@ -77,7 +84,7 @@ svbool_t test_svpext_lane_c16_3(svcount_t c) { // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.convert.to.svbool.nxv4i1( [[TMP0]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svbool_t test_svpext_lane_c32_0(svcount_t c) { +svbool_t test_svpext_lane_c32_0(svcount_t c) ATTR { return svpext_lane_c32(c, 0); } @@ -93,7 +100,7 @@ svbool_t test_svpext_lane_c32_0(svcount_t c) { // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.convert.to.svbool.nxv4i1( [[TMP0]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svbool_t test_svpext_lane_c32_3(svcount_t c) { +svbool_t test_svpext_lane_c32_3(svcount_t c) ATTR { return svpext_lane_c32(c, 3); } @@ -109,7 +116,7 @@ svbool_t test_svpext_lane_c32_3(svcount_t c) { // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.convert.to.svbool.nxv2i1( [[TMP0]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svbool_t test_svpext_lane_c64_0(svcount_t c) { +svbool_t test_svpext_lane_c64_0(svcount_t c) ATTR { return svpext_lane_c64(c, 0); } @@ -125,7 +132,7 @@ svbool_t test_svpext_lane_c64_0(svcount_t c) { // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.convert.to.svbool.nxv2i1( [[TMP0]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svbool_t test_svpext_lane_c64_3(svcount_t c) { +svbool_t test_svpext_lane_c64_3(svcount_t c) ATTR { return svpext_lane_c64(c, 3); } @@ -147,6 +154,184 @@ svbool_t test_svpext_lane_c64_3(svcount_t c) { // CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv32i1.nxv16i1( [[TMP2]], [[TMP3]], i64 16) // CPP-CHECK-NEXT: ret [[TMP4]] // -svboolx2_t test_svpext_lane_c8_x2_0(svcount_t c) { +svboolx2_t test_svpext_lane_c8_x2_0(svcount_t c) ATTR { return svpext_lane_c8_x2(c, 0); } + +// CHECK-LABEL: @test_svpext_lane_c8_x2_1( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call { , } @llvm.aarch64.sve.pext.x2.nxv16i1(target("aarch64.svcount") [[C:%.*]], i32 1) +// CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv32i1.nxv16i1( poison, [[TMP1]], i64 0) +// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP0]], 1 +// CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv32i1.nxv16i1( [[TMP2]], [[TMP3]], i64 16) +// CHECK-NEXT: ret [[TMP4]] +// +// CPP-CHECK-LABEL: @_Z24test_svpext_lane_c8_x2_1u11__SVCount_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call { , } @llvm.aarch64.sve.pext.x2.nxv16i1(target("aarch64.svcount") [[C:%.*]], i32 1) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.insert.nxv32i1.nxv16i1( poison, [[TMP1]], i64 0) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP0]], 1 +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv32i1.nxv16i1( [[TMP2]], [[TMP3]], i64 16) +// CPP-CHECK-NEXT: ret [[TMP4]] +// +svboolx2_t test_svpext_lane_c8_x2_1(svcount_t c) ATTR { + return svpext_lane_c8_x2(c, 1); +} + +// CHECK-LABEL: @test_svpext_lane_c16_x2_0( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call { , } @llvm.aarch64.sve.pext.x2.nxv8i1(target("aarch64.svcount") [[C:%.*]], i32 0) +// CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.aarch64.sve.convert.to.svbool.nxv8i1( [[TMP1]]) +// CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.insert.nxv32i1.nxv16i1( poison, [[TMP2]], i64 0) +// CHECK-NEXT: [[TMP4:%.*]] = extractvalue { , } [[TMP0]], 1 +// CHECK-NEXT: [[TMP5:%.*]] = tail call @llvm.aarch64.sve.convert.to.svbool.nxv8i1( [[TMP4]]) +// CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv32i1.nxv16i1( [[TMP3]], [[TMP5]], i64 16) +// CHECK-NEXT: ret [[TMP6]] +// +// CPP-CHECK-LABEL: @_Z25test_svpext_lane_c16_x2_0u11__SVCount_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call { , } @llvm.aarch64.sve.pext.x2.nxv8i1(target("aarch64.svcount") [[C:%.*]], i32 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.aarch64.sve.convert.to.svbool.nxv8i1( [[TMP1]]) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.insert.nxv32i1.nxv16i1( poison, [[TMP2]], i64 0) +// CPP-CHECK-NEXT: [[TMP4:%.*]] = extractvalue { , } [[TMP0]], 1 +// CPP-CHECK-NEXT: [[TMP5:%.*]] = tail call @llvm.aarch64.sve.convert.to.svbool.nxv8i1( [[TMP4]]) +// CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv32i1.nxv16i1( [[TMP3]], [[TMP5]], i64 16) +// CPP-CHECK-NEXT: ret [[TMP6]] +// +svboolx2_t test_svpext_lane_c16_x2_0(svcount_t c) ATTR { + return svpext_lane_c16_x2(c, 0); +} + +// CHECK-LABEL: @test_svpext_lane_c16_x2_1( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call { , } @llvm.aarch64.sve.pext.x2.nxv8i1(target("aarch64.svcount") [[C:%.*]], i32 1) +// CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.aarch64.sve.convert.to.svbool.nxv8i1( [[TMP1]]) +// CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.insert.nxv32i1.nxv16i1( poison, [[TMP2]], i64 0) +// CHECK-NEXT: [[TMP4:%.*]] = extractvalue { , } [[TMP0]], 1 +// CHECK-NEXT: [[TMP5:%.*]] = tail call @llvm.aarch64.sve.convert.to.svbool.nxv8i1( [[TMP4]]) +// CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv32i1.nxv16i1( [[TMP3]], [[TMP5]], i64 16) +// CHECK-NEXT: ret [[TMP6]] +// +// CPP-CHECK-LABEL: @_Z25test_svpext_lane_c16_x2_1u11__SVCount_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call { , } @llvm.aarch64.sve.pext.x2.nxv8i1(target("aarch64.svcount") [[C:%.*]], i32 1) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.aarch64.sve.convert.to.svbool.nxv8i1( [[TMP1]]) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.insert.nxv32i1.nxv16i1( poison, [[TMP2]], i64 0) +// CPP-CHECK-NEXT: [[TMP4:%.*]] = extractvalue { , } [[TMP0]], 1 +// CPP-CHECK-NEXT: [[TMP5:%.*]] = tail call @llvm.aarch64.sve.convert.to.svbool.nxv8i1( [[TMP4]]) +// CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv32i1.nxv16i1( [[TMP3]], [[TMP5]], i64 16) +// CPP-CHECK-NEXT: ret [[TMP6]] +// +svboolx2_t test_svpext_lane_c16_x2_1(svcount_t c) ATTR { + return svpext_lane_c16_x2(c, 1); +} + +// CHECK-LABEL: @test_svpext_lane_c32_x2_0( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call { , } @llvm.aarch64.sve.pext.x2.nxv4i1(target("aarch64.svcount") [[C:%.*]], i32 0) +// CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.aarch64.sve.convert.to.svbool.nxv4i1( [[TMP1]]) +// CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.insert.nxv32i1.nxv16i1( poison, [[TMP2]], i64 0) +// CHECK-NEXT: [[TMP4:%.*]] = extractvalue { , } [[TMP0]], 1 +// CHECK-NEXT: [[TMP5:%.*]] = tail call @llvm.aarch64.sve.convert.to.svbool.nxv4i1( [[TMP4]]) +// CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv32i1.nxv16i1( [[TMP3]], [[TMP5]], i64 16) +// CHECK-NEXT: ret [[TMP6]] +// +// CPP-CHECK-LABEL: @_Z25test_svpext_lane_c32_x2_0u11__SVCount_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call { , } @llvm.aarch64.sve.pext.x2.nxv4i1(target("aarch64.svcount") [[C:%.*]], i32 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.aarch64.sve.convert.to.svbool.nxv4i1( [[TMP1]]) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.insert.nxv32i1.nxv16i1( poison, [[TMP2]], i64 0) +// CPP-CHECK-NEXT: [[TMP4:%.*]] = extractvalue { , } [[TMP0]], 1 +// CPP-CHECK-NEXT: [[TMP5:%.*]] = tail call @llvm.aarch64.sve.convert.to.svbool.nxv4i1( [[TMP4]]) +// CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv32i1.nxv16i1( [[TMP3]], [[TMP5]], i64 16) +// CPP-CHECK-NEXT: ret [[TMP6]] +// +svboolx2_t test_svpext_lane_c32_x2_0(svcount_t c) ATTR { + return svpext_lane_c32_x2(c, 0); +} + +// CHECK-LABEL: @test_svpext_lane_c32_x2_1( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call { , } @llvm.aarch64.sve.pext.x2.nxv4i1(target("aarch64.svcount") [[C:%.*]], i32 1) +// CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.aarch64.sve.convert.to.svbool.nxv4i1( [[TMP1]]) +// CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.insert.nxv32i1.nxv16i1( poison, [[TMP2]], i64 0) +// CHECK-NEXT: [[TMP4:%.*]] = extractvalue { , } [[TMP0]], 1 +// CHECK-NEXT: [[TMP5:%.*]] = tail call @llvm.aarch64.sve.convert.to.svbool.nxv4i1( [[TMP4]]) +// CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv32i1.nxv16i1( [[TMP3]], [[TMP5]], i64 16) +// CHECK-NEXT: ret [[TMP6]] +// +// CPP-CHECK-LABEL: @_Z25test_svpext_lane_c32_x2_1u11__SVCount_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call { , } @llvm.aarch64.sve.pext.x2.nxv4i1(target("aarch64.svcount") [[C:%.*]], i32 1) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.aarch64.sve.convert.to.svbool.nxv4i1( [[TMP1]]) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.insert.nxv32i1.nxv16i1( poison, [[TMP2]], i64 0) +// CPP-CHECK-NEXT: [[TMP4:%.*]] = extractvalue { , } [[TMP0]], 1 +// CPP-CHECK-NEXT: [[TMP5:%.*]] = tail call @llvm.aarch64.sve.convert.to.svbool.nxv4i1( [[TMP4]]) +// CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv32i1.nxv16i1( [[TMP3]], [[TMP5]], i64 16) +// CPP-CHECK-NEXT: ret [[TMP6]] +// +svboolx2_t test_svpext_lane_c32_x2_1(svcount_t c) ATTR { + return svpext_lane_c32_x2(c, 1); +} + +// CHECK-LABEL: @test_svpext_lane_c64_x2_0( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call { , } @llvm.aarch64.sve.pext.x2.nxv2i1(target("aarch64.svcount") [[C:%.*]], i32 0) +// CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.aarch64.sve.convert.to.svbool.nxv2i1( [[TMP1]]) +// CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.insert.nxv32i1.nxv16i1( poison, [[TMP2]], i64 0) +// CHECK-NEXT: [[TMP4:%.*]] = extractvalue { , } [[TMP0]], 1 +// CHECK-NEXT: [[TMP5:%.*]] = tail call @llvm.aarch64.sve.convert.to.svbool.nxv2i1( [[TMP4]]) +// CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv32i1.nxv16i1( [[TMP3]], [[TMP5]], i64 16) +// CHECK-NEXT: ret [[TMP6]] +// +// CPP-CHECK-LABEL: @_Z25test_svpext_lane_c64_x2_0u11__SVCount_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call { , } @llvm.aarch64.sve.pext.x2.nxv2i1(target("aarch64.svcount") [[C:%.*]], i32 0) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.aarch64.sve.convert.to.svbool.nxv2i1( [[TMP1]]) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.insert.nxv32i1.nxv16i1( poison, [[TMP2]], i64 0) +// CPP-CHECK-NEXT: [[TMP4:%.*]] = extractvalue { , } [[TMP0]], 1 +// CPP-CHECK-NEXT: [[TMP5:%.*]] = tail call @llvm.aarch64.sve.convert.to.svbool.nxv2i1( [[TMP4]]) +// CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv32i1.nxv16i1( [[TMP3]], [[TMP5]], i64 16) +// CPP-CHECK-NEXT: ret [[TMP6]] +// +svboolx2_t test_svpext_lane_c64_x2_0(svcount_t c) ATTR { + return svpext_lane_c64_x2(c, 0); +} + +// CHECK-LABEL: @test_svpext_lane_c64_x2_1( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call { , } @llvm.aarch64.sve.pext.x2.nxv2i1(target("aarch64.svcount") [[C:%.*]], i32 1) +// CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.aarch64.sve.convert.to.svbool.nxv2i1( [[TMP1]]) +// CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.insert.nxv32i1.nxv16i1( poison, [[TMP2]], i64 0) +// CHECK-NEXT: [[TMP4:%.*]] = extractvalue { , } [[TMP0]], 1 +// CHECK-NEXT: [[TMP5:%.*]] = tail call @llvm.aarch64.sve.convert.to.svbool.nxv2i1( [[TMP4]]) +// CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv32i1.nxv16i1( [[TMP3]], [[TMP5]], i64 16) +// CHECK-NEXT: ret [[TMP6]] +// +// CPP-CHECK-LABEL: @_Z25test_svpext_lane_c64_x2_1u11__SVCount_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call { , } @llvm.aarch64.sve.pext.x2.nxv2i1(target("aarch64.svcount") [[C:%.*]], i32 1) +// CPP-CHECK-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.aarch64.sve.convert.to.svbool.nxv2i1( [[TMP1]]) +// CPP-CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.insert.nxv32i1.nxv16i1( poison, [[TMP2]], i64 0) +// CPP-CHECK-NEXT: [[TMP4:%.*]] = extractvalue { , } [[TMP0]], 1 +// CPP-CHECK-NEXT: [[TMP5:%.*]] = tail call @llvm.aarch64.sve.convert.to.svbool.nxv2i1( [[TMP4]]) +// CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv32i1.nxv16i1( [[TMP3]], [[TMP5]], i64 16) +// CPP-CHECK-NEXT: ret [[TMP6]] +// +svboolx2_t test_svpext_lane_c64_x2_1(svcount_t c) ATTR { + return svpext_lane_c64_x2(c, 1); +} diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_pfalse.c b/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_pfalse.c index 5432862dcf527340ef4d2c4f6dcc49f9789123bb..19993e5418128e3003e8ecec2989ed01b98989f1 100644 --- a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_pfalse.c +++ b/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_pfalse.c @@ -1,18 +1,13 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py // REQUIRES: aarch64-registered-target // RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve2p1 -S -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -passes=mem2reg,tailcallelim | FileCheck %s +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme2 -S -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -passes=mem2reg,tailcallelim | FileCheck %s // RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve2p1 -S -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s | opt -S -passes=mem2reg,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK -// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sve2p1 -S -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -passes=mem2reg,tailcallelim | FileCheck %s -// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sve2p1 -S -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s | opt -S -passes=mem2reg,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme2 -S -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s | opt -S -passes=mem2reg,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK // RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve2p1 -S -disable-O0-optnone -Werror -Wall -o /dev/null %s -#include +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme2 -S -disable-O0-optnone -Werror -Wall -o /dev/null %s -#ifdef SVE_OVERLOADED_FORMS -// A simple used,unused... macro, long enough to represent any SVE builtin. -#define SVE_ACLE_FUNC(A1,A2_UNUSED,A3,A4_UNUSED) A1##A3 -#else -#define SVE_ACLE_FUNC(A1,A2,A3,A4) A1##A2##A3##A4 -#endif +#include // CHECK-LABEL: @test_svpfalse_c( // CHECK-NEXT: entry: @@ -24,7 +19,7 @@ // CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call target("aarch64.svcount") @llvm.aarch64.sve.convert.from.svbool.taarch64.svcountt( zeroinitializer) // CPP-CHECK-NEXT: ret target("aarch64.svcount") [[TMP0]] // -svcount_t test_svpfalse_c() +svcount_t test_svpfalse_c(void) __arm_streaming_compatible { - return SVE_ACLE_FUNC(svpfalse_c,,,)(); + return svpfalse_c(); } diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_psel.c b/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_psel.c index aa2a35c2fd2541c7986333ee1804916d5cfe5fe8..73b7b0347dd970974824308600c855da81212cd9 100644 --- a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_psel.c +++ b/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_psel.c @@ -5,6 +5,11 @@ // RUN: %clang_cc1 -fclang-abi-compat=latest -triple aarch64-none-linux-gnu \ // RUN: -target-feature +sve2p1 -S -O1 -Werror -emit-llvm -o - -x c++ %s | FileCheck %s -check-prefix=CPP-CHECK // RUN: %clang_cc1 -fclang-abi-compat=latest -triple aarch64-none-linux-gnu -target-feature +sve2p1 -S -disable-O0-optnone -Werror -Wall -o /dev/null %s +// RUN: %clang_cc1 -fclang-abi-compat=latest -triple aarch64-none-linux-gnu \ +// RUN: -target-feature +sve2p1 -S -O1 -Werror -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -fclang-abi-compat=latest -triple aarch64-none-linux-gnu \ +// RUN: -target-feature +sve2p1 -S -O1 -Werror -emit-llvm -o - -x c++ %s | FileCheck %s -check-prefix=CPP-CHECK +// RUN: %clang_cc1 -fclang-abi-compat=latest -triple aarch64-none-linux-gnu -target-feature +sve2p1 -S -disable-O0-optnone -Werror -Wall -o /dev/null %s #include @@ -20,7 +25,7 @@ // CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.psel.nxv16i1( [[P1:%.*]], [[P2:%.*]], i32 [[ADD]]) // CPP-CHECK-NEXT: ret [[TMP0]] // -svbool_t test_svpsel_lane_b8(svbool_t p1, svbool_t p2, uint32_t idx) { +svbool_t test_svpsel_lane_b8(svbool_t p1, svbool_t p2, uint32_t idx) __arm_streaming_compatible { return svpsel_lane_b8(p1, p2, idx + 15); } @@ -38,7 +43,7 @@ svbool_t test_svpsel_lane_b8(svbool_t p1, svbool_t p2, uint32_t idx) { // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.psel.nxv8i1( [[P1:%.*]], [[TMP0]], i32 [[ADD]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svbool_t test_svpsel_lane_b16(svbool_t p1, svbool_t p2, uint32_t idx) { +svbool_t test_svpsel_lane_b16(svbool_t p1, svbool_t p2, uint32_t idx) __arm_streaming_compatible { return svpsel_lane_b16(p1, p2, idx + 7); } @@ -56,7 +61,7 @@ svbool_t test_svpsel_lane_b16(svbool_t p1, svbool_t p2, uint32_t idx) { // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.psel.nxv4i1( [[P1:%.*]], [[TMP0]], i32 [[ADD]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svbool_t test_svpsel_lane_b32(svbool_t p1, svbool_t p2, uint32_t idx) { +svbool_t test_svpsel_lane_b32(svbool_t p1, svbool_t p2, uint32_t idx) __arm_streaming_compatible { return svpsel_lane_b32(p1, p2, idx + 3); } @@ -74,7 +79,7 @@ svbool_t test_svpsel_lane_b32(svbool_t p1, svbool_t p2, uint32_t idx) { // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.psel.nxv2i1( [[P1:%.*]], [[TMP0]], i32 [[ADD]]) // CPP-CHECK-NEXT: ret [[TMP1]] // -svbool_t test_svpsel_lane_b64(svbool_t p1, svbool_t p2, uint32_t idx) { +svbool_t test_svpsel_lane_b64(svbool_t p1, svbool_t p2, uint32_t idx) __arm_streaming_compatible { return svpsel_lane_b64(p1, p2, idx + 1); } @@ -94,7 +99,7 @@ svbool_t test_svpsel_lane_b64(svbool_t p1, svbool_t p2, uint32_t idx) { // CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call target("aarch64.svcount") @llvm.aarch64.sve.convert.from.svbool.taarch64.svcountt( [[TMP1]]) // CPP-CHECK-NEXT: ret target("aarch64.svcount") [[TMP2]] // -svcount_t test_svpsel_lane_c8(svcount_t p1, svbool_t p2, uint32_t idx) { +svcount_t test_svpsel_lane_c8(svcount_t p1, svbool_t p2, uint32_t idx) __arm_streaming_compatible { return svpsel_lane_c8(p1, p2, idx + 15); } @@ -116,7 +121,7 @@ svcount_t test_svpsel_lane_c8(svcount_t p1, svbool_t p2, uint32_t idx) { // CPP-CHECK-NEXT: [[TMP3:%.*]] = tail call target("aarch64.svcount") @llvm.aarch64.sve.convert.from.svbool.taarch64.svcountt( [[TMP2]]) // CPP-CHECK-NEXT: ret target("aarch64.svcount") [[TMP3]] // -svcount_t test_svpsel_lane_c16(svcount_t p1, svbool_t p2, uint32_t idx) { +svcount_t test_svpsel_lane_c16(svcount_t p1, svbool_t p2, uint32_t idx) __arm_streaming_compatible { return svpsel_lane_c16(p1, p2, idx + 7); } @@ -138,7 +143,7 @@ svcount_t test_svpsel_lane_c16(svcount_t p1, svbool_t p2, uint32_t idx) { // CPP-CHECK-NEXT: [[TMP3:%.*]] = tail call target("aarch64.svcount") @llvm.aarch64.sve.convert.from.svbool.taarch64.svcountt( [[TMP2]]) // CPP-CHECK-NEXT: ret target("aarch64.svcount") [[TMP3]] // -svcount_t test_svpsel_lane_c32(svcount_t p1, svbool_t p2, uint32_t idx) { +svcount_t test_svpsel_lane_c32(svcount_t p1, svbool_t p2, uint32_t idx) __arm_streaming_compatible { return svpsel_lane_c32(p1, p2, idx + 3); } @@ -160,6 +165,6 @@ svcount_t test_svpsel_lane_c32(svcount_t p1, svbool_t p2, uint32_t idx) { // CPP-CHECK-NEXT: [[TMP3:%.*]] = tail call target("aarch64.svcount") @llvm.aarch64.sve.convert.from.svbool.taarch64.svcountt( [[TMP2]]) // CPP-CHECK-NEXT: ret target("aarch64.svcount") [[TMP3]] // -svcount_t test_svpsel_lane_c64(svcount_t p1, svbool_t p2, uint32_t idx) { +svcount_t test_svpsel_lane_c64(svcount_t p1, svbool_t p2, uint32_t idx) __arm_streaming_compatible { return svpsel_lane_c64(p1, p2, idx + 1); } diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_ptrue.c b/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_ptrue.c index c8fd84350056047935d1c1676c574a4e9aedc6f0..7f9d60a3d320fca400f421c3215e44e9e6632ec1 100644 --- a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_ptrue.c +++ b/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_ptrue.c @@ -1,10 +1,18 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py // REQUIRES: aarch64-registered-target // RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve2p1 -S -O1 -Werror -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -DTEST_SME2 -triple aarch64-none-linux-gnu -target-feature +sme2 -S -O1 -Werror -emit-llvm -o - %s | FileCheck %s // RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve2p1 -S -O1 -Werror -emit-llvm -o - -x c++ %s | FileCheck %s -check-prefix=CPP-CHECK +// RUN: %clang_cc1 -DTEST_SME2 -triple aarch64-none-linux-gnu -target-feature +sme2 -S -O1 -Werror -emit-llvm -o - -x c++ %s | FileCheck %s -check-prefix=CPP-CHECK #include +#ifndef TEST_SME2 +#define ATTR +#else +#define ATTR __arm_streaming +#endif + // CHECK-LABEL: @test_svptrue_c8( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call target("aarch64.svcount") @llvm.aarch64.sve.ptrue.c8() @@ -15,7 +23,7 @@ // CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call target("aarch64.svcount") @llvm.aarch64.sve.ptrue.c8() // CPP-CHECK-NEXT: ret target("aarch64.svcount") [[TMP0]] // -svcount_t test_svptrue_c8(void) { +svcount_t test_svptrue_c8(void) ATTR { return svptrue_c8(); } @@ -29,7 +37,7 @@ svcount_t test_svptrue_c8(void) { // CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call target("aarch64.svcount") @llvm.aarch64.sve.ptrue.c16() // CPP-CHECK-NEXT: ret target("aarch64.svcount") [[TMP0]] // -svcount_t test_svptrue_c16(void) { +svcount_t test_svptrue_c16(void) ATTR { return svptrue_c16(); } @@ -43,7 +51,7 @@ svcount_t test_svptrue_c16(void) { // CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call target("aarch64.svcount") @llvm.aarch64.sve.ptrue.c32() // CPP-CHECK-NEXT: ret target("aarch64.svcount") [[TMP0]] // -svcount_t test_svptrue_c32(void) { +svcount_t test_svptrue_c32(void) ATTR { return svptrue_c32(); } @@ -57,6 +65,6 @@ svcount_t test_svptrue_c32(void) { // CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call target("aarch64.svcount") @llvm.aarch64.sve.ptrue.c64() // CPP-CHECK-NEXT: ret target("aarch64.svcount") [[TMP0]] // -svcount_t test_svptrue_c64(void) { +svcount_t test_svptrue_c64(void) ATTR { return svptrue_c64(); } diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_set2_bool.c b/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_set2_bool.c new file mode 100644 index 0000000000000000000000000000000000000000..298e5b80ceb004b14dc6b3b81fb5b732ef1fdabb --- /dev/null +++ b/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_set2_bool.c @@ -0,0 +1,52 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve2p1 -S -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s \ +// RUN: | opt -S -passes=mem2reg,tailcallelim | FileCheck %s +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve2p1 -S -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s \ +// RUN: | opt -S -passes=mem2reg,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK +// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sve2p1 -S -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s \ +// RUN: | opt -S -passes=mem2reg,tailcallelim | FileCheck %s +// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sve2p1 -S -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s\ +// RUN: | opt -S -passes=mem2reg,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve2p1 -S -disable-O0-optnone -Werror -Wall -o /dev/null %s + +// REQUIRES: aarch64-registered-target + +#include + +#ifdef SVE_OVERLOADED_FORMS +// A simple used,unused... macro, long enough to represent any SVE builtin. +#define SVE_ACLE_FUNC(A1,A2_UNUSED,A3,A4_UNUSED) A1##A3 +#else +#define SVE_ACLE_FUNC(A1,A2,A3,A4) A1##A2##A3##A4 +#endif + +// CHECK-LABEL: @test_svset2_b8_0( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.insert.nxv32i1.nxv16i1( [[TUPLE:%.*]], [[X:%.*]], i64 0) +// CHECK-NEXT: ret [[TMP0]] +// +// CPP-CHECK-LABEL: @_Z16test_svset2_b8_010svboolx2_tu10__SVBool_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.insert.nxv32i1.nxv16i1( [[TUPLE:%.*]], [[X:%.*]], i64 0) +// CPP-CHECK-NEXT: ret [[TMP0]] +// +svboolx2_t test_svset2_b8_0(svboolx2_t tuple, svbool_t x) +{ + return SVE_ACLE_FUNC(svset2,_b8,,)(tuple, 0, x); +} + +// CHECK-LABEL: @test_svset2_b8_1( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.insert.nxv32i1.nxv16i1( [[TUPLE:%.*]], [[X:%.*]], i64 16) +// CHECK-NEXT: ret [[TMP0]] +// +// CPP-CHECK-LABEL: @_Z16test_svset2_b8_110svboolx2_tu10__SVBool_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.insert.nxv32i1.nxv16i1( [[TUPLE:%.*]], [[X:%.*]], i64 16) +// CPP-CHECK-NEXT: ret [[TMP0]] +// +svboolx2_t test_svset2_b8_1(svboolx2_t tuple, svbool_t x) +{ + return SVE_ACLE_FUNC(svset2,_b8,,)(tuple, 1, x); +} + diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_set4_bool.c b/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_set4_bool.c new file mode 100644 index 0000000000000000000000000000000000000000..746a8280ac53f3036b5de2fa1f72b4115054c114 --- /dev/null +++ b/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_set4_bool.c @@ -0,0 +1,66 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve2p1 -S -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s \ +// RUN: | opt -S -passes=mem2reg,tailcallelim | FileCheck %s +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve2p1 -S -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s \ +// RUN: | opt -S -passes=mem2reg,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK +// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sve2p1 -S -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s \ +// RUN: | opt -S -passes=mem2reg,tailcallelim | FileCheck %s +// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sve2p1 -S -disable-O0-optnone -Werror -Wall -emit-llvm -o - -x c++ %s\ +// RUN: | opt -S -passes=mem2reg,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve2p1 -S -disable-O0-optnone -Werror -Wall -o /dev/null %s +// REQUIRES: aarch64-registered-target + +#include + +#ifdef SVE_OVERLOADED_FORMS +// A simple used,unused... macro, long enough to represent any SVE builtin. +#define SVE_ACLE_FUNC(A1,A2_UNUSED,A3,A4_UNUSED) A1##A3 +#else +#define SVE_ACLE_FUNC(A1,A2,A3,A4) A1##A2##A3##A4 +#endif + + +// CHECK-LABEL: @test_svset4_b8_0( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.insert.nxv64i1.nxv16i1( [[TUPLE:%.*]], [[X:%.*]], i64 0) +// CHECK-NEXT: ret [[TMP0]] +// +// CPP-CHECK-LABEL: @_Z16test_svset4_b8_010svboolx4_tu10__SVBool_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.insert.nxv64i1.nxv16i1( [[TUPLE:%.*]], [[X:%.*]], i64 0) +// CPP-CHECK-NEXT: ret [[TMP0]] +// +svboolx4_t test_svset4_b8_0(svboolx4_t tuple, svbool_t x) +{ + return SVE_ACLE_FUNC(svset4,_b8,,)(tuple, 0, x); +} + +// CHECK-LABEL: @test_svset4_b8_1( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.insert.nxv64i1.nxv16i1( [[TUPLE:%.*]], [[X:%.*]], i64 16) +// CHECK-NEXT: ret [[TMP0]] +// +// CPP-CHECK-LABEL: @_Z16test_svset4_b8_110svboolx4_tu10__SVBool_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.insert.nxv64i1.nxv16i1( [[TUPLE:%.*]], [[X:%.*]], i64 16) +// CPP-CHECK-NEXT: ret [[TMP0]] +// +svboolx4_t test_svset4_b8_1(svboolx4_t tuple, svbool_t x) +{ + return SVE_ACLE_FUNC(svset4,_b8,,)(tuple, 1, x); +} + +// CHECK-LABEL: @test_svset4_b8_3( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.insert.nxv64i1.nxv16i1( [[TUPLE:%.*]], [[X:%.*]], i64 48) +// CHECK-NEXT: ret [[TMP0]] +// +// CPP-CHECK-LABEL: @_Z16test_svset4_b8_310svboolx4_tu10__SVBool_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.insert.nxv64i1.nxv16i1( [[TUPLE:%.*]], [[X:%.*]], i64 48) +// CPP-CHECK-NEXT: ret [[TMP0]] +// +svboolx4_t test_svset4_b8_3(svboolx4_t tuple, svbool_t x) +{ + return SVE_ACLE_FUNC(svset4,_b8,,)(tuple, 3, x); +} diff --git a/clang/test/CodeGen/arm-target-features.c b/clang/test/CodeGen/arm-target-features.c index bd051059fb0cc178375cf76520e877b01c2474e1..ad4bfd45c408b5481060f09937a4a593502aab31 100644 --- a/clang/test/CodeGen/arm-target-features.c +++ b/clang/test/CodeGen/arm-target-features.c @@ -113,6 +113,9 @@ // RUN: %clang_cc1 -triple thumb-linux-gnueabi -target-cpu cortex-m85 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-ARMV81M-CORTEX-M85-LINUX // CHECK-ARMV81M-CORTEX-M85-LINUX: "target-features"="+armv8.1-m.main,+dsp,+fp-armv8d16,+fp-armv8d16sp,+fp16,+fp64,+fullfp16,+hwdiv,+lob,+mve,+mve.fp,+pacbti,+ras,+thumb-mode,+vfp2,+vfp2sp,+vfp3d16,+vfp3d16sp,+vfp4d16,+vfp4d16sp" +// RUN: %clang_cc1 -triple thumb-linux-gnueabi -target-cpu cortex-m52 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-ARMV81M-CORTEX-M52-LINUX +// CHECK-ARMV81M-CORTEX-M52-LINUX: "target-features"="+armv8.1-m.main,+dsp,+fp-armv8d16,+fp-armv8d16sp,+fp16,+fp64,+fullfp16,+hwdiv,+lob,+mve,+mve.fp,+pacbti,+ras,+thumb-mode,+vfp2,+vfp2sp,+vfp3d16,+vfp3d16sp,+vfp4d16,+vfp4d16sp" + // RUN: %clang_cc1 -triple thumbv9.3a-linux-gnueabihf -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-ARCH93 // CHECK-ARCH93: "target-features"="+armv9.3-a,+thumb-mode,+v8.1a,+v8.2a,+v8.3a,+v8.4a,+v8.5a,+v8.6a,+v8.7a,+v8.8a,+v9.1a,+v9.2a,+v9.3a,+v9a" diff --git a/clang/test/CodeGen/atomic-ops.c b/clang/test/CodeGen/atomic-ops.c index 1295786524a0d3feb90df8ed3425204f33fb9be2..9ac05d270b97c5a3163ac0750ca46a0becad0824 100644 --- a/clang/test/CodeGen/atomic-ops.c +++ b/clang/test/CodeGen/atomic-ops.c @@ -697,9 +697,9 @@ void test_underaligned(void) { __atomic_load(&aligned_a, &aligned_b, memory_order_seq_cst); // CHECK: store atomic i64 {{.*}}, align 16 __atomic_store(&aligned_a, &aligned_b, memory_order_seq_cst); - // CHECK: atomicrmw xchg ptr {{.*}}, align 8 + // CHECK: atomicrmw xchg ptr {{.*}}, align 16 __atomic_exchange(&aligned_a, &aligned_b, &aligned_c, memory_order_seq_cst); - // CHECK: cmpxchg weak ptr {{.*}}, align 8 + // CHECK: cmpxchg weak ptr {{.*}}, align 16 __atomic_compare_exchange(&aligned_a, &aligned_b, &aligned_c, 1, memory_order_seq_cst, memory_order_seq_cst); } diff --git a/clang/test/CodeGen/attr-target-clones.c b/clang/test/CodeGen/attr-target-clones.c index 98ffea40f56d887b8a49fb5a40bb7cdba8ec7f6a..4b99914031b10e557cbccd02abf228096cae95d7 100644 --- a/clang/test/CodeGen/attr-target-clones.c +++ b/clang/test/CodeGen/attr-target-clones.c @@ -16,13 +16,23 @@ // LINUX: @__cpu_model = external dso_local global { i32, i32, i32, [1 x i32] } // LINUX: @__cpu_features2 = external dso_local global [3 x i32] -// LINUX: @internal.ifunc = internal ifunc i32 (), ptr @internal.resolver -// LINUX: @foo.ifunc = weak_odr ifunc i32 (), ptr @foo.resolver -// LINUX: @foo_dupes.ifunc = weak_odr ifunc void (), ptr @foo_dupes.resolver -// LINUX: @unused.ifunc = weak_odr ifunc void (), ptr @unused.resolver -// LINUX: @foo_inline.ifunc = weak_odr ifunc i32 (), ptr @foo_inline.resolver -// LINUX: @foo_inline2.ifunc = weak_odr ifunc i32 (), ptr @foo_inline2.resolver -// LINUX: @foo_used_no_defn.ifunc = weak_odr ifunc i32 (), ptr @foo_used_no_defn.resolver +// LINUX: @internal.ifunc = internal alias i32 (), ptr @internal +// LINUX: @foo.ifunc = weak_odr alias i32 (), ptr @foo +// LINUX: @foo_dupes.ifunc = weak_odr alias void (), ptr @foo_dupes +// LINUX: @unused.ifunc = weak_odr alias void (), ptr @unused +// LINUX: @foo_inline.ifunc = weak_odr alias i32 (), ptr @foo_inline +// LINUX: @foo_inline2.ifunc = weak_odr alias i32 (), ptr @foo_inline2 +// LINUX: @foo_used_no_defn.ifunc = weak_odr alias i32 (), ptr @foo_used_no_defn +// LINUX: @isa_level.ifunc = weak_odr alias i32 (i32), ptr @isa_level + +// LINUX: @internal = internal ifunc i32 (), ptr @internal.resolver +// LINUX: @foo = weak_odr ifunc i32 (), ptr @foo.resolver +// LINUX: @foo_dupes = weak_odr ifunc void (), ptr @foo_dupes.resolver +// LINUX: @unused = weak_odr ifunc void (), ptr @unused.resolver +// LINUX: @foo_inline = weak_odr ifunc i32 (), ptr @foo_inline.resolver +// LINUX: @foo_inline2 = weak_odr ifunc i32 (), ptr @foo_inline2.resolver +// LINUX: @foo_used_no_defn = weak_odr ifunc i32 (), ptr @foo_used_no_defn.resolver +// LINUX: @isa_level = weak_odr ifunc i32 (i32), ptr @isa_level.resolver static int __attribute__((target_clones("sse4.2, default"))) internal(void) { return 0; } int use(void) { return internal(); } @@ -60,7 +70,7 @@ void bar2(void) { // LINUX: define {{.*}}void @bar2() // WINDOWS: define dso_local void @bar2() foo_dupes(); - // LINUX: call void @foo_dupes.ifunc() + // LINUX: call void @foo_dupes() // WINDOWS: call void @foo_dupes() } @@ -68,7 +78,7 @@ int bar(void) { // LINUX: define {{.*}}i32 @bar() #[[DEF:[0-9]+]] // WINDOWS: define dso_local i32 @bar() #[[DEF:[0-9]+]] return foo(); - // LINUX: call i32 @foo.ifunc() + // LINUX: call i32 @foo() // WINDOWS: call i32 @foo() } @@ -95,8 +105,8 @@ int bar3(void) { // LINUX: define {{.*}}i32 @bar3() // WINDOWS: define dso_local i32 @bar3() return foo_inline() + foo_inline2(); - // LINUX: call i32 @foo_inline.ifunc() - // LINUX: call i32 @foo_inline2.ifunc() + // LINUX: call i32 @foo_inline() + // LINUX: call i32 @foo_inline2() // WINDOWS: call i32 @foo_inline() // WINDOWS: call i32 @foo_inline2() } @@ -134,7 +144,7 @@ int test_foo_used_no_defn(void) { // LINUX: define {{.*}}i32 @test_foo_used_no_defn() // WINDOWS: define dso_local i32 @test_foo_used_no_defn() return foo_used_no_defn(); - // LINUX: call i32 @foo_used_no_defn.ifunc() + // LINUX: call i32 @foo_used_no_defn() // WINDOWS: call i32 @foo_used_no_defn() } diff --git a/clang/test/CodeGen/bpf-preserve-static-offset-arr.c b/clang/test/CodeGen/bpf-preserve-static-offset-arr.c new file mode 100644 index 0000000000000000000000000000000000000000..295bd2919fc651232bbb8571f0967df080f0537f --- /dev/null +++ b/clang/test/CodeGen/bpf-preserve-static-offset-arr.c @@ -0,0 +1,33 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 2 +// REQUIRES: bpf-registered-target +// RUN: %clang -cc1 -triple bpf -disable-llvm-passes -S -emit-llvm -o - %s \ +// RUN: | FileCheck %s + +// Check that call to preserve.static.offset is generated when array +// member of a struct marked with __attribute__((preserve_static_offset)) +// is accessed. + +#define __ctx __attribute__((preserve_static_offset)) + +struct foo { + struct { + int a; + } b[7]; +} __ctx; + +// CHECK-LABEL: define dso_local i32 @arr_access +// CHECK-SAME: (ptr noundef [[P:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[P_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[P]], ptr [[P_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P_ADDR]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = call ptr @llvm.preserve.static.offset(ptr [[TMP0]]) +// CHECK-NEXT: [[B:%.*]] = getelementptr inbounds [[STRUCT_FOO:%.*]], ptr [[TMP1]], i32 0, i32 0 +// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [7 x %struct.anon], ptr [[B]], i64 0, i64 2 +// CHECK-NEXT: [[A:%.*]] = getelementptr inbounds [[STRUCT_ANON:%.*]], ptr [[ARRAYIDX]], i32 0, i32 0 +// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[A]], align 4 +// CHECK-NEXT: ret i32 [[TMP2]] +// +int arr_access(struct foo *p) { + return p->b[2].a; +} diff --git a/clang/test/CodeGen/bpf-preserve-static-offset-bitfield.c b/clang/test/CodeGen/bpf-preserve-static-offset-bitfield.c new file mode 100644 index 0000000000000000000000000000000000000000..5983e6d27721c1d132766f85885eded6ef0cb8cf --- /dev/null +++ b/clang/test/CodeGen/bpf-preserve-static-offset-bitfield.c @@ -0,0 +1,31 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 2 +// REQUIRES: bpf-registered-target +// RUN: %clang -cc1 -triple bpfel -disable-llvm-passes -S -emit-llvm -o - %s \ +// RUN: | FileCheck %s + +// Check that call to preserve.static.offset is generated when bitfield +// from a struct marked with __attribute__((preserve_static_offset)) is +// accessed. + +#define __ctx __attribute__((preserve_static_offset)) + +struct foo { + unsigned a:1; +} __ctx; + +// CHECK-LABEL: define dso_local void @lvalue_bitfield +// CHECK-SAME: (ptr noundef [[P:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[P_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[P]], ptr [[P_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P_ADDR]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = call ptr @llvm.preserve.static.offset(ptr [[TMP0]]) +// CHECK-NEXT: [[BF_LOAD:%.*]] = load i8, ptr [[TMP1]], align 4 +// CHECK-NEXT: [[BF_CLEAR:%.*]] = and i8 [[BF_LOAD]], -2 +// CHECK-NEXT: [[BF_SET:%.*]] = or i8 [[BF_CLEAR]], 1 +// CHECK-NEXT: store i8 [[BF_SET]], ptr [[TMP1]], align 4 +// CHECK-NEXT: ret void +// +void lvalue_bitfield(struct foo *p) { + p->a = 1; +} diff --git a/clang/test/CodeGen/bpf-preserve-static-offset-lvalue.c b/clang/test/CodeGen/bpf-preserve-static-offset-lvalue.c new file mode 100644 index 0000000000000000000000000000000000000000..4f0c359366f5a5446b40544ae57aec84166261dc --- /dev/null +++ b/clang/test/CodeGen/bpf-preserve-static-offset-lvalue.c @@ -0,0 +1,28 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 2 +// REQUIRES: bpf-registered-target +// RUN: %clang -cc1 -triple bpf -disable-llvm-passes -S -emit-llvm -o - %s \ +// RUN: | FileCheck %s + +// Check that call to preserve.static.offset is generated when field of +// a struct marked with __attribute__((preserve_static_offset)) is accessed. + +#define __ctx __attribute__((preserve_static_offset)) + +struct foo { + int a; +} __ctx; + +// CHECK-LABEL: define dso_local void @lvalue +// CHECK-SAME: (ptr noundef [[P:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[P_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[P]], ptr [[P_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P_ADDR]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = call ptr @llvm.preserve.static.offset(ptr [[TMP0]]) +// CHECK-NEXT: [[A:%.*]] = getelementptr inbounds [[STRUCT_FOO:%.*]], ptr [[TMP1]], i32 0, i32 0 +// CHECK-NEXT: store i32 42, ptr [[A]], align 4 +// CHECK-NEXT: ret void +// +void lvalue(struct foo *p) { + p->a = 42; +} diff --git a/clang/test/CodeGen/bpf-preserve-static-offset-non-bpf.c b/clang/test/CodeGen/bpf-preserve-static-offset-non-bpf.c new file mode 100644 index 0000000000000000000000000000000000000000..3fe8d2517fe30afc36014dfdc21589c6a3f9a6ac --- /dev/null +++ b/clang/test/CodeGen/bpf-preserve-static-offset-non-bpf.c @@ -0,0 +1,18 @@ +// REQUIRES: x86-registered-target +// RUN: %clang -cc1 -triple x86_64 -disable-llvm-passes -S -emit-llvm -o - %s \ +// RUN: | FileCheck %s + +// Verify that __attribute__((preserve_static_offset)) +// has no effect for non-BPF target. + +#define __ctx __attribute__((preserve_static_offset)) + +struct foo { + int a; +} __ctx; + +// CHECK-NOT: @llvm_preserve_static_offset + +int bar(struct foo *p) { + return p->a; +} diff --git a/clang/test/CodeGen/bpf-preserve-static-offset-pai.c b/clang/test/CodeGen/bpf-preserve-static-offset-pai.c new file mode 100644 index 0000000000000000000000000000000000000000..df1f33b1a66415fe8fbe380407868ecf014d57db --- /dev/null +++ b/clang/test/CodeGen/bpf-preserve-static-offset-pai.c @@ -0,0 +1,29 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 2 +// REQUIRES: bpf-registered-target +// RUN: %clang -cc1 -triple bpf -disable-llvm-passes -S -emit-llvm -o - %s \ +// RUN: | FileCheck %s + +// Verify that preserve_static_offset does not interfere with +// preserve_access_index at IR generation stage. + +#define __ctx __attribute__((preserve_static_offset)) +#define __pai __attribute__((preserve_access_index)) + +struct foo { + int a; +} __ctx __pai; + +// CHECK-LABEL: define dso_local i32 @bar +// CHECK-SAME: (ptr noundef [[P:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[P_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[P]], ptr [[P_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P_ADDR]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = call ptr @llvm.preserve.static.offset(ptr [[TMP0]]) +// CHECK-NEXT: [[A:%.*]] = getelementptr inbounds [[STRUCT_FOO:%.*]], ptr [[TMP1]], i32 0, i32 0 +// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[A]], align 4 +// CHECK-NEXT: ret i32 [[TMP2]] +// +int bar(struct foo *p) { + return p->a; +} diff --git a/clang/test/CodeGen/complex-math.c b/clang/test/CodeGen/complex-math.c index c59baaa452369d66d71362b71e4efaafe77ca240..a44aa0014a6587955bdac9d6fca37d5e42adb3d7 100644 --- a/clang/test/CodeGen/complex-math.c +++ b/clang/test/CodeGen/complex-math.c @@ -5,7 +5,7 @@ // RUN: %clang_cc1 %s -O0 -emit-llvm -triple armv7-none-linux-gnueabi -o - | FileCheck %s --check-prefix=ARM // RUN: %clang_cc1 %s -O0 -emit-llvm -triple armv7-none-linux-gnueabihf -o - | FileCheck %s --check-prefix=ARMHF // RUN: %clang_cc1 %s -O0 -emit-llvm -triple thumbv7k-apple-watchos2.0 -o - -target-abi aapcs16 | FileCheck %s --check-prefix=ARM7K -// RUN: %clang_cc1 %s -O0 -emit-llvm -triple aarch64-unknown-unknown -ffast-math -ffp-contract=fast -o - | FileCheck %s --check-prefix=AARCH64-FASTMATH +// RUN: %clang_cc1 %s -O0 -emit-llvm -triple aarch64-unknown-unknown -ffast-math -ffp-contract=fast -complex-range=fortran -o - | FileCheck %s --check-prefix=AARCH64-FASTMATH // RUN: %clang_cc1 %s -O0 -emit-llvm -triple spir -o - | FileCheck %s --check-prefix=SPIR float _Complex add_float_rr(float a, float b) { @@ -135,24 +135,68 @@ float _Complex div_float_rc(float a, float _Complex b) { // SPIR: call spir_func {{.*}} @__divsc3( - // a / b = (A+iB) / (C+iD) = ((AC+BD)/(CC+DD)) + i((BC-AD)/(CC+DD)) + // a / b = (A+iB) / (C+iD) = (E+iF) + // if (|C| >= |D|) + // DdC = D/C + // CpRD = C+DdC*D + // E = (A+B*DdC)/CpRD + // F = (B-A*DdC)/CpRD + // else + // CdD = C/D + // DpRC= D+CdD*C + // E = (A*CdD+B)/DpRC + // F = (B*CdD-A)/DpRC // AARCH64-FASTMATH-LABEL: @div_float_rc(float noundef nofpclass(nan inf) %a, [2 x float] noundef nofpclass(nan inf) alignstack(8) %b.coerce) - // A = a - // B = 0 - // - // AARCH64-FASTMATH: [[AC:%.*]] = fmul fast float - // BD = 0 - // ACpBD = AC - // - // AARCH64-FASTMATH: [[CC:%.*]] = fmul fast float - // AARCH64-FASTMATH: [[DD:%.*]] = fmul fast float - // AARCH64-FASTMATH: [[CCpDD:%.*]] = fadd fast float - // - // BC = 0 - // AARCH64-FASTMATH: [[AD:%.*]] = fmul fast float - // - // AARCH64-FASTMATH: fdiv fast float - // AARCH64-FASTMATH: fdiv fast float + // |C| + // AARCH64-FASTMATH: call {{.*}}float @llvm.fabs.f32(float {{.*}}) + // |D| + // AARCH64-FASTMATH-NEXT: call {{.*}}float @llvm.fabs.f32(float {{.*}}) + // AARCH64-FASTMATH-NEXT: fcmp {{.*}}ugt float + // AARCH64-FASTMATH-NEXT: br i1 {{.*}}, label + // AARCH64-FASTMATH: abs_rhsr_greater_or_equal_abs_rhsi: + + // |C| >= |D| + // DdC=D/C + // AARCH64-FASTMATH-NEXT: fdiv {{.*}}float + + // CpRD=C+CdC*D + // AARCH64-FASTMATH-NEXT: fmul {{.*}}float + // AARCH64-FASTMATH-NEXT: fadd {{.*}}float + + // A+BR/CpRD + // AARCH64-FASTMATH-NEXT: fmul {{.*}}float + // AARCH64-FASTMATH-NEXT: fadd {{.*}}float + // AARCH64-FASTMATH-NEXT: fdiv {{.*}}float + + // B-AR/CpRD + // AARCH64-FASTMATH-NEXT: fmul {{.*}}float + // AARCH64-FASTMATH-NEXT: fsub {{.*}}float + // AARCH64-FASTMATH-NEXT: fdiv {{.*}}float + // AARCH64-FASTMATH-NEXT: br label + // AARCH64-FASTMATH: abs_rhsr_less_than_abs_rhsi: + + // |C| < |D| + // CdD=C/D + // AARCH64-FASTMATH-NEXT: fdiv {{.*}}float + + // DpRC=D+CdD*C + // AARCH64-FASTMATH-NEXT: fmul {{.*}}float + // AARCH64-FASTMATH-NEXT: fadd {{.*}}float + + // (A*CdD+B)/DpRC + // AARCH64-FASTMATH-NEXT: fmul {{.*}}float + // AARCH64-FASTMATH-NEXT: fadd {{.*}}float + // AARCH64-FASTMATH-NEXT: fdiv {{.*}}float + + // (BCdD-A)/DpRC + // AARCH64-FASTMATH-NEXT: fmul {{.*}}float + // AARCH64-FASTMATH-NEXT: fsub {{.*}}float + // AARCH64-FASTMATH-NEXT: fdiv {{.*}}float + + // AARCH64-FASTMATH-NEXT: br label + // AARCH64-FASTMATH: complex_div: + // AARCH64-FASTMATH-NEXT: phi {{.*}}float + // AARCH64-FASTMATH-NEXT: phi {{.*}}float // AARCH64-FASTMATH: ret return a / b; } @@ -164,24 +208,68 @@ float _Complex div_float_cc(float _Complex a, float _Complex b) { // SPIR: call spir_func {{.*}} @__divsc3( - // a / b = (A+iB) / (C+iD) = ((AC+BD)/(CC+DD)) + i((BC-AD)/(CC+DD)) + // a / b = (A+iB) / (C+iD) = (E+iF) + // if (|C| >= |D|) + // DdC = D/C + // CpRD = C+DdC*D + // E = (A+B*DdC)/CpRD + // F = (B-A*DdC)/CpRD + // else + // CdD = C/D + // DpRC= D+CdD*C + // E = (A*CdD+B)/DpRC + // F = (B*CdD-A)/DpRC // AARCH64-FASTMATH-LABEL: @div_float_cc([2 x float] noundef nofpclass(nan inf) alignstack(8) %a.coerce, [2 x float] noundef nofpclass(nan inf) alignstack(8) %b.coerce) - // - // AARCH64-FASTMATH: [[AC:%.*]] = fmul fast float - // AARCH64-FASTMATH: [[BD:%.*]] = fmul fast float - // AARCH64-FASTMATH: [[ACpBD:%.*]] = fadd fast float - // - // AARCH64-FASTMATH: [[CC:%.*]] = fmul fast float - // AARCH64-FASTMATH: [[DD:%.*]] = fmul fast float - // AARCH64-FASTMATH: [[CCpDD:%.*]] = fadd fast float - // - // AARCH64-FASTMATH: [[BC:%.*]] = fmul fast float - // AARCH64-FASTMATH: [[AD:%.*]] = fmul fast float - // AARCH64-FASTMATH: [[BCmAD:%.*]] = fsub fast float - // - // AARCH64-FASTMATH: fdiv fast float - // AARCH64-FASTMATH: fdiv fast float - // AARCH64-FASTMATH: ret + // |C| + // AARCH64-FASTMATH: call {{.*}}float @llvm.fabs.f32(float {{.*}}) + // |D| + // AARCH64-FASTMATH-NEXT: call {{.*}}float @llvm.fabs.f32(float {{.*}}) + // AARCH64-FASTMATH-NEXT: fcmp {{.*}}ugt float + // AARCH64-FASTMATH-NEXT: br i1 {{.*}}, label + // AARCH64-FASTMATH: abs_rhsr_greater_or_equal_abs_rhsi: + + // |C| >= |D| + // DdC=D/C + // AARCH64-FASTMATH-NEXT: fdiv {{.*}}float + + // CpRD=C+CdC*D + // AARCH64-FASTMATH-NEXT: fmul {{.*}}float + // AARCH64-FASTMATH-NEXT: fadd {{.*}}float + + // A+BR/CpRD + // AARCH64-FASTMATH-NEXT: fmul {{.*}}float + // AARCH64-FASTMATH-NEXT: fadd {{.*}}float + // AARCH64-FASTMATH-NEXT: fdiv {{.*}}float + + // B-AR/CpRD + // AARCH64-FASTMATH-NEXT: fmul {{.*}}float + // AARCH64-FASTMATH-NEXT: fsub {{.*}}float + // AARCH64-FASTMATH-NEXT: fdiv {{.*}}float + // AARCH64-FASTMATH-NEXT: br label + // AARCH64-FASTMATH: abs_rhsr_less_than_abs_rhsi: + + // |C| < |D| + // CdD=C/D + // AARCH64-FASTMATH-NEXT: fdiv {{.*}}float + + // DpRC=D+CdD*C + // AARCH64-FASTMATH-NEXT: fmul {{.*}}float + // AARCH64-FASTMATH-NEXT: fadd {{.*}}float + + // (A*CdD+B)/DpRC + // AARCH64-FASTMATH-NEXT: fmul {{.*}}float + // AARCH64-FASTMATH-NEXT: fadd {{.*}}float + // AARCH64-FASTMATH-NEXT: fdiv {{.*}}float + + // (BCdD-A)/DpRC + // AARCH64-FASTMATH-NEXT: fmul {{.*}}float + // AARCH64-FASTMATH-NEXT: fsub {{.*}}float + // AARCH64-FASTMATH-NEXT: fdiv {{.*}}float + + // AARCH64-FASTMATH-NEXT: br label + // AARCH64-FASTMATH: complex_div: + // AARCH64-FASTMATH-NEXT: phi {{.*}}float + // AARCH64-FASTMATH-NEXT: phi {{.*}}float return a / b; } @@ -312,24 +400,68 @@ double _Complex div_double_rc(double a, double _Complex b) { // SPIR: call spir_func {{.*}} @__divdc3( - // a / b = (A+iB) / (C+iD) = ((AC+BD)/(CC+DD)) + i((BC-AD)/(CC+DD)) + // a / b = (A+iB) / (C+iD) = (E+iF) + // if (|C| >= |D|) + // DdC = D/C + // CpRD = C+DdC*D + // E = (A+B*DdC)/CpRD + // F = (B-A*DdC)/CpRD + // else + // CdD = C/D + // DpRC= D+CdD*C + // E = (A*CdD+B)/DpRC + // F = (B*CdD-A)/DpRC // AARCH64-FASTMATH-LABEL: @div_double_rc(double noundef nofpclass(nan inf) %a, [2 x double] noundef nofpclass(nan inf) alignstack(8) %b.coerce) - // A = a - // B = 0 - // - // AARCH64-FASTMATH: [[AC:%.*]] = fmul fast double - // BD = 0 - // ACpBD = AC - // - // AARCH64-FASTMATH: [[CC:%.*]] = fmul fast double - // AARCH64-FASTMATH: [[DD:%.*]] = fmul fast double - // AARCH64-FASTMATH: [[CCpDD:%.*]] = fadd fast double - // - // BC = 0 - // AARCH64-FASTMATH: [[AD:%.*]] = fmul fast double - // - // AARCH64-FASTMATH: fdiv fast double - // AARCH64-FASTMATH: fdiv fast double + // |C| + // AARCH64-FASTMATH: call {{.*}}double @llvm.fabs.f64(double {{.*}}) + // |D| + // AARCH64-FASTMATH-NEXT: call {{.*}}double @llvm.fabs.f64(double {{.*}}) + // AARCH64-FASTMATH-NEXT: fcmp {{.*}}ugt double + // AARCH64-FASTMATH-NEXT: br i1 {{.*}}, label + // AARCH64-FASTMATH: abs_rhsr_greater_or_equal_abs_rhsi: + + // |C| >= |D| + // DdC=D/C + // AARCH64-FASTMATH-NEXT: fdiv {{.*}}double + + // CpRD=C+CdC*D + // AARCH64-FASTMATH-NEXT: fmul {{.*}}double + // AARCH64-FASTMATH-NEXT: fadd {{.*}}double + + // A+BR/CpRD + // AARCH64-FASTMATH-NEXT: fmul {{.*}}double + // AARCH64-FASTMATH-NEXT: fadd {{.*}}double + // AARCH64-FASTMATH-NEXT: fdiv {{.*}}double + + // B-AR/CpRD + // AARCH64-FASTMATH-NEXT: fmul {{.*}}double + // AARCH64-FASTMATH-NEXT: fsub {{.*}}double + // AARCH64-FASTMATH-NEXT: fdiv {{.*}}double + // AARCH64-FASTMATH-NEXT: br label + // AARCH64-FASTMATH: abs_rhsr_less_than_abs_rhsi: + + // |C| < |D| + // CdD=C/D + // AARCH64-FASTMATH-NEXT: fdiv {{.*}}double + + // DpRC=D+CdD*C + // AARCH64-FASTMATH-NEXT: fmul {{.*}}double + // AARCH64-FASTMATH-NEXT: fadd {{.*}}double + + // (A*CdD+B)/DpRC + // AARCH64-FASTMATH-NEXT: fmul {{.*}}double + // AARCH64-FASTMATH-NEXT: fadd {{.*}}double + // AARCH64-FASTMATH-NEXT: fdiv {{.*}}double + + // (BCdD-A)/DpRC + // AARCH64-FASTMATH-NEXT: fmul {{.*}}double + // AARCH64-FASTMATH-NEXT: fsub {{.*}}double + // AARCH64-FASTMATH-NEXT: fdiv {{.*}}double + + // AARCH64-FASTMATH-NEXT: br label + // AARCH64-FASTMATH: complex_div: + // AARCH64-FASTMATH-NEXT: phi {{.*}}double + // AARCH64-FASTMATH-NEXT: phi {{.*}}double // AARCH64-FASTMATH: ret return a / b; } @@ -341,23 +473,68 @@ double _Complex div_double_cc(double _Complex a, double _Complex b) { // SPIR: call spir_func {{.*}} @__divdc3( - // a / b = (A+iB) / (C+iD) = ((AC+BD)/(CC+DD)) + i((BC-AD)/(CC+DD)) + // a / b = (A+iB) / (C+iD) = (E+iF) + // if (|C| >= |D|) + // DdC = D/C + // CpRD = C+DdC*D + // E = (A+B*DdC)/CpRD + // F = (B-A*DdC)/CpRD + // else + // CdD = C/D + // DpRC= D+CdD*C + // E = (A*CdD+B)/DpRC + // F = (B*CdD-A)/DpRC // AARCH64-FASTMATH-LABEL: @div_double_cc([2 x double] noundef nofpclass(nan inf) alignstack(8) %a.coerce, [2 x double] noundef nofpclass(nan inf) alignstack(8) %b.coerce) - // - // AARCH64-FASTMATH: [[AC:%.*]] = fmul fast double - // AARCH64-FASTMATH: [[BD:%.*]] = fmul fast double - // AARCH64-FASTMATH: [[ACpBD:%.*]] = fadd fast double - // - // AARCH64-FASTMATH: [[CC:%.*]] = fmul fast double - // AARCH64-FASTMATH: [[DD:%.*]] = fmul fast double - // AARCH64-FASTMATH: [[CCpDD:%.*]] = fadd fast double - // - // AARCH64-FASTMATH: [[BC:%.*]] = fmul fast double - // AARCH64-FASTMATH: [[AD:%.*]] = fmul fast double - // AARCH64-FASTMATH: [[BCmAD:%.*]] = fsub fast double - // - // AARCH64-FASTMATH: fdiv fast double - // AARCH64-FASTMATH: fdiv fast double + // |C| + // AARCH64-FASTMATH: call {{.*}}double @llvm.fabs.f64(double {{.*}}) + // |D| + // AARCH64-FASTMATH-NEXT: call {{.*}}double @llvm.fabs.f64(double {{.*}}) + // AARCH64-FASTMATH-NEXT: fcmp {{.*}}ugt double + // AARCH64-FASTMATH-NEXT: br i1 {{.*}}, label + // AARCH64-FASTMATH: abs_rhsr_greater_or_equal_abs_rhsi: + + // |C| >= |D| + // DdC=D/C + // AARCH64-FASTMATH-NEXT: fdiv {{.*}}double + + // CpRD=C+CdC*D + // AARCH64-FASTMATH-NEXT: fmul {{.*}}double + // AARCH64-FASTMATH-NEXT: fadd {{.*}}double + + // A+BR/CpRD + // AARCH64-FASTMATH-NEXT: fmul {{.*}}double + // AARCH64-FASTMATH-NEXT: fadd {{.*}}double + // AARCH64-FASTMATH-NEXT: fdiv {{.*}}double + + // B-AR/CpRD + // AARCH64-FASTMATH-NEXT: fmul {{.*}}double + // AARCH64-FASTMATH-NEXT: fsub {{.*}}double + // AARCH64-FASTMATH-NEXT: fdiv {{.*}}double + // AARCH64-FASTMATH-NEXT: br label + // AARCH64-FASTMATH: abs_rhsr_less_than_abs_rhsi: + + // |C| < |D| + // CdD=C/D + // AARCH64-FASTMATH-NEXT: fdiv {{.*}}double + + // DpRC=D+CdD*C + // AARCH64-FASTMATH-NEXT: fmul {{.*}}double + // AARCH64-FASTMATH-NEXT: fadd {{.*}}double + + // (A*CdD+B)/DpRC + // AARCH64-FASTMATH-NEXT: fmul {{.*}}double + // AARCH64-FASTMATH-NEXT: fadd {{.*}}double + // AARCH64-FASTMATH-NEXT: fdiv {{.*}}double + + // (BCdD-A)/DpRC + // AARCH64-FASTMATH-NEXT: fmul {{.*}}double + // AARCH64-FASTMATH-NEXT: fsub {{.*}}double + // AARCH64-FASTMATH-NEXT: fdiv {{.*}}double + + // AARCH64-FASTMATH-NEXT: br label + // AARCH64-FASTMATH: complex_div: + // AARCH64-FASTMATH-NEXT: phi {{.*}}double + // AARCH64-FASTMATH-NEXT: phi {{.*}}double // AARCH64-FASTMATH: ret return a / b; } @@ -505,24 +682,68 @@ long double _Complex div_long_double_rc(long double a, long double _Complex b) { // PPC: ret // SPIR: call spir_func {{.*}} @__divdc3( - // a / b = (A+iB) / (C+iD) = ((AC+BD)/(CC+DD)) + i((BC-AD)/(CC+DD)) + // a / b = (A+iB) / (C+iD) = (E+iF) + // if (|C| >= |D|) + // DdC = D/C + // CpRD = C+DdC*D + // E = (A+B*DdC)/CpRD + // F = (B-A*DdC)/CpRD + // else + // CdD = C/D + // DpRC= D+CdD*C + // E = (A*CdD+B)/DpRC + // F = (B*CdD-A)/DpRC // AARCH64-FASTMATH-LABEL: @div_long_double_rc(fp128 noundef nofpclass(nan inf) %a, [2 x fp128] noundef nofpclass(nan inf) alignstack(16) %b.coerce) - // A = a - // B = 0 - // - // AARCH64-FASTMATH: [[AC:%.*]] = fmul fast fp128 - // BD = 0 - // ACpBD = AC - // - // AARCH64-FASTMATH: [[CC:%.*]] = fmul fast fp128 - // AARCH64-FASTMATH: [[DD:%.*]] = fmul fast fp128 - // AARCH64-FASTMATH: [[CCpDD:%.*]] = fadd fast fp128 - // - // BC = 0 - // AARCH64-FASTMATH: [[AD:%.*]] = fmul fast fp128 - // - // AARCH64-FASTMATH: fdiv fast fp128 - // AARCH64-FASTMATH: fdiv fast fp128 + // |C| + // AARCH64-FASTMATH: call {{.*}}fp128 @llvm.fabs.f128(fp128 {{.*}}) + // |D| + // AARCH64-FASTMATH-NEXT: call {{.*}}fp128 @llvm.fabs.f128(fp128 {{.*}}) + // AARCH64-FASTMATH-NEXT: fcmp {{.*}}ugt fp128 + // AARCH64-FASTMATH-NEXT: br i1 {{.*}}, label + // AARCH64-FASTMATH: abs_rhsr_greater_or_equal_abs_rhsi: + + // |C| >= |D| + // DdC=D/C + // AARCH64-FASTMATH-NEXT: fdiv {{.*}}fp128 + + // CpRD=C+CdC*D + // AARCH64-FASTMATH-NEXT: fmul {{.*}}fp128 + // AARCH64-FASTMATH-NEXT: fadd {{.*}}fp128 + + // A+BR/CpRD + // AARCH64-FASTMATH-NEXT: fmul {{.*}}fp128 + // AARCH64-FASTMATH-NEXT: fadd {{.*}}fp128 + // AARCH64-FASTMATH-NEXT: fdiv {{.*}}fp128 + + // B-AR/CpRD + // AARCH64-FASTMATH-NEXT: fmul {{.*}}fp128 + // AARCH64-FASTMATH-NEXT: fsub {{.*}}fp128 + // AARCH64-FASTMATH-NEXT: fdiv {{.*}}fp128 + // AARCH64-FASTMATH-NEXT: br label + // AARCH64-FASTMATH: abs_rhsr_less_than_abs_rhsi: + + // |C| < |D| + // CdD=C/D + // AARCH64-FASTMATH-NEXT: fdiv {{.*}}fp128 + + // DpRC=D+CdD*C + // AARCH64-FASTMATH-NEXT: fmul {{.*}}fp128 + // AARCH64-FASTMATH-NEXT: fadd {{.*}}fp128 + + // (A*CdD+B)/DpRC + // AARCH64-FASTMATH-NEXT: fmul {{.*}}fp128 + // AARCH64-FASTMATH-NEXT: fadd {{.*}}fp128 + // AARCH64-FASTMATH-NEXT: fdiv {{.*}}fp128 + + // (BCdD-A)/DpRC + // AARCH64-FASTMATH-NEXT: fmul {{.*}}fp128 + // AARCH64-FASTMATH-NEXT: fsub {{.*}}fp128 + // AARCH64-FASTMATH-NEXT: fdiv {{.*}}fp128 + + // AARCH64-FASTMATH-NEXT: br label + // AARCH64-FASTMATH: complex_div: + // AARCH64-FASTMATH-NEXT: phi {{.*}}fp128 + // AARCH64-FASTMATH-NEXT: phi {{.*}}fp128 // AARCH64-FASTMATH: ret return a / b; } @@ -537,23 +758,68 @@ long double _Complex div_long_double_cc(long double _Complex a, long double _Com // PPC: ret // SPIR: call spir_func {{.*}} @__divdc3( - // a / b = (A+iB) / (C+iD) = ((AC+BD)/(CC+DD)) + i((BC-AD)/(CC+DD)) + // a / b = (A+iB) / (C+iD) = (E+iF) + // if (|C| >= |D|) + // DdC = D/C + // CpRD = C+DdC*D + // E = (A+B*DdC)/CpRD + // F = (B-A*DdC)/CpRD + // else + // CdD = C/D + // DpRC= D+CdD*C + // E = (A*CdD+B)/DpRC + // F = (B*CdD-A)/DpRC // AARCH64-FASTMATH-LABEL: @div_long_double_cc([2 x fp128] noundef nofpclass(nan inf) alignstack(16) %a.coerce, [2 x fp128] noundef nofpclass(nan inf) alignstack(16) %b.coerce) - // - // AARCH64-FASTMATH: [[AC:%.*]] = fmul fast fp128 - // AARCH64-FASTMATH: [[BD:%.*]] = fmul fast fp128 - // AARCH64-FASTMATH: [[ACpBD:%.*]] = fadd fast fp128 - // - // AARCH64-FASTMATH: [[CC:%.*]] = fmul fast fp128 - // AARCH64-FASTMATH: [[DD:%.*]] = fmul fast fp128 - // AARCH64-FASTMATH: [[CCpDD:%.*]] = fadd fast fp128 - // - // AARCH64-FASTMATH: [[BC:%.*]] = fmul fast fp128 - // AARCH64-FASTMATH: [[AD:%.*]] = fmul fast fp128 - // AARCH64-FASTMATH: [[BCmAD:%.*]] = fsub fast fp128 - // - // AARCH64-FASTMATH: fdiv fast fp128 - // AARCH64-FASTMATH: fdiv fast fp128 + // |C| + // AARCH64-FASTMATH: call {{.*}}fp128 @llvm.fabs.f128(fp128 {{.*}}) + // |D| + // AARCH64-FASTMATH-NEXT: call {{.*}}fp128 @llvm.fabs.f128(fp128 {{.*}}) + // AARCH64-FASTMATH-NEXT: fcmp {{.*}}ugt fp128 + // AARCH64-FASTMATH-NEXT: br i1 {{.*}}, label + // AARCH64-FASTMATH: abs_rhsr_greater_or_equal_abs_rhsi: + + // |C| >= |D| + // DdC=D/C + // AARCH64-FASTMATH-NEXT: fdiv {{.*}}fp128 + + // CpRD=C+CdC*D + // AARCH64-FASTMATH-NEXT: fmul {{.*}}fp128 + // AARCH64-FASTMATH-NEXT: fadd {{.*}}fp128 + + // A+BR/CpRD + // AARCH64-FASTMATH-NEXT: fmul {{.*}}fp128 + // AARCH64-FASTMATH-NEXT: fadd {{.*}}fp128 + // AARCH64-FASTMATH-NEXT: fdiv {{.*}}fp128 + + // B-AR/CpRD + // AARCH64-FASTMATH-NEXT: fmul {{.*}}fp128 + // AARCH64-FASTMATH-NEXT: fsub {{.*}}fp128 + // AARCH64-FASTMATH-NEXT: fdiv {{.*}}fp128 + // AARCH64-FASTMATH-NEXT: br label + // AARCH64-FASTMATH: abs_rhsr_less_than_abs_rhsi: + + // |C| < |D| + // CdD=C/D + // AARCH64-FASTMATH-NEXT: fdiv {{.*}}fp128 + + // DpRC=D+CdD*C + // AARCH64-FASTMATH-NEXT: fmul {{.*}}fp128 + // AARCH64-FASTMATH-NEXT: fadd {{.*}}fp128 + + // (A*CdD+B)/DpRC + // AARCH64-FASTMATH-NEXT: fmul {{.*}}fp128 + // AARCH64-FASTMATH-NEXT: fadd {{.*}}fp128 + // AARCH64-FASTMATH-NEXT: fdiv {{.*}}fp128 + + // (BCdD-A)/DpRC + // AARCH64-FASTMATH-NEXT: fmul {{.*}}fp128 + // AARCH64-FASTMATH-NEXT: fsub {{.*}}fp128 + // AARCH64-FASTMATH-NEXT: fdiv {{.*}}fp128 + + // AARCH64-FASTMATH-NEXT: br label + // AARCH64-FASTMATH: complex_div: + // AARCH64-FASTMATH-NEXT: phi {{.*}}fp128 + // AARCH64-FASTMATH-NEXT: phi {{.*}}fp128 // AARCH64-FASTMATH: ret return a / b; } diff --git a/clang/test/CodeGen/cx-complex-range.c b/clang/test/CodeGen/cx-complex-range.c new file mode 100644 index 0000000000000000000000000000000000000000..8368fa611335cca7595e921fd754119b5119a3c4 --- /dev/null +++ b/clang/test/CodeGen/cx-complex-range.c @@ -0,0 +1,108 @@ +// RUN: %clang_cc1 %s -O0 -emit-llvm -triple x86_64-unknown-unknown \ +// RUN: -o - | FileCheck %s --check-prefix=FULL + +// RUN: %clang_cc1 %s -O0 -emit-llvm -triple x86_64-unknown-unknown \ +// RUN: -complex-range=limited -o - | FileCheck %s --check-prefix=LMTD + +// RUN: %clang_cc1 %s -O0 -emit-llvm -triple x86_64-unknown-unknown \ +// RUN: -fno-cx-limited-range -o - | FileCheck %s --check-prefix=FULL + +// RUN: %clang_cc1 %s -O0 -emit-llvm -triple x86_64-unknown-unknown \ +// RUN: -complex-range=fortran -o - | FileCheck %s --check-prefix=FRTRN + +// Fast math +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu \ +// RUN: -ffast-math -complex-range=limited -emit-llvm -o - %s \ +// RUN: | FileCheck %s --check-prefix=LMTD-FAST + +// RUN: %clang_cc1 %s -O0 -emit-llvm -triple x86_64-unknown-unknown \ +// RUN: -fno-cx-fortran-rules -o - | FileCheck %s --check-prefix=FULL + +_Complex float div(_Complex float a, _Complex float b) { + // LABEL: define {{.*}} @div( + // FULL: call {{.*}} @__divsc3 + + // LMTD: fmul float + // LMTD-NEXT: fmul float + // LMTD-NEXT: fadd float + // LMTD-NEXT: fmul float + // LMTD-NEXT: fmul float + // LMTD-NEXT: fadd float + // LMTD-NEXT: fmul float + // LMTD-NEXT: fmul float + // LMTD-NEXT: fsub float + // LMTD-NEXT: fdiv float + // LMTD-NEXT: fdiv float + + // FRTRN: call {{.*}}float @llvm.fabs.f32(float {{.*}}) + // FRTRN-NEXT: call {{.*}}float @llvm.fabs.f32(float {{.*}}) + // FRTRN-NEXT: fcmp {{.*}}ugt float + // FRTRN-NEXT: br i1 {{.*}}, label + // FRTRN: abs_rhsr_greater_or_equal_abs_rhsi: + // FRTRN-NEXT: fdiv {{.*}}float + // FRTRN-NEXT: fmul {{.*}}float + // FRTRN-NEXT: fadd {{.*}}float + // FRTRN-NEXT: fmul {{.*}}float + // FRTRN-NEXT: fadd {{.*}}float + // FRTRN-NEXT: fdiv {{.*}}float + // FRTRN-NEXT: fmul {{.*}}float + // FRTRN-NEXT: fsub {{.*}}float + // FRTRN-NEXT: fdiv {{.*}}float + // FRTRN-NEXT: br label + // FRTRN: abs_rhsr_less_than_abs_rhsi: + // FRTRN-NEXT: fdiv {{.*}}float + // FRTRN-NEXT: fmul {{.*}}float + // FRTRN-NEXT: fadd {{.*}}float + // FRTRN-NEXT: fmul {{.*}}float + // FRTRN-NEXT: fadd {{.*}}float + // FRTRN-NEXT: fdiv {{.*}}float + // FRTRN-NEXT: fmul {{.*}}float + // FRTRN-NEXT: fsub {{.*}}float + // FRTRN-NEXT: fdiv {{.*}}float + // FRTRN-NEXT: br label + // FRTRN: complex_div: + // FRTRN-NEXT: phi {{.*}}float + // FRTRN-NEXT: phi {{.*}}float + + // LMTD-FAST: fmul {{.*}} float + // LMTD-FAST-NEXT: fmul {{.*}} float + // LMTD-FAST-NEXT: fadd {{.*}} float + // LMTD-FAST-NEXT: fmul {{.*}} float + // LMTD-FAST-NEXT: fmul {{.*}} float + // LMTD-FAST-NEXT: fadd {{.*}} float + // LMTD-FAST-NEXT: fmul {{.*}} float + // LMTD-FAST-NEXT: fmul {{.*}} float + // LMTD-FAST-NEXT: fsub {{.*}} float + // LMTD-FAST-NEXT: fdiv {{.*}} float + // LMTD-FAST-NEXT: fdiv {{.*}} float + + return a / b; +} + +_Complex float mul(_Complex float a, _Complex float b) { + // LABEL: define {{.*}} @mul( + // FULL: call {{.*}} @__mulsc3 + + // LMTD: fmul float + // LMTD-NEXT: fmul float + // LMTD-NEXT: fmul float + // LMTD-NEXT: fmul float + // LMTD-NEXT: fsub float + // LMTD-NEXT: fadd float + + // FRTRN: fmul {{.*}}float + // FRTRN-NEXT: fmul {{.*}}float + // FRTRN-NEXT: fmul {{.*}}float + // FRTRN-NEXT: fmul {{.*}}float + // FRTRN-NEXT: fsub {{.*}}float + // FRTRN-NEXT: fadd {{.*}}float + + // LMTD-FAST: fmul {{.*}} float + // LMTD-FAST-NEXT: fmul {{.*}} float + // LMTD-FAST-NEXT: fmul {{.*}} float + // LMTD-FAST-NEXT: fmul {{.*}} float + // LMTD-FAST-NEXT: fsub {{.*}} float + // LMTD-FAST-NEXT: fadd {{.*}} float + + return a * b; +} diff --git a/clang/test/CodeGen/debug-info-preprocessed-file.i b/clang/test/CodeGen/debug-info-preprocessed-file.i index 23fd26525e3bf03a97abf7c520d21f8005a172ef..c8a2307d46c3163b4dd37756b10c59f1865f832a 100644 --- a/clang/test/CodeGen/debug-info-preprocessed-file.i +++ b/clang/test/CodeGen/debug-info-preprocessed-file.i @@ -6,6 +6,10 @@ # 1 "" 2 # 1 "preprocessed-input.c" 2 +/// The main file is preprocessed. We change it to preprocessed-input.c. Since +/// the content is not available, we don't compute a checksum. // RUN: %clang -g -c -S -emit-llvm -o - %s | FileCheck %s // CHECK: !DICompileUnit(language: DW_LANG_C{{.*}}, file: ![[FILE:[0-9]+]] // CHECK: ![[FILE]] = !DIFile(filename: "/foo/bar/preprocessed-input.c" +// CHECK-NOT: checksumkind: +// CHECK-NOT: !DIFile( diff --git a/clang/test/CodeGen/ms-intrinsics-underaligned.c b/clang/test/CodeGen/ms-intrinsics-underaligned.c new file mode 100644 index 0000000000000000000000000000000000000000..e1f0d2cba8e25733a2dd7985ba9769dd4037ba72 --- /dev/null +++ b/clang/test/CodeGen/ms-intrinsics-underaligned.c @@ -0,0 +1,110 @@ +// RUN: %clang_cc1 -ffreestanding -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 \ +// RUN: -triple x86_64--windows -Oz -emit-llvm -target-feature +cx16 %s -o - \ +// RUN: | FileCheck %s --check-prefixes=CHECK + +// RUN: %clang_cc1 -ffreestanding -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 \ +// RUN: -triple aarch64--windows -Oz -emit-llvm %s -o - \ +// RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-AARCH64 + +// Ensure that we emit _Interlocked atomic operations specifying natural +// alignment, even when clang's usual alignment derivation would result in a +// lower alignment value. + +// intrin.h needs size_t, but -ffreestanding prevents us from getting it from +// stddef.h. Work around it with this typedef. +typedef __SIZE_TYPE__ size_t; + +#include + +#pragma pack(1) +typedef struct { + char a; + short b; + long c; + long long d; + void *p; +} X; + +_Static_assert(sizeof(X) == 23, ""); +_Static_assert(__alignof__(X) == 1, ""); + +// CHECK-LABEL: @test_InterlockedExchangePointer( +// CHECK: atomicrmw {{.*}} align 8 +void *test_InterlockedExchangePointer(X *x) { + return _InterlockedExchangePointer(&x->p, 0); +} + +// CHECK-LABEL: @test_InterlockedExchange8( +// CHECK: atomicrmw {{.*}} align 1 +char test_InterlockedExchange8(X *x) { + return _InterlockedExchange8(&x->a, 0); +} + +// CHECK-LABEL: @test_InterlockedExchange16( +// CHECK: atomicrmw {{.*}} align 2 +short test_InterlockedExchange16(X *x) { + return _InterlockedExchange16(&x->b, 0); +} + +// CHECK-LABEL: @test_InterlockedExchange( +// CHECK: atomicrmw {{.*}} align 4 +long test_InterlockedExchange(X *x) { + return _InterlockedExchange(&x->c, 0); +} + +// CHECK-LABEL: @test_InterlockedExchange64( +// CHECK: atomicrmw {{.*}} align 8 +long long test_InterlockedExchange64(X *x) { + return _InterlockedExchange64(&x->d, 0); +} + +// CHECK-LABEL: @test_InterlockedIncrement( +// CHECK: atomicrmw {{.*}} align 4 +long test_InterlockedIncrement(X *x) { + return _InterlockedIncrement(&x->c); +} + +// CHECK-LABEL: @test_InterlockedDecrement16( +// CHECK: atomicrmw {{.*}} align 2 +short test_InterlockedDecrement16(X *x) { + return _InterlockedDecrement16(&x->b); +} + + +// CHECK-LABEL: @test_InterlockedCompareExchangePointer( +// CHECK: cmpxchg {{.*}} align 8 +void *test_InterlockedCompareExchangePointer(X *x) { + return _InterlockedCompareExchangePointer(&x->p, 0, 0); +} + +// CHECK-LABEL: @test_InterlockedCompareExchange8( +// CHECK: cmpxchg {{.*}} align 1 +char test_InterlockedCompareExchange8(X *x) { + return _InterlockedCompareExchange8(&x->a, 0, 0); +} + +// CHECK-LABEL: @test_InterlockedCompareExchange16( +// CHECK: cmpxchg {{.*}} align 2 +short test_InterlockedCompareExchange16(X *x) { + return _InterlockedCompareExchange16(&x->b, 0, 0); +} + +// CHECK-LABEL: @test_InterlockedCompareExchange( +// CHECK: cmpxchg {{.*}} align 4 +long test_InterlockedCompareExchange(X *x) { + return _InterlockedCompareExchange(&x->c, 0, 0); +} + +// CHECK-LABEL: @test_InterlockedCompareExchange64( +// CHECK: cmpxchg {{.*}} align 8 +long long test_InterlockedCompareExchange64(X *x) { + return _InterlockedCompareExchange64(&x->d, 0, 0); +} + +#ifdef __aarch64__ +// CHECK-AARCH64-LABEL: @test_InterlockedAdd( +// CHECK-AARCH64: atomicrmw {{.*}} align 4 +long test_InterlockedAdd(X *x) { + return _InterlockedAdd(&x->c, 4); +} +#endif diff --git a/clang/test/CodeGen/ms-intrinsics.c b/clang/test/CodeGen/ms-intrinsics.c index debc84404aed1c12e5983743ffdb21737c7e9f8a..ffab8b998d8bdfb888b290b9ef20619eee526842 100644 --- a/clang/test/CodeGen/ms-intrinsics.c +++ b/clang/test/CodeGen/ms-intrinsics.c @@ -445,10 +445,10 @@ unsigned char test_InterlockedCompareExchange128( // CHECK-64: [[EL:%[0-9]+]] = zext i64 %inc1 to i128 // CHECK-64: [[EHS:%[0-9]+]] = shl nuw i128 [[EH]], 64 // CHECK-64: [[EXP:%[0-9]+]] = or disjoint i128 [[EHS]], [[EL]] -// CHECK-64: [[ORG:%[0-9]+]] = load i128, ptr %incdec.ptr2, align 16 +// CHECK-64: [[ORG:%[0-9]+]] = load i128, ptr %incdec.ptr2, align 8 // CHECK-64: [[RES:%[0-9]+]] = cmpxchg volatile ptr %incdec.ptr, i128 [[ORG]], i128 [[EXP]] seq_cst seq_cst, align 16 // CHECK-64: [[OLD:%[0-9]+]] = extractvalue { i128, i1 } [[RES]], 0 -// CHECK-64: store i128 [[OLD]], ptr %incdec.ptr2, align 16 +// CHECK-64: store i128 [[OLD]], ptr %incdec.ptr2, align 8 // CHECK-64: [[SUC1:%[0-9]+]] = extractvalue { i128, i1 } [[RES]], 1 // CHECK-64: [[SUC8:%[0-9]+]] = zext i1 [[SUC1]] to i8 // CHECK-64: ret i8 [[SUC8]] diff --git a/clang/test/CodeGen/pgo-instrumentation.c b/clang/test/CodeGen/pgo-instrumentation.c index a65c6712291bd26c414e88d29498339f599ada6e..c01658065497e3036105f388e399e57c86904650 100644 --- a/clang/test/CodeGen/pgo-instrumentation.c +++ b/clang/test/CodeGen/pgo-instrumentation.c @@ -3,7 +3,7 @@ // Ensure Pass PGOInstrumentationGenPass is invoked. // RUN: %clang_cc1 -O2 -fprofile-instrument=llvm %s -fdebug-pass-manager -emit-llvm -o - 2>&1 | FileCheck %s -check-prefix=CHECK-PGOGENPASS-INVOKED-INSTR-GEN --check-prefix=CHECK-INSTRPROF // CHECK-PGOGENPASS-INVOKED-INSTR-GEN: Running pass: PGOInstrumentationGen on -// CHECK-INSTRPROF: Running pass: InstrProfiling on +// CHECK-INSTRPROF: Running pass: InstrProfilingLoweringPass on // // Ensure Pass PGOInstrumentationGenPass is not invoked. // RUN: %clang_cc1 -O2 -fprofile-instrument=clang %s -fdebug-pass-manager -emit-llvm -o - 2>&1 | FileCheck %s -check-prefix=CHECK-PGOGENPASS-INVOKED-INSTR-GEN-CLANG @@ -11,7 +11,7 @@ // RUN: %clang_cc1 -O2 -fprofile-instrument=clang %s -fdebug-pass-manager -emit-llvm -o - 2>&1 | FileCheck %s --check-prefix=CHECK-CLANG-INSTRPROF // RUN: %clang_cc1 -O0 -fprofile-instrument=clang %s -fdebug-pass-manager -emit-llvm -o - 2>&1 | FileCheck %s --check-prefix=CHECK-CLANG-INSTRPROF -// CHECK-CLANG-INSTRPROF: Running pass: InstrProfiling on +// CHECK-CLANG-INSTRPROF: Running pass: InstrProfilingLoweringPass on // Ensure Pass PGOInstrumentationUsePass is invoked. // RUN: llvm-profdata merge -o %t.profdata %S/Inputs/pgotestir.profraw diff --git a/clang/test/CodeGen/pragma-cx-limited-range.c b/clang/test/CodeGen/pragma-cx-limited-range.c new file mode 100644 index 0000000000000000000000000000000000000000..926da8afbee558c9428b0ed2e41605597b6e6a58 --- /dev/null +++ b/clang/test/CodeGen/pragma-cx-limited-range.c @@ -0,0 +1,107 @@ +// RUN: %clang_cc1 %s -O0 -emit-llvm -triple x86_64-unknown-unknown \ +// RUN: -o - | FileCheck %s --check-prefix=FULL + +// RUN: %clang_cc1 %s -O0 -emit-llvm -triple x86_64-unknown-unknown \ +// RUN: -complex-range=limited -o - | FileCheck --check-prefix=LMTD %s + +// RUN: %clang_cc1 %s -O0 -emit-llvm -triple x86_64-unknown-unknown \ +// RUN: -fno-cx-limited-range -o - | FileCheck %s --check-prefix=FULL + +// RUN: %clang_cc1 %s -O0 -emit-llvm -triple x86_64-unknown-unknown \ +// RUN: -complex-range=fortran -o - | FileCheck --check-prefix=FRTRN %s + +// RUN: %clang_cc1 %s -O0 -emit-llvm -triple x86_64-unknown-unknown \ +// RUN: -fno-cx-fortran-rules -o - | FileCheck --check-prefix=FULL %s + +_Complex float pragma_on_mul(_Complex float a, _Complex float b) { +#pragma STDC CX_LIMITED_RANGE ON + // LABEL: define {{.*}} @pragma_on_mul( + // FULL: fmul float + // FULL-NEXT: fmul float + // FULL-NEXT: fmul float + // FULL-NEXT: fmul float + // FULL-NEXT: fsub float + // FULL-NEXT: fadd float + + // LMTD: fmul float + // LMTD-NEXT: fmul float + // LMTD-NEXT: fmul float + // LMTD-NEXT: fmul float + // LMTD-NEXT: fsub float + // LMTD-NEXT: fadd float + + // FRTRN: fmul float + // FRTRN-NEXT: fmul float + // FRTRN-NEXT: fmul float + // FRTRN-NEXT: fmul float + // FRTRN-NEXT: fsub float + // FRTRN-NEXT: fadd float + + return a * b; +} + +_Complex float pragma_off_mul(_Complex float a, _Complex float b) { +#pragma STDC CX_LIMITED_RANGE OFF + // LABEL: define {{.*}} @pragma_off_mul( + // FULL: call {{.*}} @__mulsc3 + + // LMTD: call {{.*}} @__mulsc3 + + // FRTRN: call {{.*}} @__mulsc3 + + return a * b; +} + +_Complex float pragma_on_div(_Complex float a, _Complex float b) { +#pragma STDC CX_LIMITED_RANGE ON + // LABEL: define {{.*}} @pragma_on_div( + // FULL: fmul float + // FULL-NEXT: fmul float + // FULL-NEXT: fadd float + // FULL-NEXT: fmul float + // FULL-NEXT: fmul float + // FULL-NEXT: fadd float + // FULL-NEXT: fmul float + // FULL-NEXT: fmul float + // FULL-NEXT: fsub float + // FULL-NEXT: fdiv float + // FULL: fdiv float + + // LMTD: fmul float + // LMTD-NEXT: fmul float + // LMTD-NEXT: fadd float + // LMTD-NEXT: fmul float + // LMTD-NEXT: fmul float + // LMTD-NEXT: fadd float + // LMTD-NEXT: fmul float + // LMTD-NEXT: fmul float + // LMTD-NEXT: fsub float + // LMTD-NEXT: fdiv float + // LMTD-NEXT: fdiv float + + // FRTRN: fmul float + // FRTRN-NEXT: fmul float + // FRTRN-NEXT: fadd float + // FRTRN-NEXT: fmul float + // FRTRN-NEXT: fmul float + // FRTRN-NEXT: fadd float + // FRTRN-NEXT: fmul float + // FRTRN-NEXT: fmul float + // FRTRN-NEXT: fsub float + // FRTRN-NEXT: fdiv float + // FRTRN-NEXT: fdiv float + + return a / b; +} + +_Complex float pragma_off_div(_Complex float a, _Complex float b) { +#pragma STDC CX_LIMITED_RANGE OFF + // LABEL: define {{.*}} @pragma_off_div( + // FULL: call {{.*}} @__divsc3 + + // LMTD: call {{.*}} @__divsc3 + + // FRTRN: call {{.*}} @__divsc3 + + return a / b; +} diff --git a/clang/test/CodeGen/scoped-atomic-ops.c b/clang/test/CodeGen/scoped-atomic-ops.c new file mode 100644 index 0000000000000000000000000000000000000000..b0032046639b89eb067bef4aca671e2f9f9a3767 --- /dev/null +++ b/clang/test/CodeGen/scoped-atomic-ops.c @@ -0,0 +1,331 @@ +// RUN: %clang_cc1 %s -emit-llvm -o - -triple=amdgcn-amd-amdhsa -ffreestanding \ +// RUN: -fvisibility=hidden | FileCheck %s + +// CHECK-LABEL: define hidden i32 @fi1a( +// CHECK: [[TMP0:%.*]] = load atomic i32, ptr [[PTR0:.+]] syncscope("one-as") monotonic, align 4 +// CHECK: [[TMP1:%.*]] = load atomic i32, ptr [[PTR1:.+]] syncscope("agent-one-as") monotonic, align 4 +// CHECK: [[TMP2:%.*]] = load atomic i32, ptr [[PTR2:.+]] syncscope("workgroup-one-as") monotonic, align 4 +// CHECK: [[TMP3:%.*]] = load atomic i32, ptr [[PTR3:.+]] syncscope("wavefront-one-as") monotonic, align 4 +// CHECK: [[TMP4:%.*]] = load atomic i32, ptr [[PTR4:.+]] syncscope("singlethread-one-as") monotonic, align 4 +int fi1a(int *i) { + int v; + __scoped_atomic_load(i, &v, __ATOMIC_RELAXED, __MEMORY_SCOPE_SYSTEM); + __scoped_atomic_load(i, &v, __ATOMIC_RELAXED, __MEMORY_SCOPE_DEVICE); + __scoped_atomic_load(i, &v, __ATOMIC_RELAXED, __MEMORY_SCOPE_WRKGRP); + __scoped_atomic_load(i, &v, __ATOMIC_RELAXED, __MEMORY_SCOPE_WVFRNT); + __scoped_atomic_load(i, &v, __ATOMIC_RELAXED, __MEMORY_SCOPE_SINGLE); + return v; +} + +// CHECK-LABEL: define hidden i32 @fi1b( +// CHECK: [[TMP0:%.*]] = load atomic i32, ptr [[PTR0:%.+]] syncscope("one-as") monotonic, align 4 +// CHECK: [[TMP1:%.*]] = load atomic i32, ptr [[PTR1:%.+]] syncscope("agent-one-as") monotonic, align 4 +// CHECK: [[TMP2:%.*]] = load atomic i32, ptr [[PTR2:%.+]] syncscope("workgroup-one-as") monotonic, align 4 +// CHECK: [[TMP3:%.*]] = load atomic i32, ptr [[PTR3:%.+]] syncscope("wavefront-one-as") monotonic, align 4 +// CHECK: [[TMP4:%.*]] = load atomic i32, ptr [[PTR4:%.+]] syncscope("singlethread-one-as") monotonic, align 4 +// +int fi1b(int *i) { + *i = __scoped_atomic_load_n(i, __ATOMIC_RELAXED, __MEMORY_SCOPE_SYSTEM); + *i = __scoped_atomic_load_n(i, __ATOMIC_RELAXED, __MEMORY_SCOPE_DEVICE); + *i = __scoped_atomic_load_n(i, __ATOMIC_RELAXED, __MEMORY_SCOPE_WRKGRP); + *i = __scoped_atomic_load_n(i, __ATOMIC_RELAXED, __MEMORY_SCOPE_WVFRNT); + *i = __scoped_atomic_load_n(i, __ATOMIC_RELAXED, __MEMORY_SCOPE_SINGLE); + return *i; +} + +// CHECK-LABEL: define hidden void @fi2a( +// CHECK: store atomic i32 [[TMP0:%.+]], ptr [[PTR0:%.+]] syncscope("one-as") monotonic, align 4 +// CHECK: store atomic i32 [[TMP1:%.+]], ptr [[PTR1:%.+]] syncscope("agent-one-as") monotonic, align 4 +// CHECK: store atomic i32 [[TMP2:%.+]], ptr [[PTR2:%.+]] syncscope("workgroup-one-as") monotonic, align 4 +// CHECK: store atomic i32 [[TMP3:%.+]], ptr [[PTR3:%.+]] syncscope("wavefront-one-as") monotonic, align 4 +// CHECK: store atomic i32 [[TMP4:%.+]], ptr [[PTR4:%.+]] syncscope("singlethread-one-as") monotonic, align 4 +// +void fi2a(int *i) { + int v = 1; + __scoped_atomic_store(i, &v, __ATOMIC_RELAXED, __MEMORY_SCOPE_SYSTEM); + __scoped_atomic_store(i, &v, __ATOMIC_RELAXED, __MEMORY_SCOPE_DEVICE); + __scoped_atomic_store(i, &v, __ATOMIC_RELAXED, __MEMORY_SCOPE_WRKGRP); + __scoped_atomic_store(i, &v, __ATOMIC_RELAXED, __MEMORY_SCOPE_WVFRNT); + __scoped_atomic_store(i, &v, __ATOMIC_RELAXED, __MEMORY_SCOPE_SINGLE); +} + +// CHECK-LABEL: define hidden void @fi2b( +// CHECK: store atomic i32 [[TMP0:%.+]], ptr [[PTR0:%.+]] syncscope("one-as") monotonic, align 4 +// CHECK: store atomic i32 [[TMP1:%.+]], ptr [[PTR1:%.+]] syncscope("agent-one-as") monotonic, align 4 +// CHECK: store atomic i32 [[TMP2:%.+]], ptr [[PTR2:%.+]] syncscope("workgroup-one-as") monotonic, align 4 +// CHECK: store atomic i32 [[TMP3:%.+]], ptr [[PTR3:%.+]] syncscope("wavefront-one-as") monotonic, align 4 +// CHECK: store atomic i32 [[TMP4:%.+]], ptr [[PTR4:%.+]] syncscope("singlethread-one-as") monotonic, align 4 +void fi2b(int *i) { + __scoped_atomic_store_n(i, 1, __ATOMIC_RELAXED, __MEMORY_SCOPE_SYSTEM); + __scoped_atomic_store_n(i, 1, __ATOMIC_RELAXED, __MEMORY_SCOPE_DEVICE); + __scoped_atomic_store_n(i, 1, __ATOMIC_RELAXED, __MEMORY_SCOPE_WRKGRP); + __scoped_atomic_store_n(i, 1, __ATOMIC_RELAXED, __MEMORY_SCOPE_WVFRNT); + __scoped_atomic_store_n(i, 1, __ATOMIC_RELAXED, __MEMORY_SCOPE_SINGLE); +} + +// CHECK-LABEL: define hidden void @fi3a( +// CHECK: [[TMP0:%.*]] = atomicrmw add ptr [[PTR0:%.+]], i32 [[VAL0:.+]] syncscope("one-as") monotonic, align 4 +// CHECK: [[TMP1:%.*]] = atomicrmw sub ptr [[PTR1:%.+]], i32 [[VAL1:.+]] syncscope("one-as") monotonic, align 4 +// CHECK: [[TMP2:%.*]] = atomicrmw and ptr [[PTR2:%.+]], i32 [[VAL2:.+]] syncscope("one-as") monotonic, align 4 +// CHECK: [[TMP3:%.*]] = atomicrmw or ptr [[PTR3:%.+]], i32 [[VAL3:.+]] syncscope("one-as") monotonic, align 4 +// CHECK: [[TMP4:%.*]] = atomicrmw xor ptr [[PTR4:%.+]], i32 [[VAL4:.+]] syncscope("one-as") monotonic, align 4 +// CHECK: [[TMP5:%.*]] = atomicrmw nand ptr [[PTR5:%.+]], i32 [[VAL5:.+]] syncscope("one-as") monotonic, align 4 +// CHECK: [[TMP6:%.*]] = atomicrmw min ptr [[PTR6:%.+]], i32 [[VAL6:.+]] syncscope("one-as") monotonic, align 4 +// CHECK: [[TMP7:%.*]] = atomicrmw max ptr [[PTR7:%.+]], i32 [[VAL7:.+]] syncscope("one-as") monotonic, align 4 +void fi3a(int *a, int *b, int *c, int *d, int *e, int *f, int *g, int *h) { + *a = __scoped_atomic_fetch_add(a, 1, __ATOMIC_RELAXED, __MEMORY_SCOPE_SYSTEM); + *b = __scoped_atomic_fetch_sub(b, 1, __ATOMIC_RELAXED, __MEMORY_SCOPE_SYSTEM); + *c = __scoped_atomic_fetch_and(c, 1, __ATOMIC_RELAXED, __MEMORY_SCOPE_SYSTEM); + *d = __scoped_atomic_fetch_or(d, 1, __ATOMIC_RELAXED, __MEMORY_SCOPE_SYSTEM); + *e = __scoped_atomic_fetch_xor(e, 1, __ATOMIC_RELAXED, __MEMORY_SCOPE_SYSTEM); + *f = __scoped_atomic_fetch_nand(f, 1, __ATOMIC_RELAXED, __MEMORY_SCOPE_SYSTEM); + *g = __scoped_atomic_fetch_min(g, 1, __ATOMIC_RELAXED, __MEMORY_SCOPE_SYSTEM); + *h = __scoped_atomic_fetch_max(h, 1, __ATOMIC_RELAXED, __MEMORY_SCOPE_SYSTEM); +} + +// CHECK-LABEL: define hidden void @fi3b( +// CHECK: [[TMP0:%.*]] = atomicrmw add ptr [[PTR0:%.+]], i32 [[VAL0:.+]] syncscope("agent-one-as") monotonic, align 4 +// CHECK: [[TMP1:%.*]] = atomicrmw sub ptr [[PTR1:%.+]], i32 [[VAL1:.+]] syncscope("agent-one-as") monotonic, align 4 +// CHECK: [[TMP2:%.*]] = atomicrmw and ptr [[PTR2:%.+]], i32 [[VAL2:.+]] syncscope("agent-one-as") monotonic, align 4 +// CHECK: [[TMP3:%.*]] = atomicrmw or ptr [[PTR3:%.+]], i32 [[VAL3:.+]] syncscope("agent-one-as") monotonic, align 4 +// CHECK: [[TMP4:%.*]] = atomicrmw xor ptr [[PTR4:%.+]], i32 [[VAL4:.+]] syncscope("agent-one-as") monotonic, align 4 +// CHECK: [[TMP5:%.*]] = atomicrmw nand ptr [[PTR5:%.+]], i32 [[VAL5:.+]] syncscope("agent-one-as") monotonic, align 4 +// CHECK: [[TMP6:%.*]] = atomicrmw min ptr [[PTR6:%.+]], i32 [[VAL6:.+]] syncscope("agent-one-as") monotonic, align 4 +// CHECK: [[TMP7:%.*]] = atomicrmw max ptr [[PTR7:%.+]], i32 [[VAL7:.+]] syncscope("agent-one-as") monotonic, align 4 +void fi3b(int *a, int *b, int *c, int *d, int *e, int *f, int *g, int *h) { + *a = __scoped_atomic_fetch_add(a, 1, __ATOMIC_RELAXED, __MEMORY_SCOPE_DEVICE); + *b = __scoped_atomic_fetch_sub(b, 1, __ATOMIC_RELAXED, __MEMORY_SCOPE_DEVICE); + *c = __scoped_atomic_fetch_and(c, 1, __ATOMIC_RELAXED, __MEMORY_SCOPE_DEVICE); + *d = __scoped_atomic_fetch_or(d, 1, __ATOMIC_RELAXED, __MEMORY_SCOPE_DEVICE); + *e = __scoped_atomic_fetch_xor(e, 1, __ATOMIC_RELAXED, __MEMORY_SCOPE_DEVICE); + *f = __scoped_atomic_fetch_nand(f, 1, __ATOMIC_RELAXED, __MEMORY_SCOPE_DEVICE); + *g = __scoped_atomic_fetch_min(g, 1, __ATOMIC_RELAXED, __MEMORY_SCOPE_DEVICE); + *h = __scoped_atomic_fetch_max(h, 1, __ATOMIC_RELAXED, __MEMORY_SCOPE_DEVICE); +} + +// CHECK-LABEL: define hidden void @fi3c( +// CHECK: [[TMP0:%.*]] = atomicrmw add ptr [[PTR0:%.+]], i32 [[VAL0:.+]] syncscope("workgroup-one-as") monotonic, align 4 +// CHECK: [[TMP1:%.*]] = atomicrmw sub ptr [[PTR1:%.+]], i32 [[VAL1:.+]] syncscope("workgroup-one-as") monotonic, align 4 +// CHECK: [[TMP2:%.*]] = atomicrmw and ptr [[PTR2:%.+]], i32 [[VAL2:.+]] syncscope("workgroup-one-as") monotonic, align 4 +// CHECK: [[TMP3:%.*]] = atomicrmw or ptr [[PTR3:%.+]], i32 [[VAL3:.+]] syncscope("workgroup-one-as") monotonic, align 4 +// CHECK: [[TMP4:%.*]] = atomicrmw xor ptr [[PTR4:%.+]], i32 [[VAL4:.+]] syncscope("workgroup-one-as") monotonic, align 4 +// CHECK: [[TMP5:%.*]] = atomicrmw nand ptr [[PTR5:%.+]], i32 [[VAL5:.+]] syncscope("workgroup-one-as") monotonic, align 4 +// CHECK: [[TMP6:%.*]] = atomicrmw min ptr [[PTR6:%.+]], i32 [[VAL6:.+]] syncscope("workgroup-one-as") monotonic, align 4 +// CHECK: [[TMP7:%.*]] = atomicrmw max ptr [[PTR7:%.+]], i32 [[VAL7:.+]] syncscope("workgroup-one-as") monotonic, align 4 +void fi3c(int *a, int *b, int *c, int *d, int *e, int *f, int *g, int *h) { + *a = __scoped_atomic_fetch_add(a, 1, __ATOMIC_RELAXED, __MEMORY_SCOPE_WRKGRP); + *b = __scoped_atomic_fetch_sub(b, 1, __ATOMIC_RELAXED, __MEMORY_SCOPE_WRKGRP); + *c = __scoped_atomic_fetch_and(c, 1, __ATOMIC_RELAXED, __MEMORY_SCOPE_WRKGRP); + *d = __scoped_atomic_fetch_or(d, 1, __ATOMIC_RELAXED, __MEMORY_SCOPE_WRKGRP); + *e = __scoped_atomic_fetch_xor(e, 1, __ATOMIC_RELAXED, __MEMORY_SCOPE_WRKGRP); + *f = __scoped_atomic_fetch_nand(f, 1, __ATOMIC_RELAXED, __MEMORY_SCOPE_WRKGRP); + *g = __scoped_atomic_fetch_min(g, 1, __ATOMIC_RELAXED, __MEMORY_SCOPE_WRKGRP); + *h = __scoped_atomic_fetch_max(h, 1, __ATOMIC_RELAXED, __MEMORY_SCOPE_WRKGRP); +} + +// CHECK-LABEL: define hidden void @fi3d( +// CHECK: [[TMP0:%.*]] = atomicrmw add ptr [[PTR0:%.+]], i32 [[VAL0:.+]] syncscope("wavefront-one-as") monotonic, align 4 +// CHECK: [[TMP1:%.*]] = atomicrmw sub ptr [[PTR1:%.+]], i32 [[VAL1:.+]] syncscope("wavefront-one-as") monotonic, align 4 +// CHECK: [[TMP2:%.*]] = atomicrmw and ptr [[PTR2:%.+]], i32 [[VAL2:.+]] syncscope("wavefront-one-as") monotonic, align 4 +// CHECK: [[TMP3:%.*]] = atomicrmw or ptr [[PTR3:%.+]], i32 [[VAL3:.+]] syncscope("wavefront-one-as") monotonic, align 4 +// CHECK: [[TMP4:%.*]] = atomicrmw xor ptr [[PTR4:%.+]], i32 [[VAL4:.+]] syncscope("wavefront-one-as") monotonic, align 4 +// CHECK: [[TMP5:%.*]] = atomicrmw nand ptr [[PTR5:%.+]], i32 [[VAL5:.+]] syncscope("wavefront-one-as") monotonic, align 4 +// CHECK: [[TMP6:%.*]] = atomicrmw min ptr [[PTR6:%.+]], i32 [[VAL6:.+]] syncscope("wavefront-one-as") monotonic, align 4 +// CHECK: [[TMP7:%.*]] = atomicrmw max ptr [[PTR7:%.+]], i32 [[VAL7:.+]] syncscope("wavefront-one-as") monotonic, align 4 +void fi3d(int *a, int *b, int *c, int *d, int *e, int *f, int *g, int *h) { + *a = __scoped_atomic_fetch_add(a, 1, __ATOMIC_RELAXED, __MEMORY_SCOPE_WVFRNT); + *b = __scoped_atomic_fetch_sub(b, 1, __ATOMIC_RELAXED, __MEMORY_SCOPE_WVFRNT); + *c = __scoped_atomic_fetch_and(c, 1, __ATOMIC_RELAXED, __MEMORY_SCOPE_WVFRNT); + *d = __scoped_atomic_fetch_or(d, 1, __ATOMIC_RELAXED, __MEMORY_SCOPE_WVFRNT); + *e = __scoped_atomic_fetch_xor(e, 1, __ATOMIC_RELAXED, __MEMORY_SCOPE_WVFRNT); + *f = __scoped_atomic_fetch_nand(f, 1, __ATOMIC_RELAXED, __MEMORY_SCOPE_WVFRNT); + *g = __scoped_atomic_fetch_min(g, 1, __ATOMIC_RELAXED, __MEMORY_SCOPE_WVFRNT); + *h = __scoped_atomic_fetch_max(h, 1, __ATOMIC_RELAXED, __MEMORY_SCOPE_WVFRNT); +} + +// CHECK-LABEL: define hidden void @fi3e( +// CHECK: [[TMP0:%.*]] = atomicrmw add ptr [[PTR0:%.+]], i32 [[VAL0:.+]] syncscope("singlethread-one-as") monotonic, align 4 +// CHECK: [[TMP1:%.*]] = atomicrmw sub ptr [[PTR1:%.+]], i32 [[VAL1:.+]] syncscope("singlethread-one-as") monotonic, align 4 +// CHECK: [[TMP2:%.*]] = atomicrmw and ptr [[PTR2:%.+]], i32 [[VAL2:.+]] syncscope("singlethread-one-as") monotonic, align 4 +// CHECK: [[TMP3:%.*]] = atomicrmw or ptr [[PTR3:%.+]], i32 [[VAL3:.+]] syncscope("singlethread-one-as") monotonic, align 4 +// CHECK: [[TMP4:%.*]] = atomicrmw xor ptr [[PTR4:%.+]], i32 [[VAL4:.+]] syncscope("singlethread-one-as") monotonic, align 4 +// CHECK: [[TMP5:%.*]] = atomicrmw nand ptr [[PTR5:%.+]], i32 [[VAL5:.+]] syncscope("singlethread-one-as") monotonic, align 4 +// CHECK: [[TMP6:%.*]] = atomicrmw min ptr [[PTR6:%.+]], i32 [[VAL6:.+]] syncscope("singlethread-one-as") monotonic, align 4 +// CHECK: [[TMP7:%.*]] = atomicrmw max ptr [[PTR7:%.+]], i32 [[VAL7:.+]] syncscope("singlethread-one-as") monotonic, align 4 +void fi3e(int *a, int *b, int *c, int *d, int *e, int *f, int *g, int *h) { + *a = __scoped_atomic_fetch_add(a, 1, __ATOMIC_RELAXED, __MEMORY_SCOPE_SINGLE); + *b = __scoped_atomic_fetch_sub(b, 1, __ATOMIC_RELAXED, __MEMORY_SCOPE_SINGLE); + *c = __scoped_atomic_fetch_and(c, 1, __ATOMIC_RELAXED, __MEMORY_SCOPE_SINGLE); + *d = __scoped_atomic_fetch_or(d, 1, __ATOMIC_RELAXED, __MEMORY_SCOPE_SINGLE); + *e = __scoped_atomic_fetch_xor(e, 1, __ATOMIC_RELAXED, __MEMORY_SCOPE_SINGLE); + *f = __scoped_atomic_fetch_nand(f, 1, __ATOMIC_RELAXED, __MEMORY_SCOPE_SINGLE); + *g = __scoped_atomic_fetch_min(g, 1, __ATOMIC_RELAXED, __MEMORY_SCOPE_SINGLE); + *h = __scoped_atomic_fetch_max(h, 1, __ATOMIC_RELAXED, __MEMORY_SCOPE_SINGLE); +} + +// CHECK-LABEL: define hidden zeroext i1 @fi4a( +// CHECK: [[TMP0:%.*]] = cmpxchg ptr [[PTR0:%.+]], i32 [[VAL0:.+]], i32 [[VAL1:.+]] syncscope("one-as") acquire acquire, align 4 +_Bool fi4a(int *i) { + int cmp = 0; + int desired = 1; + return __scoped_atomic_compare_exchange(i, &cmp, &desired, 0, + __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE, + __MEMORY_SCOPE_SYSTEM); +} + +// CHECK-LABEL: define hidden zeroext i1 @fi4b( +// CHECK: [[TMP0:%.*]] = cmpxchg ptr [[PTR0:%.+]], i32 [[VAL0:.+]], i32 [[VAL1:.+]] syncscope("agent-one-as") acquire acquire, align 4 +_Bool fi4b(int *i) { + int cmp = 0; + int desired = 1; + return __scoped_atomic_compare_exchange(i, &cmp, &desired, 0, + __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE, + __MEMORY_SCOPE_DEVICE); +} + +// CHECK-LABEL: define hidden zeroext i1 @fi4c( +// CHECK: [[TMP0:%.*]] = cmpxchg ptr [[PTR0:%.+]], i32 [[VAL0:.+]], i32 [[VAL1:.+]] syncscope("workgroup-one-as") acquire acquire, align 4 +_Bool fi4c(int *i) { + int cmp = 0; + int desired = 1; + return __scoped_atomic_compare_exchange(i, &cmp, &desired, 0, + __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE, + __MEMORY_SCOPE_WRKGRP); +} + +// CHECK-LABEL: define hidden zeroext i1 @fi4d( +// CHECK: [[TMP0:%.*]] = cmpxchg ptr [[PTR0:%.+]], i32 [[VAL0:.+]], i32 [[VAL1:.+]] syncscope("wavefront-one-as") acquire acquire, align 4 +_Bool fi4d(int *i) { + int cmp = 0; + int desired = 1; + return __scoped_atomic_compare_exchange(i, &cmp, &desired, 0, + __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE, + __MEMORY_SCOPE_WVFRNT); +} + +// CHECK-LABEL: define hidden zeroext i1 @fi4e( +// CHECK: [[TMP0:%.*]] = cmpxchg ptr [[PTR0:%.+]], i32 [[VAL0:.+]], i32 [[VAL1:.+]] syncscope("singlethread-one-as") acquire acquire, align 4 +_Bool fi4e(int *i) { + int cmp = 0; + int desired = 1; + return __scoped_atomic_compare_exchange(i, &cmp, &desired, 0, + __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE, + __MEMORY_SCOPE_SINGLE); +} + +// CHECK-LABEL: define hidden zeroext i1 @fi5a( +// CHECK: [[TMP0:%.*]] = cmpxchg weak ptr [[PTR0:%.+]], i32 [[VAL0:.+]], i32 [[VAL1:.+]] syncscope("one-as") acquire acquire, align 4 +_Bool fi5a(int *i) { + int cmp = 0; + return __scoped_atomic_compare_exchange_n(i, &cmp, 1, 1, __ATOMIC_ACQUIRE, + __ATOMIC_ACQUIRE, + __MEMORY_SCOPE_SYSTEM); +} + +// CHECK-LABEL: define hidden zeroext i1 @fi5b( +// CHECK: [[TMP0:%.*]] = cmpxchg weak ptr [[PTR0:%.+]], i32 [[VAL0:.+]], i32 [[VAL1:.+]] syncscope("agent-one-as") acquire acquire, align 4 +_Bool fi5b(int *i) { + int cmp = 0; + return __scoped_atomic_compare_exchange_n(i, &cmp, 1, 1, __ATOMIC_ACQUIRE, + __ATOMIC_ACQUIRE, + __MEMORY_SCOPE_DEVICE); +} + +// CHECK-LABEL: define hidden zeroext i1 @fi5c( +// CHECK: [[TMP0:%.*]] = cmpxchg weak ptr [[PTR0:%.+]], i32 [[VAL0:.+]], i32 [[VAL1:.+]] syncscope("workgroup-one-as") acquire acquire, align 4 +_Bool fi5c(int *i) { + int cmp = 0; + return __scoped_atomic_compare_exchange_n( + i, &cmp, 1, 1, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE, __MEMORY_SCOPE_WRKGRP); +} + +// CHECK-LABEL: define hidden zeroext i1 @fi5d( +// CHECK: [[TMP0:%.*]] = cmpxchg weak ptr [[PTR0:%.+]], i32 [[VAL0:.+]], i32 [[VAL1:.+]] syncscope("wavefront-one-as") acquire acquire, align 4 +_Bool fi5d(int *i) { + int cmp = 0; + return __scoped_atomic_compare_exchange_n( + i, &cmp, 1, 1, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE, __MEMORY_SCOPE_WVFRNT); +} + +// CHECK-LABEL: define hidden zeroext i1 @fi5e( +// CHECK: [[TMP0:%.*]] = cmpxchg weak ptr [[PTR0:%.+]], i32 [[VAL0:.+]], i32 [[VAL1:.+]] syncscope("singlethread-one-as") acquire acquire, align 4 +_Bool fi5e(int *i) { + int cmp = 0; + return __scoped_atomic_compare_exchange_n( + i, &cmp, 1, 1, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE, __MEMORY_SCOPE_SINGLE); +} + +// CHECK-LABEL: define hidden i32 @fi6a( +// CHECK: [[TMP0:%.*]] = atomicrmw xchg ptr [[PTR0:%.+]], i32 [[VAL0:.+]] syncscope("one-as") monotonic, align 4 +int fi6a(int *c, int *d) { + int ret; + __scoped_atomic_exchange(c, d, &ret, __ATOMIC_RELAXED, __MEMORY_SCOPE_SYSTEM); + return ret; +} + +// CHECK-LABEL: define hidden i32 @fi6b( +// CHECK: [[TMP0:%.*]] = atomicrmw xchg ptr [[PTR0:%.+]], i32 [[VAL0:.+]] syncscope("agent-one-as") monotonic, align 4 +int fi6b(int *c, int *d) { + int ret; + __scoped_atomic_exchange(c, d, &ret, __ATOMIC_RELAXED, __MEMORY_SCOPE_DEVICE); + return ret; +} + +// CHECK-LABEL: define hidden i32 @fi6c( +// CHECK: [[TMP0:%.*]] = atomicrmw xchg ptr [[PTR0:%.+]], i32 [[VAL0:.+]] syncscope("workgroup-one-as") monotonic, align 4 +int fi6c(int *c, int *d) { + int ret; + __scoped_atomic_exchange(c, d, &ret, __ATOMIC_RELAXED, __MEMORY_SCOPE_WRKGRP); + return ret; +} + +// CHECK-LABEL: define hidden i32 @fi6d( +// CHECK: [[TMP0:%.*]] = atomicrmw xchg ptr [[PTR0:%.+]], i32 [[VAL0:.+]] syncscope("wavefront-one-as") monotonic, align 4 +int fi6d(int *c, int *d) { + int ret; + __scoped_atomic_exchange(c, d, &ret, __ATOMIC_RELAXED, __MEMORY_SCOPE_WVFRNT); + return ret; +} + +// CHECK-LABEL: define hidden i32 @fi6e( +// CHECK: [[TMP0:%.*]] = atomicrmw xchg ptr [[PTR0:%.+]], i32 [[VAL0:.+]] syncscope("singlethread-one-as") monotonic, align 4 +int fi6e(int *c, int *d) { + int ret; + __scoped_atomic_exchange(c, d, &ret, __ATOMIC_RELAXED, __MEMORY_SCOPE_SINGLE); + return ret; +} + +// CHECK-LABEL: define hidden zeroext i1 @fi7a( +// CHECK: [[TMP0:%.*]] = atomicrmw xchg ptr [[PTR0:%.+]], i8 [[VAL0:.+]] syncscope("one-as") monotonic, align 1 +_Bool fi7a(_Bool *c) { + return __scoped_atomic_exchange_n(c, 1, __ATOMIC_RELAXED, + __MEMORY_SCOPE_SYSTEM); +} + +// CHECK-LABEL: define hidden zeroext i1 @fi7b( +// CHECK: [[TMP0:%.*]] = atomicrmw xchg ptr [[PTR0:%.+]], i8 [[VAL0:.+]] syncscope("agent-one-as") monotonic, align 1 +_Bool fi7b(_Bool *c) { + return __scoped_atomic_exchange_n(c, 1, __ATOMIC_RELAXED, + __MEMORY_SCOPE_DEVICE); +} + +// CHECK-LABEL: define hidden zeroext i1 @fi7c( +// CHECK: [[TMP0:%.*]] = atomicrmw xchg ptr [[PTR0:%.+]], i8 [[VAL0:.+]] syncscope("workgroup-one-as") monotonic, align 1 +_Bool fi7c(_Bool *c) { + return __scoped_atomic_exchange_n(c, 1, __ATOMIC_RELAXED, + __MEMORY_SCOPE_WRKGRP); +} + +// CHECK-LABEL: define hidden zeroext i1 @fi7d( +// CHECK: [[TMP0:%.*]] = atomicrmw xchg ptr [[PTR0:%.+]], i8 [[VAL0:.+]] syncscope("wavefront-one-as") monotonic, align 1 +_Bool fi7d(_Bool *c) { + return __scoped_atomic_exchange_n(c, 1, __ATOMIC_RELAXED, + __MEMORY_SCOPE_WVFRNT); +} + +// CHECK-LABEL: define hidden zeroext i1 @fi7e( +// CHECK: [[TMP0:%.*]] = atomicrmw xchg ptr [[PTR0:%.+]], i8 [[VAL0:.+]] syncscope("singlethread-one-as") monotonic, align 1 +_Bool fi7e(_Bool *c) { + return __scoped_atomic_exchange_n(c, 1, __ATOMIC_RELAXED, + __MEMORY_SCOPE_SINGLE); +} diff --git a/clang/test/CodeGen/tbaa.c b/clang/test/CodeGen/tbaa.c new file mode 100644 index 0000000000000000000000000000000000000000..0ab81f60a71941c56809271ee99299aaa9124d66 --- /dev/null +++ b/clang/test/CodeGen/tbaa.c @@ -0,0 +1,116 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin -O1 -no-struct-path-tbaa -disable-llvm-passes %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin -O1 -disable-llvm-passes %s -emit-llvm -o - | FileCheck %s -check-prefixes=PATH +// RUN: %clang_cc1 -triple x86_64-apple-darwin -O0 -disable-llvm-passes %s -emit-llvm -o - | FileCheck %s -check-prefix=NO-TBAA +// RUN: %clang_cc1 -triple x86_64-apple-darwin -O1 -relaxed-aliasing -disable-llvm-passes %s -emit-llvm -o - | FileCheck %s -check-prefix=NO-TBAA +// Test TBAA metadata generated by front-end. +// +// NO-TBAA-NOT: !tbaa + +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; +typedef unsigned long long uint64_t; + +typedef enum { + RED_AUTO_32, + GREEN_AUTO_32, + BLUE_AUTO_32 +} EnumAuto32; + +typedef enum { + RED_AUTO_64, + GREEN_AUTO_64, + BLUE_AUTO_64 = 0x100000000ull +} EnumAuto64; + +typedef enum : uint16_t { + RED_16, + GREEN_16, + BLUE_16 +} Enum16; + +typedef enum : uint8_t { + RED_8, + GREEN_8, + BLUE_8 +} Enum8; + +uint32_t g0(EnumAuto32 *E, uint32_t *val) { +// CHECK-LABEL: define{{.*}} i32 @g0( +// CHECK: store i32 5, ptr %{{.*}}, align 4, !tbaa [[TAG_i32:!.*]] +// CHECK: store i32 0, ptr %{{.*}}, align 4, !tbaa [[TAG_i32]] +// CHECK: load i32, ptr %{{.*}}, align 4, !tbaa [[TAG_i32]] +// PATH-LABEL: define{{.*}} i32 @g0( +// PATH: store i32 5, ptr %{{.*}}, align 4, !tbaa [[TAG_i32:!.*]] +// PATH: store i32 0, ptr %{{.*}}, align 4, !tbaa [[TAG_i32]] +// PATH: load i32, ptr %{{.*}}, align 4, !tbaa [[TAG_i32]] + *val = 5; + *E = RED_AUTO_32; + return *val; +} + +uint64_t g1(EnumAuto64 *E, uint64_t *val) { +// CHECK-LABEL: define{{.*}} i64 @g1( +// CHECK: store i64 5, ptr %{{.*}}, align 8, !tbaa [[TAG_i64:!.*]] +// CHECK: store i64 0, ptr %{{.*}}, align 8, !tbaa [[TAG_long:!.*]] +// CHECK: load i64, ptr %{{.*}}, align 8, !tbaa [[TAG_i64]] +// PATH-LABEL: define{{.*}} i64 @g1( +// PATH: store i64 5, ptr %{{.*}}, align 8, !tbaa [[TAG_i64:!.*]] +// PATH: store i64 0, ptr %{{.*}}, align 8, !tbaa [[TAG_long:!.*]] +// PATH: load i64, ptr %{{.*}}, align 8, !tbaa [[TAG_i64]] + *val = 5; + *E = RED_AUTO_64; + return *val; +} + +uint16_t g2(Enum16 *E, uint16_t *val) { +// CHECK-LABEL: define{{.*}} i16 @g2( +// CHECK: store i16 5, ptr %{{.*}}, align 2, !tbaa [[TAG_i16:!.*]] +// CHECK: store i16 0, ptr %{{.*}}, align 2, !tbaa [[TAG_i16]] +// CHECK: load i16, ptr %{{.*}}, align 2, !tbaa [[TAG_i16]] +// PATH-LABEL: define{{.*}} i16 @g2( +// PATH: store i16 5, ptr %{{.*}}, align 2, !tbaa [[TAG_i16:!.*]] +// PATH: store i16 0, ptr %{{.*}}, align 2, !tbaa [[TAG_i16]] +// PATH: load i16, ptr %{{.*}}, align 2, !tbaa [[TAG_i16]] + *val = 5; + *E = RED_16; + return *val; +} + +uint8_t g3(Enum8 *E, uint8_t *val) { +// CHECK-LABEL: define{{.*}} i8 @g3( +// CHECK: store i8 5, ptr %{{.*}}, align 1, !tbaa [[TAG_i8:!.*]] +// CHECK: store i8 0, ptr %{{.*}}, align 1, !tbaa [[TAG_i8]] +// CHECK: load i8, ptr %{{.*}}, align 1, !tbaa [[TAG_i8]] +// PATH-LABEL: define{{.*}} i8 @g3( +// PATH: store i8 5, ptr %{{.*}}, align 1, !tbaa [[TAG_i8:!.*]] +// PATH: store i8 0, ptr %{{.*}}, align 1, !tbaa [[TAG_i8]] +// PATH: load i8, ptr %{{.*}}, align 1, !tbaa [[TAG_i8]] + *val = 5; + *E = RED_8; + return *val; +} + +// CHECK: [[TYPE_char:!.*]] = !{!"omnipotent char", [[TAG_c_tbaa:!.*]], +// CHECK: [[TAG_c_tbaa]] = !{!"Simple C/C++ TBAA"} +// CHECK: [[TAG_i32]] = !{[[TYPE_i32:!.*]], [[TYPE_i32]], i64 0} +// CHECK: [[TYPE_i32]] = !{!"int", [[TYPE_char]], +// CHECK: [[TAG_i64]] = !{[[TYPE_i64:!.*]], [[TYPE_i64]], i64 0} +// CHECK: [[TYPE_i64]] = !{!"long long", [[TYPE_char]], +// CHECK: [[TAG_long]] = !{[[TYPE_long:!.*]], [[TYPE_long]], i64 0} +// CHECK: [[TYPE_long]] = !{!"long", [[TYPE_char]], +// CHECK: [[TAG_i16]] = !{[[TYPE_i16:!.*]], [[TYPE_i16]], i64 0} +// CHECK: [[TYPE_i16]] = !{!"short", [[TYPE_char]], +// CHECK: [[TAG_i8]] = !{[[TYPE_i8:!.*]], [[TYPE_char]], i64 0} + +// PATH: [[TYPE_char:!.*]] = !{!"omnipotent char", [[TAG_c_tbaa:!.*]], +// PATH: [[TAG_c_tbaa]] = !{!"Simple C/C++ TBAA"} +// PATH: [[TAG_i32]] = !{[[TYPE_i32:!.*]], [[TYPE_i32]], i64 0} +// PATH: [[TYPE_i32]] = !{!"int", [[TYPE_char]], +// PATH: [[TAG_i64]] = !{[[TYPE_i64:!.*]], [[TYPE_i64]], i64 0} +// PATH: [[TYPE_i64]] = !{!"long long", [[TYPE_char]], +// PATH: [[TAG_long]] = !{[[TYPE_long:!.*]], [[TYPE_long]], i64 0} +// PATH: [[TYPE_long]] = !{!"long", [[TYPE_char]], +// PATH: [[TAG_i16]] = !{[[TYPE_i16:!.*]], [[TYPE_i16]], i64 0} +// PATH: [[TYPE_i16]] = !{!"short", [[TYPE_char]], +// PATH: [[TAG_i8]] = !{[[TYPE_i8:!.*]], [[TYPE_char]], i64 0} diff --git a/clang/test/CodeGenCUDA/offloading-entries.cu b/clang/test/CodeGenCUDA/offloading-entries.cu index 46235051f1e4f12cda5812150400c08d69bd23b0..4f5cf65ecd0bde66e36b46ed351ca29548668c12 100644 --- a/clang/test/CodeGenCUDA/offloading-entries.cu +++ b/clang/test/CodeGenCUDA/offloading-entries.cu @@ -17,31 +17,47 @@ //. // CUDA: @.omp_offloading.entry_name = internal unnamed_addr constant [8 x i8] c"_Z3foov\00" // CUDA: @.omp_offloading.entry._Z3foov = weak constant %struct.__tgt_offload_entry { ptr @_Z18__device_stub__foov, ptr @.omp_offloading.entry_name, i64 0, i32 0, i32 0 }, section "cuda_offloading_entries", align 1 -// CUDA: @.omp_offloading.entry_name.1 = internal unnamed_addr constant [8 x i8] c"_Z3barv\00" -// CUDA: @.omp_offloading.entry._Z3barv = weak constant %struct.__tgt_offload_entry { ptr @_Z18__device_stub__barv, ptr @.omp_offloading.entry_name.1, i64 0, i32 0, i32 0 }, section "cuda_offloading_entries", align 1 -// CUDA: @.omp_offloading.entry_name.2 = internal unnamed_addr constant [2 x i8] c"x\00" -// CUDA: @.omp_offloading.entry.x = weak constant %struct.__tgt_offload_entry { ptr @x, ptr @.omp_offloading.entry_name.2, i64 4, i32 0, i32 0 }, section "cuda_offloading_entries", align 1 +// CUDA: @.omp_offloading.entry_name.1 = internal unnamed_addr constant [11 x i8] c"_Z6kernelv\00" +// CUDA: @.omp_offloading.entry._Z6kernelv = weak constant %struct.__tgt_offload_entry { ptr @_Z21__device_stub__kernelv, ptr @.omp_offloading.entry_name.1, i64 0, i32 0, i32 0 }, section "cuda_offloading_entries", align 1 +// CUDA: @.omp_offloading.entry_name.2 = internal unnamed_addr constant [4 x i8] c"var\00" +// CUDA: @.omp_offloading.entry.var = weak constant %struct.__tgt_offload_entry { ptr @var, ptr @.omp_offloading.entry_name.2, i64 4, i32 0, i32 0 }, section "cuda_offloading_entries", align 1 +// CUDA: @.omp_offloading.entry_name.3 = internal unnamed_addr constant [5 x i8] c"surf\00" +// CUDA: @.omp_offloading.entry.surf = weak constant %struct.__tgt_offload_entry { ptr @surf, ptr @.omp_offloading.entry_name.3, i64 4, i32 2, i32 1 }, section "cuda_offloading_entries", align 1 +// CUDA: @.omp_offloading.entry_name.4 = internal unnamed_addr constant [4 x i8] c"tex\00" +// CUDA: @.omp_offloading.entry.tex = weak constant %struct.__tgt_offload_entry { ptr @tex, ptr @.omp_offloading.entry_name.4, i64 4, i32 3, i32 1 }, section "cuda_offloading_entries", align 1 //. // HIP: @.omp_offloading.entry_name = internal unnamed_addr constant [8 x i8] c"_Z3foov\00" // HIP: @.omp_offloading.entry._Z3foov = weak constant %struct.__tgt_offload_entry { ptr @_Z3foov, ptr @.omp_offloading.entry_name, i64 0, i32 0, i32 0 }, section "hip_offloading_entries", align 1 -// HIP: @.omp_offloading.entry_name.1 = internal unnamed_addr constant [8 x i8] c"_Z3barv\00" -// HIP: @.omp_offloading.entry._Z3barv = weak constant %struct.__tgt_offload_entry { ptr @_Z3barv, ptr @.omp_offloading.entry_name.1, i64 0, i32 0, i32 0 }, section "hip_offloading_entries", align 1 -// HIP: @.omp_offloading.entry_name.2 = internal unnamed_addr constant [2 x i8] c"x\00" -// HIP: @.omp_offloading.entry.x = weak constant %struct.__tgt_offload_entry { ptr @x, ptr @.omp_offloading.entry_name.2, i64 4, i32 0, i32 0 }, section "hip_offloading_entries", align 1 +// HIP: @.omp_offloading.entry_name.1 = internal unnamed_addr constant [11 x i8] c"_Z6kernelv\00" +// HIP: @.omp_offloading.entry._Z6kernelv = weak constant %struct.__tgt_offload_entry { ptr @_Z6kernelv, ptr @.omp_offloading.entry_name.1, i64 0, i32 0, i32 0 }, section "hip_offloading_entries", align 1 +// HIP: @.omp_offloading.entry_name.2 = internal unnamed_addr constant [4 x i8] c"var\00" +// HIP: @.omp_offloading.entry.var = weak constant %struct.__tgt_offload_entry { ptr @var, ptr @.omp_offloading.entry_name.2, i64 4, i32 0, i32 0 }, section "hip_offloading_entries", align 1 +// HIP: @.omp_offloading.entry_name.3 = internal unnamed_addr constant [5 x i8] c"surf\00" +// HIP: @.omp_offloading.entry.surf = weak constant %struct.__tgt_offload_entry { ptr @surf, ptr @.omp_offloading.entry_name.3, i64 4, i32 2, i32 1 }, section "hip_offloading_entries", align 1 +// HIP: @.omp_offloading.entry_name.4 = internal unnamed_addr constant [4 x i8] c"tex\00" +// HIP: @.omp_offloading.entry.tex = weak constant %struct.__tgt_offload_entry { ptr @tex, ptr @.omp_offloading.entry_name.4, i64 4, i32 3, i32 1 }, section "hip_offloading_entries", align 1 //. // CUDA-COFF: @.omp_offloading.entry_name = internal unnamed_addr constant [8 x i8] c"_Z3foov\00" // CUDA-COFF: @.omp_offloading.entry._Z3foov = weak constant %struct.__tgt_offload_entry { ptr @_Z18__device_stub__foov, ptr @.omp_offloading.entry_name, i64 0, i32 0, i32 0 }, section "cuda_offloading_entries$OE", align 1 -// CUDA-COFF: @.omp_offloading.entry_name.1 = internal unnamed_addr constant [8 x i8] c"_Z3barv\00" -// CUDA-COFF: @.omp_offloading.entry._Z3barv = weak constant %struct.__tgt_offload_entry { ptr @_Z18__device_stub__barv, ptr @.omp_offloading.entry_name.1, i64 0, i32 0, i32 0 }, section "cuda_offloading_entries$OE", align 1 -// CUDA-COFF: @.omp_offloading.entry_name.2 = internal unnamed_addr constant [2 x i8] c"x\00" -// CUDA-COFF: @.omp_offloading.entry.x = weak constant %struct.__tgt_offload_entry { ptr @x, ptr @.omp_offloading.entry_name.2, i64 4, i32 0, i32 0 }, section "cuda_offloading_entries$OE", align 1 +// CUDA-COFF: @.omp_offloading.entry_name.1 = internal unnamed_addr constant [11 x i8] c"_Z6kernelv\00" +// CUDA-COFF: @.omp_offloading.entry._Z6kernelv = weak constant %struct.__tgt_offload_entry { ptr @_Z21__device_stub__kernelv, ptr @.omp_offloading.entry_name.1, i64 0, i32 0, i32 0 }, section "cuda_offloading_entries$OE", align 1 +// CUDA-COFF: @.omp_offloading.entry_name.2 = internal unnamed_addr constant [4 x i8] c"var\00" +// CUDA-COFF: @.omp_offloading.entry.var = weak constant %struct.__tgt_offload_entry { ptr @var, ptr @.omp_offloading.entry_name.2, i64 4, i32 0, i32 0 }, section "cuda_offloading_entries$OE", align 1 +// CUDA-COFF: @.omp_offloading.entry_name.3 = internal unnamed_addr constant [5 x i8] c"surf\00" +// CUDA-COFF: @.omp_offloading.entry.surf = weak constant %struct.__tgt_offload_entry { ptr @surf, ptr @.omp_offloading.entry_name.3, i64 4, i32 2, i32 1 }, section "cuda_offloading_entries$OE", align 1 +// CUDA-COFF: @.omp_offloading.entry_name.4 = internal unnamed_addr constant [4 x i8] c"tex\00" +// CUDA-COFF: @.omp_offloading.entry.tex = weak constant %struct.__tgt_offload_entry { ptr @tex, ptr @.omp_offloading.entry_name.4, i64 4, i32 3, i32 1 }, section "cuda_offloading_entries$OE", align 1 //. // HIP-COFF: @.omp_offloading.entry_name = internal unnamed_addr constant [8 x i8] c"_Z3foov\00" // HIP-COFF: @.omp_offloading.entry._Z3foov = weak constant %struct.__tgt_offload_entry { ptr @_Z3foov, ptr @.omp_offloading.entry_name, i64 0, i32 0, i32 0 }, section "hip_offloading_entries$OE", align 1 -// HIP-COFF: @.omp_offloading.entry_name.1 = internal unnamed_addr constant [8 x i8] c"_Z3barv\00" -// HIP-COFF: @.omp_offloading.entry._Z3barv = weak constant %struct.__tgt_offload_entry { ptr @_Z3barv, ptr @.omp_offloading.entry_name.1, i64 0, i32 0, i32 0 }, section "hip_offloading_entries$OE", align 1 -// HIP-COFF: @.omp_offloading.entry_name.2 = internal unnamed_addr constant [2 x i8] c"x\00" -// HIP-COFF: @.omp_offloading.entry.x = weak constant %struct.__tgt_offload_entry { ptr @x, ptr @.omp_offloading.entry_name.2, i64 4, i32 0, i32 0 }, section "hip_offloading_entries$OE", align 1 +// HIP-COFF: @.omp_offloading.entry_name.1 = internal unnamed_addr constant [11 x i8] c"_Z6kernelv\00" +// HIP-COFF: @.omp_offloading.entry._Z6kernelv = weak constant %struct.__tgt_offload_entry { ptr @_Z6kernelv, ptr @.omp_offloading.entry_name.1, i64 0, i32 0, i32 0 }, section "hip_offloading_entries$OE", align 1 +// HIP-COFF: @.omp_offloading.entry_name.2 = internal unnamed_addr constant [4 x i8] c"var\00" +// HIP-COFF: @.omp_offloading.entry.var = weak constant %struct.__tgt_offload_entry { ptr @var, ptr @.omp_offloading.entry_name.2, i64 4, i32 0, i32 0 }, section "hip_offloading_entries$OE", align 1 +// HIP-COFF: @.omp_offloading.entry_name.3 = internal unnamed_addr constant [5 x i8] c"surf\00" +// HIP-COFF: @.omp_offloading.entry.surf = weak constant %struct.__tgt_offload_entry { ptr @surf, ptr @.omp_offloading.entry_name.3, i64 4, i32 2, i32 1 }, section "hip_offloading_entries$OE", align 1 +// HIP-COFF: @.omp_offloading.entry_name.4 = internal unnamed_addr constant [4 x i8] c"tex\00" +// HIP-COFF: @.omp_offloading.entry.tex = weak constant %struct.__tgt_offload_entry { ptr @tex, ptr @.omp_offloading.entry_name.4, i64 4, i32 3, i32 1 }, section "hip_offloading_entries$OE", align 1 //. // CUDA-LABEL: @_Z18__device_stub__foov( // CUDA-NEXT: entry: @@ -72,34 +88,52 @@ // HIP-COFF-NEXT: ret void // __global__ void foo() {} +__device__ int var = 1; +const __device__ int constant = 1; +extern __device__ int external; -// CUDA-LABEL: @_Z18__device_stub__barv( +// CUDA-LABEL: @_Z21__device_stub__kernelv( // CUDA-NEXT: entry: -// CUDA-NEXT: [[TMP0:%.*]] = call i32 @cudaLaunch(ptr @_Z18__device_stub__barv) +// CUDA-NEXT: [[TMP0:%.*]] = call i32 @cudaLaunch(ptr @_Z21__device_stub__kernelv) // CUDA-NEXT: br label [[SETUP_END:%.*]] // CUDA: setup.end: // CUDA-NEXT: ret void // -// HIP-LABEL: @_Z18__device_stub__barv( +// HIP-LABEL: @_Z21__device_stub__kernelv( // HIP-NEXT: entry: -// HIP-NEXT: [[TMP0:%.*]] = call i32 @hipLaunchByPtr(ptr @_Z3barv) +// HIP-NEXT: [[TMP0:%.*]] = call i32 @hipLaunchByPtr(ptr @_Z6kernelv) // HIP-NEXT: br label [[SETUP_END:%.*]] // HIP: setup.end: // HIP-NEXT: ret void // -// CUDA-COFF-LABEL: @_Z18__device_stub__barv( +// CUDA-COFF-LABEL: @_Z21__device_stub__kernelv( // CUDA-COFF-NEXT: entry: -// CUDA-COFF-NEXT: [[TMP0:%.*]] = call i32 @cudaLaunch(ptr @_Z18__device_stub__barv) +// CUDA-COFF-NEXT: [[TMP0:%.*]] = call i32 @cudaLaunch(ptr @_Z21__device_stub__kernelv) // CUDA-COFF-NEXT: br label [[SETUP_END:%.*]] // CUDA-COFF: setup.end: // CUDA-COFF-NEXT: ret void // -// HIP-COFF-LABEL: @_Z18__device_stub__barv( +// HIP-COFF-LABEL: @_Z21__device_stub__kernelv( // HIP-COFF-NEXT: entry: -// HIP-COFF-NEXT: [[TMP0:%.*]] = call i32 @hipLaunchByPtr(ptr @_Z3barv) +// HIP-COFF-NEXT: [[TMP0:%.*]] = call i32 @hipLaunchByPtr(ptr @_Z6kernelv) // HIP-COFF-NEXT: br label [[SETUP_END:%.*]] // HIP-COFF: setup.end: // HIP-COFF-NEXT: ret void // -__global__ void bar() {} -__device__ int x = 1; +__global__ void kernel() { external = 1; } + +struct surfaceReference { int desc; }; + +template +struct __attribute__((device_builtin_surface_type)) surface : public surfaceReference {}; + +surface surf; + +struct textureReference { + int desc; +}; + +template +struct __attribute__((device_builtin_texture_type)) texture : public textureReference {}; + +texture tex; diff --git a/clang/test/CodeGenCXX/RelativeVTablesABI/member-function-pointer.cpp b/clang/test/CodeGenCXX/RelativeVTablesABI/member-function-pointer.cpp index 24f884a8d23befb1dd1f2415ac1b08bc21e47407..000568b3b6bf09c972672cc5ab202d6ba4446803 100644 --- a/clang/test/CodeGenCXX/RelativeVTablesABI/member-function-pointer.cpp +++ b/clang/test/CodeGenCXX/RelativeVTablesABI/member-function-pointer.cpp @@ -14,7 +14,7 @@ // The loading of the virtual function here should be replaced with a llvm.load.relative() call. // CHECK-NEXT: [[vtable:%.+]] = load ptr, ptr [[this_adj]], align 8 -// CHECK-NEXT: [[offset:%.+]] = add i64 [[fn_ptr]], -1 +// CHECK-NEXT: [[offset:%.+]] = add nsw i64 [[fn_ptr]], -1 // CHECK-NEXT: [[ptr:%.+]] = tail call ptr @llvm.load.relative.i64(ptr [[vtable]], i64 [[offset]]) // CHECK-NEXT: br label %[[memptr_end:.+]] // CHECK: [[nonvirt]]: diff --git a/clang/test/CodeGenCXX/attr-target-clones.cpp b/clang/test/CodeGenCXX/attr-target-clones.cpp index 86293b98dbbd35fc7363fe194a9eb9ca29d67a46..fd2d38062a71e511b19ec6a46fe92673ea78ff6d 100644 --- a/clang/test/CodeGenCXX/attr-target-clones.cpp +++ b/clang/test/CodeGenCXX/attr-target-clones.cpp @@ -1,13 +1,20 @@ // RUN: %clang_cc1 -std=c++11 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix=LINUX // RUN: %clang_cc1 -std=c++11 -triple x86_64-windows-pc -emit-llvm %s -o - | FileCheck %s --check-prefix=WINDOWS +// Aliases for ifuncs +// LINUX: @_Z10overloadedi.ifunc = weak_odr alias i32 (i32), ptr @_Z10overloadedi +// LINUX: @_Z10overloadedPKc.ifunc = weak_odr alias i32 (ptr), ptr @_Z10overloadedPKc +// LINUX: @_ZN1CIssE3fooEv.ifunc = weak_odr alias i32 (ptr), ptr @_ZN1CIssE3fooEv +// LINUX: @_ZN1CIisE3fooEv.ifunc = weak_odr alias i32 (ptr), ptr @_ZN1CIisE3fooEv +// LINUX: @_ZN1CIdfE3fooEv.ifunc = weak_odr alias i32 (ptr), ptr @_ZN1CIdfE3fooEv + // Overloaded ifuncs -// LINUX: @_Z10overloadedi.ifunc = weak_odr ifunc i32 (i32), ptr @_Z10overloadedi.resolver -// LINUX: @_Z10overloadedPKc.ifunc = weak_odr ifunc i32 (ptr), ptr @_Z10overloadedPKc.resolver +// LINUX: @_Z10overloadedi = weak_odr ifunc i32 (i32), ptr @_Z10overloadedi.resolver +// LINUX: @_Z10overloadedPKc = weak_odr ifunc i32 (ptr), ptr @_Z10overloadedPKc.resolver // struct 'C' ifuncs, note the 'float, U' one doesn't get one. -// LINUX: @_ZN1CIssE3fooEv.ifunc = weak_odr ifunc i32 (ptr), ptr @_ZN1CIssE3fooEv.resolver -// LINUX: @_ZN1CIisE3fooEv.ifunc = weak_odr ifunc i32 (ptr), ptr @_ZN1CIisE3fooEv.resolver -// LINUX: @_ZN1CIdfE3fooEv.ifunc = weak_odr ifunc i32 (ptr), ptr @_ZN1CIdfE3fooEv.resolver +// LINUX: @_ZN1CIssE3fooEv = weak_odr ifunc i32 (ptr), ptr @_ZN1CIssE3fooEv.resolver +// LINUX: @_ZN1CIisE3fooEv = weak_odr ifunc i32 (ptr), ptr @_ZN1CIisE3fooEv.resolver +// LINUX: @_ZN1CIdfE3fooEv = weak_odr ifunc i32 (ptr), ptr @_ZN1CIdfE3fooEv.resolver int __attribute__((target_clones("sse4.2", "default"))) overloaded(int) { return 1; } // LINUX: define {{.*}}i32 @_Z10overloadedi.sse4.2.0(i32{{.+}}) @@ -37,10 +44,10 @@ int __attribute__((target_clones("arch=ivybridge", "default"))) overloaded(const void use_overloaded() { overloaded(1); - // LINUX: call noundef i32 @_Z10overloadedi.ifunc + // LINUX: call noundef i32 @_Z10overloadedi // WINDOWS: call noundef i32 @"?overloaded@@YAHH@Z" overloaded(nullptr); - // LINUX: call noundef i32 @_Z10overloadedPKc.ifunc + // LINUX: call noundef i32 @_Z10overloadedPKc // WINDOWS: call noundef i32 @"?overloaded@@YAHPEBD@Z" } @@ -64,11 +71,11 @@ int __attribute__((target_clones("sse4.2", "default"))) foo(){ return 3;} void uses_specialized() { C c; c.foo(); - // LINUX: call noundef i32 @_ZN1CIssE3fooEv.ifunc(ptr + // LINUX: call noundef i32 @_ZN1CIssE3fooEv(ptr // WINDOWS: call noundef i32 @"?foo@?$C@FF@@QEAAHXZ"(ptr C c2; c2.foo(); - // LINUX: call noundef i32 @_ZN1CIisE3fooEv.ifunc(ptr + // LINUX: call noundef i32 @_ZN1CIisE3fooEv(ptr // WINDOWS: call noundef i32 @"?foo@?$C@HF@@QEAAHXZ"(ptr C c3; c3.foo(); @@ -77,7 +84,7 @@ void uses_specialized() { // WINDOWS: call noundef i32 @"?foo@?$C@MF@@QEAAHXZ"(ptr C c4; c4.foo(); - // LINUX: call noundef i32 @_ZN1CIdfE3fooEv.ifunc(ptr + // LINUX: call noundef i32 @_ZN1CIdfE3fooEv(ptr // WINDOWS: call noundef i32 @"?foo@?$C@NM@@QEAAHXZ"(ptr } diff --git a/clang/test/CodeGenCXX/debug-info-class.cpp b/clang/test/CodeGenCXX/debug-info-class.cpp index a3111cd7c3640a09678f8c89ff1305be8532340b..8d610ca68a9d4b79479ca8f882aa7356caeb9601 100644 --- a/clang/test/CodeGenCXX/debug-info-class.cpp +++ b/clang/test/CodeGenCXX/debug-info-class.cpp @@ -117,18 +117,11 @@ int main(int argc, char **argv) { // CHECK-NOT: identifier: // CHECK-SAME: ){{$}} -// CHECK: !DIGlobalVariableExpression(var: ![[HDR_VAR:[0-9]+]], expr: !DIExpression(DW_OP_constu, 52, DW_OP_stack_value)) -// CHECK: ![[HDR_VAR]] = distinct !DIGlobalVariable(name: "HdrSize", -// CHECK-SAME: isLocal: true, isDefinition: true, declaration: ![[HDR_VAR_DECL:[0-9]+]]) -// CHECK: ![[INT:[0-9]+]] = !DIBasicType(name: "int" -// CHECK: ![[HDR_VAR_DECL]] = !DIDerivedType(tag: DW_TAG_member, name: "HdrSize" - -// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "A" - // CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "I" // CHECK-NOT: DIFlagFwdDecl // CHECK-SAME: ){{$}} +// CHECK: ![[INT:[0-9]+]] = !DIBasicType(name: "int" // CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "foo" // CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "bar" // CHECK: !DICompositeType(tag: DW_TAG_union_type, name: "baz" @@ -194,5 +187,8 @@ int main(int argc, char **argv) { // CHECK: [[G_INNER_I]] = !DIDerivedType(tag: DW_TAG_member, name: "j" // CHECK-SAME: baseType: ![[INT]] +// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "A" +// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "HdrSize" + // CHECK: ![[EXCEPTLOC]] = !DILocation(line: 100, // CHECK: ![[RETLOC]] = !DILocation(line: 99, diff --git a/clang/test/CodeGenCXX/debug-info-static-inline-member.cpp b/clang/test/CodeGenCXX/debug-info-static-inline-member.cpp deleted file mode 100644 index 3230b0e0c9c60f13cf8426e642a00773a01ef04e..0000000000000000000000000000000000000000 --- a/clang/test/CodeGenCXX/debug-info-static-inline-member.cpp +++ /dev/null @@ -1,104 +0,0 @@ -// RUN: %clangxx -target arm64-apple-macosx11.0.0 -g -gdwarf-4 -debug-info-kind=standalone %s -emit-llvm -S -o - | FileCheck --check-prefixes=CHECK %s -// RUN: %clangxx -target arm64-apple-macosx11.0.0 -g -gdwarf-4 -debug-info-kind=limited %s -emit-llvm -S -o - | FileCheck --check-prefixes=CHECK %s - -enum class Enum : int { - VAL = -1 -}; - -struct Empty {}; -struct Fwd; - -constexpr auto func() { return 25; } - -struct Foo { - static constexpr int cexpr_int_with_addr = func(); - static constexpr int cexpr_int2 = func() + 1; - static constexpr float cexpr_float = 2.0 + 1.0; - static constexpr Enum cexpr_enum = Enum::VAL; - static constexpr Empty cexpr_struct_with_addr{}; - - template - static constexpr auto cexpr_template = V; - - static const auto empty_templated = cexpr_template; -}; - -int main() { - Foo f; - //Bar b; - - // Force global variable definitions to be emitted. - (void)&Foo::cexpr_int_with_addr; - (void)&Foo::cexpr_struct_with_addr; - - return Foo::cexpr_int_with_addr + Foo::cexpr_float - + (int)Foo::cexpr_enum + Foo::cexpr_template - + Foo::empty_templated; -} - -// CHECK: @{{.*}}cexpr_int_with_addr{{.*}} = -// CHECK-SAME: !dbg ![[INT_GLOBAL:[0-9]+]] - -// CHECK: @{{.*}}cexpr_struct_with_addr{{.*}} = -// CHECK-SAME !dbg ![[EMPTY_GLOBAL:[0-9]+]] - -// CHECK: !DIGlobalVariableExpression(var: ![[INT_VAR:[0-9]+]], expr: !DIExpression()) -// CHECK: ![[INT_VAR]] = distinct !DIGlobalVariable(name: "cexpr_int_with_addr", linkageName: -// CHECK-SAME: isLocal: false, isDefinition: true, declaration: ![[INT_DECL:[0-9]+]]) - -// CHECK: ![[INT_DECL]] = !DIDerivedType(tag: DW_TAG_member, name: "cexpr_int_with_addr", -// CHECK-SAME: flags: DIFlagStaticMember -// CHECK-SAME: extraData: i32 25 - -// CHECK: ![[INT_DECL2:[0-9]+]] = !DIDerivedType(tag: DW_TAG_member, name: "cexpr_int2", -// CHECK-SAME: flags: DIFlagStaticMember -// CHECK-SAME: extraData: i32 26 - -// CHECK: ![[FLOAT_DECL:[0-9]+]] = !DIDerivedType(tag: DW_TAG_member, name: "cexpr_float", -// CHECK-SAME: flags: DIFlagStaticMember -// CHECK-SAME: extraData: float - -// CHECK: ![[ENUM_DECL:[0-9]+]] = !DIDerivedType(tag: DW_TAG_member, name: "cexpr_enum", -// CHECK-SAME: flags: DIFlagStaticMember -// CHECK-SAME: extraData: i32 -1 - -// CHECK: ![[EMPTY_DECL:[0-9]+]] = !DIDerivedType(tag: DW_TAG_member, name: "cexpr_struct_with_addr", -// CHECK-SAME: flags: DIFlagStaticMember -// CHECK-NOT: extraData: - -// CHECK: ![[EMPTY_TEMPLATED_DECL:[0-9]+]] = !DIDerivedType(tag: DW_TAG_member, name: "empty_templated", -// CHECK-SAME: flags: DIFlagStaticMember -// CHECK-SAME: extraData: i32 1 - -// CHECK: ![[TEMPLATE_DECL:[0-9]+]] = !DIDerivedType(tag: DW_TAG_member, name: "cexpr_template", -// CHECK-SAME: flags: DIFlagStaticMember -// CHECK-SAME: extraData: i32 1 - -// CHECK: !DIGlobalVariableExpression(var: ![[EMPTY_VAR:[0-9]+]], expr: !DIExpression()) -// CHECK: ![[EMPTY_VAR]] = distinct !DIGlobalVariable(name: "cexpr_struct_with_addr", linkageName: -// CHECK-SAME: isLocal: false, isDefinition: true, declaration: ![[EMPTY_DECL]]) - -// CHECK: !DIGlobalVariableExpression(var: ![[INT_VAR2:[0-9]+]], expr: !DIExpression(DW_OP_constu, 26, DW_OP_stack_value)) -// CHECK: ![[INT_VAR2]] = distinct !DIGlobalVariable(name: "cexpr_int2" -// CHECK-NOT: linkageName: -// CHECK-SAME: isLocal: true, isDefinition: true, declaration: ![[INT_DECL2]]) - -// CHECK: !DIGlobalVariableExpression(var: ![[FLOAT_VAR:[0-9]+]], expr: !DIExpression(DW_OP_constu, {{.*}}, DW_OP_stack_value)) -// CHECK: ![[FLOAT_VAR]] = distinct !DIGlobalVariable(name: "cexpr_float" -// CHECK-NOT: linkageName: -// CHECK-SAME: isLocal: true, isDefinition: true, declaration: ![[FLOAT_DECL]]) - -// CHECK: !DIGlobalVariableExpression(var: ![[ENUM_VAR:[0-9]+]], expr: !DIExpression(DW_OP_constu, {{.*}}, DW_OP_stack_value)) -// CHECK: ![[ENUM_VAR]] = distinct !DIGlobalVariable(name: "cexpr_enum" -// CHECK-NOT: linkageName: -// CHECK-SAME: isLocal: true, isDefinition: true, declaration: ![[ENUM_DECL]]) - -// CHECK: !DIGlobalVariableExpression(var: ![[EMPTY_TEMPLATED_VAR:[0-9]+]], expr: !DIExpression(DW_OP_constu, 1, DW_OP_stack_value)) -// CHECK: ![[EMPTY_TEMPLATED_VAR]] = distinct !DIGlobalVariable(name: "empty_templated" -// CHECK-NOT: linkageName: -// CHECK-SAME: isLocal: true, isDefinition: true, declaration: ![[EMPTY_TEMPLATED_DECL]]) - -// CHECK: !DIGlobalVariableExpression(var: ![[TEMPLATE_VAR:[0-9]+]], expr: !DIExpression(DW_OP_constu, 5, DW_OP_stack_value)) -// CHECK: ![[TEMPLATE_VAR]] = distinct !DIGlobalVariable(name: "cexpr_template" -// CHECK-NOT: linkageName: -// CHECK-SAME: isLocal: true, isDefinition: true, declaration: ![[TEMPLATE_DECL]], templateParams: ![[TEMPLATE_PARMS_2:[0-9]+]]) diff --git a/clang/test/CodeGenCXX/debug-info-static-member.cpp b/clang/test/CodeGenCXX/debug-info-static-member.cpp index a111dc84b6e665a2dc3a73de7f3eb6daa1544ae2..972ca62d7b26757ebce022e214cfb07f65b55a14 100644 --- a/clang/test/CodeGenCXX/debug-info-static-member.cpp +++ b/clang/test/CodeGenCXX/debug-info-static-member.cpp @@ -1,8 +1,8 @@ -// RUN: %clangxx -target x86_64-unknown-unknown -g -gdwarf-4 %s -emit-llvm -S -o - | FileCheck --check-prefixes=CHECK,DWARF4,CPP11,NOT-MS %s +// RUN: %clangxx -target x86_64-unknown-unknown -g -gdwarf-4 %s -emit-llvm -S -o - | FileCheck --check-prefixes=CHECK,DWARF4,NOT-MS %s // RUN: %clangxx -target x86_64-unknown-unknown -g -gdwarf-4 -std=c++98 %s -emit-llvm -S -o - | FileCheck --check-prefixes=CHECK,DWARF4,NOT-MS %s -// RUN: %clangxx -target x86_64-unknown-unknown -g -gdwarf-4 -std=c++11 %s -emit-llvm -S -o - | FileCheck --check-prefixes=CHECK,DWARF4,CPP11,NOT-MS %s -// RUN: %clangxx -target x86_64-unknown-unknown -g -gdwarf-5 -std=c++11 %s -emit-llvm -S -o - | FileCheck --check-prefixes=CHECK,DWARF5,CPP11 %s -// RUN: %clangxx -target x86_64-windows-msvc -g -gdwarf-4 %s -emit-llvm -S -o - | FileCheck --check-prefixes=CHECK,DWARF4,CPP11 %s +// RUN: %clangxx -target x86_64-unknown-unknown -g -gdwarf-4 -std=c++11 %s -emit-llvm -S -o - | FileCheck --check-prefixes=CHECK,DWARF4,NOT-MS %s +// RUN: %clangxx -target x86_64-unknown-unknown -g -gdwarf-5 -std=c++11 %s -emit-llvm -S -o - | FileCheck --check-prefixes=CHECK,DWARF5 %s +// RUN: %clangxx -target x86_64-windows-msvc -g -gdwarf-4 %s -emit-llvm -S -o - | FileCheck --check-prefixes=CHECK,DWARF4 %s // PR14471 // CHECK: @{{.*}}a{{.*}} = dso_local global i32 4, align 4, !dbg [[A:![0-9]+]] @@ -166,15 +166,3 @@ struct y { }; int y::z; } - -// CHECK: !DIGlobalVariableExpression(var: ![[CONST_A_VAR:[0-9]+]], expr: !DIExpression(DW_OP_constu, 1, DW_OP_stack_value)) -// CHECK: ![[CONST_A_VAR]] = distinct !DIGlobalVariable(name: "const_a" -// CHECK-SAME: isLocal: true, isDefinition: true, declaration: ![[CONST_A_DECL]]) - -// CPP11: !DIGlobalVariableExpression(var: ![[CONST_B_VAR:[0-9]+]], expr: !DIExpression(DW_OP_constu, {{.*}}, DW_OP_stack_value)) -// CPP11: ![[CONST_B_VAR]] = distinct !DIGlobalVariable(name: "const_b" -// CPP11-SAME: isLocal: true, isDefinition: true, declaration: ![[CONST_B_DECL]]) - -// CHECK: !DIGlobalVariableExpression(var: ![[CONST_C_VAR:[0-9]+]], expr: !DIExpression(DW_OP_constu, 18, DW_OP_stack_value)) -// CHECK: ![[CONST_C_VAR]] = distinct !DIGlobalVariable(name: "const_c" -// CHECK-SAME: isLocal: true, isDefinition: true, declaration: ![[CONST_C_DECL]]) diff --git a/clang/test/CodeGenHLSL/builtins/RWBuffer-annotations.hlsl b/clang/test/CodeGenHLSL/builtins/RWBuffer-annotations.hlsl index 77091f8390a15a18e39253af82a8c42f7bc9e8c8..a70e224b81e4b74ab36f6e97cc5a7058b12b5cee 100644 --- a/clang/test/CodeGenHLSL/builtins/RWBuffer-annotations.hlsl +++ b/clang/test/CodeGenHLSL/builtins/RWBuffer-annotations.hlsl @@ -16,9 +16,9 @@ void main() { } // CHECK: !hlsl.uavs = !{![[Single:[0-9]+]], ![[Array:[0-9]+]], ![[SingleAllocated:[0-9]+]], ![[ArrayAllocated:[0-9]+]], ![[SingleSpace:[0-9]+]], ![[ArraySpace:[0-9]+]]} -// CHECK-DAG: ![[Single]] = !{ptr @"?Buffer1@@3V?$RWBuffer@M@hlsl@@A", !"RWBuffer", i32 10, i32 -1, i32 0} -// CHECK-DAG: ![[Array]] = !{ptr @"?BufferArray@@3PAV?$RWBuffer@T?$__vector@M$03@__clang@@@hlsl@@A", !"RWBuffer >", i32 10, i32 -1, i32 0} -// CHECK-DAG: ![[SingleAllocated]] = !{ptr @"?Buffer2@@3V?$RWBuffer@M@hlsl@@A", !"RWBuffer", i32 10, i32 3, i32 0} -// CHECK-DAG: ![[ArrayAllocated]] = !{ptr @"?BufferArray2@@3PAV?$RWBuffer@T?$__vector@M$03@__clang@@@hlsl@@A", !"RWBuffer >", i32 10, i32 4, i32 0} -// CHECK-DAG: ![[SingleSpace]] = !{ptr @"?Buffer3@@3V?$RWBuffer@M@hlsl@@A", !"RWBuffer", i32 10, i32 3, i32 1} -// CHECK-DAG: ![[ArraySpace]] = !{ptr @"?BufferArray3@@3PAV?$RWBuffer@T?$__vector@M$03@__clang@@@hlsl@@A", !"RWBuffer >", i32 10, i32 4, i32 1} +// CHECK-DAG: ![[Single]] = !{ptr @"?Buffer1@@3V?$RWBuffer@M@hlsl@@A", !"RWBuffer", i32 10, i1 false, i32 -1, i32 0} +// CHECK-DAG: ![[Array]] = !{ptr @"?BufferArray@@3PAV?$RWBuffer@T?$__vector@M$03@__clang@@@hlsl@@A", !"RWBuffer >", i32 10, i1 false, i32 -1, i32 0} +// CHECK-DAG: ![[SingleAllocated]] = !{ptr @"?Buffer2@@3V?$RWBuffer@M@hlsl@@A", !"RWBuffer", i32 10, i1 false, i32 3, i32 0} +// CHECK-DAG: ![[ArrayAllocated]] = !{ptr @"?BufferArray2@@3PAV?$RWBuffer@T?$__vector@M$03@__clang@@@hlsl@@A", !"RWBuffer >", i32 10, i1 false, i32 4, i32 0} +// CHECK-DAG: ![[SingleSpace]] = !{ptr @"?Buffer3@@3V?$RWBuffer@M@hlsl@@A", !"RWBuffer", i32 10, i1 false, i32 3, i32 1} +// CHECK-DAG: ![[ArraySpace]] = !{ptr @"?BufferArray3@@3PAV?$RWBuffer@T?$__vector@M$03@__clang@@@hlsl@@A", !"RWBuffer >", i32 10, i1 false, i32 4, i32 1} diff --git a/clang/test/CodeGenHLSL/builtins/RasterizerOrderedBuffer-annotations.hlsl b/clang/test/CodeGenHLSL/builtins/RasterizerOrderedBuffer-annotations.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..ce7d84ecf5b1470d1a6605bd9095b6f1e5130447 --- /dev/null +++ b/clang/test/CodeGenHLSL/builtins/RasterizerOrderedBuffer-annotations.hlsl @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-pixel -x hlsl -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s + +RasterizerOrderedBuffer Buffer1; +RasterizerOrderedBuffer > BufferArray[4]; + +RasterizerOrderedBuffer Buffer2 : register(u3); +RasterizerOrderedBuffer > BufferArray2[4] : register(u4); + +RasterizerOrderedBuffer Buffer3 : register(u3, space1); +RasterizerOrderedBuffer > BufferArray3[4] : register(u4, space1); + +void main() {} + +// CHECK: !hlsl.uavs = !{![[Single:[0-9]+]], ![[Array:[0-9]+]], ![[SingleAllocated:[0-9]+]], ![[ArrayAllocated:[0-9]+]], ![[SingleSpace:[0-9]+]], ![[ArraySpace:[0-9]+]]} +// CHECK-DAG: ![[Single]] = !{ptr @"?Buffer1@@3V?$RasterizerOrderedBuffer@M@hlsl@@A", !"RasterizerOrderedBuffer", i32 10, i1 true, i32 -1, i32 0} +// CHECK-DAG: ![[Array]] = !{ptr @"?BufferArray@@3PAV?$RasterizerOrderedBuffer@T?$__vector@M$03@__clang@@@hlsl@@A", !"RasterizerOrderedBuffer >", i32 10, i1 true, i32 -1, i32 0} +// CHECK-DAG: ![[SingleAllocated]] = !{ptr @"?Buffer2@@3V?$RasterizerOrderedBuffer@M@hlsl@@A", !"RasterizerOrderedBuffer", i32 10, i1 true, i32 3, i32 0} +// CHECK-DAG: ![[ArrayAllocated]] = !{ptr @"?BufferArray2@@3PAV?$RasterizerOrderedBuffer@T?$__vector@M$03@__clang@@@hlsl@@A", !"RasterizerOrderedBuffer >", i32 10, i1 true, i32 4, i32 0} +// CHECK-DAG: ![[SingleSpace]] = !{ptr @"?Buffer3@@3V?$RasterizerOrderedBuffer@M@hlsl@@A", !"RasterizerOrderedBuffer", i32 10, i1 true, i32 3, i32 1} +// CHECK-DAG: ![[ArraySpace]] = !{ptr @"?BufferArray3@@3PAV?$RasterizerOrderedBuffer@T?$__vector@M$03@__clang@@@hlsl@@A", !"RasterizerOrderedBuffer >", i32 10, i1 true, i32 4, i32 1} diff --git a/clang/test/CodeGenHLSL/cbuf.hlsl b/clang/test/CodeGenHLSL/cbuf.hlsl index 92c883943d03e774829d137fff019741a74bad72..5dee1feb902aa0391951d611a8afc75f7f7e7a08 100644 --- a/clang/test/CodeGenHLSL/cbuf.hlsl +++ b/clang/test/CodeGenHLSL/cbuf.hlsl @@ -24,5 +24,5 @@ float foo() { // CHECK: !hlsl.cbufs = !{![[CBMD:[0-9]+]]} // CHECK: !hlsl.srvs = !{![[TBMD:[0-9]+]]} -// CHECK: ![[CBMD]] = !{ptr @[[CB]], !"A.cb.ty", i32 13, i32 0, i32 2} -// CHECK: ![[TBMD]] = !{ptr @[[TB]], !"A.tb.ty", i32 15, i32 2, i32 1} +// CHECK: ![[CBMD]] = !{ptr @[[CB]], !"A.cb.ty", i32 13, i1 false, i32 0, i32 2} +// CHECK: ![[TBMD]] = !{ptr @[[TB]], !"A.tb.ty", i32 15, i1 false, i32 2, i32 1} diff --git a/clang/test/Driver/aarch64-outliner.c b/clang/test/Driver/aarch64-outliner.c index 42e43b433e282d387457e633cd66829cf27c95d8..06e5de11ec49ecde2007cf53da388d116989be21 100644 --- a/clang/test/Driver/aarch64-outliner.c +++ b/clang/test/Driver/aarch64-outliner.c @@ -1,7 +1,9 @@ // REQUIRES: aarch64-registered-target // RUN: %clang --target=aarch64 -moutline -S %s -### 2>&1 | FileCheck %s -check-prefix=ON +// RUN: %clang --target=aarch64_be -moutline -S %s -### 2>&1 | FileCheck %s -check-prefix=ON // ON: "-mllvm" "-enable-machine-outliner" // RUN: %clang --target=aarch64 -moutline -mno-outline -S %s -### 2>&1 | FileCheck %s -check-prefix=OFF +// RUN: %clang --target=aarch64_be -moutline -mno-outline -S %s -### 2>&1 | FileCheck %s -check-prefix=OFF // OFF: "-mllvm" "-enable-machine-outliner=never" // RUN: %clang --target=x86_64 -moutline -S %s -### 2>&1 | FileCheck %s -check-prefix=WARN // WARN: warning: 'x86_64' does not support '-moutline'; flag ignored [-Woption-ignored] diff --git a/clang/test/Driver/aarch64-thread-pointer.c b/clang/test/Driver/aarch64-thread-pointer.c index 6a5d4ba0852edc4ce663a206b0e816b6efbf1f6a..b1c6df4ac5e5ddf637fe000f12cb27e2ba51fda3 100644 --- a/clang/test/Driver/aarch64-thread-pointer.c +++ b/clang/test/Driver/aarch64-thread-pointer.c @@ -1,45 +1,45 @@ // Test of the AArch64 values of -mtp=, checking that each one maps to // the right target features. -// RUN: %clang --target=aarch64-linux -### -S %s -arch armv8a 2>&1 | \ +// RUN: %clang --target=aarch64-linux -### -S %s 2>&1 | \ // RUN: FileCheck -check-prefix=ARMv8_THREAD_POINTER_EL0 %s -// RUN: %clang --target=aarch64-linux -### -S %s -arch armv8a -mtp=el0 2>&1 | \ +// RUN: %clang --target=aarch64-linux -### -S %s -mtp=el0 2>&1 | \ // RUN: FileCheck -check-prefix=ARMv8_THREAD_POINTER_EL0 %s -// RUN: %clang --target=aarch64-linux -### -S %s -arch armv8a -mtp=tpidr_el0 2>&1 | \ +// RUN: %clang --target=aarch64-linux -### -S %s -mtp=tpidr_el0 2>&1 | \ // RUN: FileCheck -check-prefix=ARMv8_THREAD_POINTER_EL0 %s // ARMv8_THREAD_POINTER_EL0-NOT: "-target-feature" "+tpidrro-el0" // ARMv8_THREAD_POINTER_EL0-NOT: "-target-feature" "+tpidr-el1" // ARMv8_THREAD_POINTER_EL0-NOT: "-target-feature" "+tpidr-el2" // ARMv8_THREAD_POINTER_EL0-NOT: "-target-feature" "+tpidr-el3" -// RUN: %clang --target=aarch64-linux -### -S %s -arch armv8a -mtp=tpidrro_el0 2>&1 | \ +// RUN: %clang --target=aarch64-linux -### -S %s -mtp=tpidrro_el0 2>&1 | \ // RUN: FileCheck -check-prefix=ARMv8_THREAD_POINTER_ROEL0 %s // ARMv8_THREAD_POINTER_ROEL0: "-target-feature" "+tpidrro-el0" // ARMv8_THREAD_POINTER_ROEL0-NOT: "-target-feature" "+tpidr-el1" // ARMv8_THREAD_POINTER_ROEL0-NOT: "-target-feature" "+tpidr-el2" // ARMv8_THREAD_POINTER_ROEL0-NOT: "-target-feature" "+tpidr-el3" -// RUN: %clang --target=aarch64-linux -### -S %s -arch armv8a -mtp=el1 2>&1 | \ +// RUN: %clang --target=aarch64-linux -### -S %s -mtp=el1 2>&1 | \ // RUN: FileCheck -check-prefix=ARMv8_THREAD_POINTER_EL1 %s -// RUN: %clang --target=aarch64-linux -### -S %s -arch armv8a -mtp=tpidr_el1 2>&1 | \ +// RUN: %clang --target=aarch64-linux -### -S %s -mtp=tpidr_el1 2>&1 | \ // RUN: FileCheck -check-prefix=ARMv8_THREAD_POINTER_EL1 %s // ARMv8_THREAD_POINTER_EL1-NOT: "-target-feature" "+tpidrro-el0" // ARMv8_THREAD_POINTER_EL1: "-target-feature" "+tpidr-el1" // ARMv8_THREAD_POINTER_EL1-NOT: "-target-feature" "+tpidr-el2" // ARMv8_THREAD_POINTER_EL1-NOT: "-target-feature" "+tpidr-el3" -// RUN: %clang --target=aarch64-linux -### -S %s -arch armv8a -mtp=el2 2>&1 | \ +// RUN: %clang --target=aarch64-linux -### -S %s -mtp=el2 2>&1 | \ // RUN: FileCheck -check-prefix=ARMv8_THREAD_POINTER_EL2 %s -// RUN: %clang --target=aarch64-linux -### -S %s -arch armv8a -mtp=tpidr_el2 2>&1 | \ +// RUN: %clang --target=aarch64-linux -### -S %s -mtp=tpidr_el2 2>&1 | \ // RUN: FileCheck -check-prefix=ARMv8_THREAD_POINTER_EL2 %s // ARMv8_THREAD_POINTER_EL2-NOT: "-target-feature" "+tpidrro-el0" // ARMv8_THREAD_POINTER_EL2-NOT: "-target-feature" "+tpidr-el1" // ARMv8_THREAD_POINTER_EL2: "-target-feature" "+tpidr-el2" // ARMv8_THREAD_POINTER_EL2-NOT: "-target-feature" "+tpidr-el3" -// RUN: %clang --target=aarch64-linux -### -S %s -arch armv8a -mtp=el3 2>&1 | \ +// RUN: %clang --target=aarch64-linux -### -S %s -mtp=el3 2>&1 | \ // RUN: FileCheck -check-prefix=ARMv8_THREAD_POINTER_EL3 %s -// RUN: %clang --target=aarch64-linux -### -S %s -arch armv8a -mtp=tpidr_el3 2>&1 | \ +// RUN: %clang --target=aarch64-linux -### -S %s -mtp=tpidr_el3 2>&1 | \ // RUN: FileCheck -check-prefix=ARMv8_THREAD_POINTER_EL3 %s // ARMv8_THREAD_POINTER_EL3-NOT: "-target-feature" "+tpidrro-el0" // ARMv8_THREAD_POINTER_EL3-NOT: "-target-feature" "+tpidr-el1" diff --git a/clang/test/Driver/arc-exceptions.m b/clang/test/Driver/arc-exceptions.m index 4501ccd07382340106393d62b069ae7bc74c34bd..c1dd02d59988c8d14780ea5a8224d36c4441ec7e 100644 --- a/clang/test/Driver/arc-exceptions.m +++ b/clang/test/Driver/arc-exceptions.m @@ -1,5 +1,5 @@ -// RUN: %clang -### -x objective-c -arch x86_64 -fobjc-arc -fsyntax-only %s 2> %t.log +// RUN: %clang -### -x objective-c --target=x86_64-apple-macos10.6 -fobjc-arc -fsyntax-only %s 2> %t.log // RUN: grep objective-c %t.log // RUN: not grep "fobjc-arc-exceptions" %t.log -// RUN: %clang -### -x objective-c++ -arch x86_64 -fobjc-arc -fsyntax-only %s 2> %t.log +// RUN: %clang -### -x objective-c++ --target=x86_64-apple-macos10.6 -fobjc-arc -fsyntax-only %s 2> %t.log // RUN: grep "fobjc-arc-exceptions" %t.log diff --git a/clang/test/Driver/arm-arch-darwin.c b/clang/test/Driver/arm-arch-darwin.c index 55089619d1e7143a138e7b40d5f3b634e1014a97..f6d3f88a3f8d1f693efef585d5a2146e4b79d806 100644 --- a/clang/test/Driver/arm-arch-darwin.c +++ b/clang/test/Driver/arm-arch-darwin.c @@ -1,6 +1,10 @@ // On Darwin, arch should override CPU for triple purposes // RUN: %clang -target armv7m-apple-darwin -arch armv7m -mcpu=cortex-m4 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V7M-DARWIN %s // CHECK-V7M-DARWIN: "-cc1"{{.*}} "-triple" "thumbv7m-{{.*}} "-target-cpu" "cortex-m4" -// RUN: %clang -target armv7m -arch armv7m -mcpu=cortex-m4 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V7M-OVERRIDDEN %s -// CHECK-V7M-OVERRIDDEN: "-cc1"{{.*}} "-triple" "thumbv7em-{{.*}} "-target-cpu" "cortex-m4" +/// -arch is unsupported for non-Darwin targets. +// RUN: not %clang --target=armv7m -arch armv7m -mcpu=cortex-m4 -### -c %s 2>&1 | FileCheck -check-prefix=ERR %s +// ERR: unsupported option '-arch' for target 'armv7m' + +// RUN: not %clang --target=aarch64-linux-gnu -arch arm64 -### -c %s 2>&1 | FileCheck -check-prefix=ERR2 %s +// ERR2: unsupported option '-arch' for target 'aarch64-linux-gnu' diff --git a/clang/test/Driver/arm-cortex-cpus-2.c b/clang/test/Driver/arm-cortex-cpus-2.c index 5b52488bc498f3e41b367719ebdcbee466715047..c322303d22786681c25d11b271f273624d5cc2d7 100644 --- a/clang/test/Driver/arm-cortex-cpus-2.c +++ b/clang/test/Driver/arm-cortex-cpus-2.c @@ -562,8 +562,11 @@ // RUN: %clang -target arm -mcpu=cortex-m85 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CORTEX-M85 %s // CHECK-CORTEX-M85: "-cc1"{{.*}} "-triple" "thumbv8.1m.main-{{.*}} "-target-cpu" "cortex-m85" +// RUN: %clang -target arm -mcpu=cortex-m52 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CORTEX-M52 %s +// CHECK-CORTEX-M52: "-cc1"{{.*}} "-triple" "thumbv8.1m.main-{{.*}} "-target-cpu" "cortex-m52" + // RUN: %clang -target arm -mcpu=neoverse-n2 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-NEOVERSE-N2 %s -// CHECK-NEOVERSE-N2: "-cc1"{{.*}} "-triple" "armv8.5a-{{.*}}" "-target-cpu" "neoverse-n2" +// CHECK-NEOVERSE-N2: "-cc1"{{.*}} "-triple" "armv9a-{{.*}}" "-target-cpu" "neoverse-n2" // ================== Check whether -mcpu accepts mixed-case values. // RUN: %clang -target arm-linux-gnueabi -mcpu=Cortex-a5 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CASE-INSENSITIVE-CPUV7A %s diff --git a/clang/test/Driver/cl-options.c b/clang/test/Driver/cl-options.c index 6d929b19e7e2ef8da5fdc6b038bcf8b4a70433b1..81d1b907eced188c5c7096aca6e9c751f9973eb3 100644 --- a/clang/test/Driver/cl-options.c +++ b/clang/test/Driver/cl-options.c @@ -747,7 +747,7 @@ // Validate that the default triple is used when run an empty tools dir is specified // RUN: %clang_cl -vctoolsdir "" -### -- %s 2>&1 | FileCheck %s --check-prefix VCTOOLSDIR -// VCTOOLSDIR: "-triple" "{{[a-zA-Z0-9_-]*}}-pc-windows-msvc19.20.0" +// VCTOOLSDIR: "-triple" "{{[a-zA-Z0-9_-]*}}-pc-windows-msvc19.33.0" // Validate that built-in include paths are based on the supplied path // RUN: %clang_cl --target=aarch64-pc-windows-msvc -vctoolsdir "/fake" -winsdkdir "/foo" -winsdkversion 10.0.12345.0 -### -- %s 2>&1 | FileCheck %s --check-prefix FAKEDIR @@ -787,7 +787,7 @@ // RUN: %clang_cl -vctoolsdir "" /arm64EC /c -### -- %s 2>&1 | FileCheck --check-prefix=ARM64EC %s // ARM64EC-NOT: /arm64EC has been overridden by specified target -// ARM64EC: "-triple" "arm64ec-pc-windows-msvc19.20.0" +// ARM64EC: "-triple" "arm64ec-pc-windows-msvc19.33.0" // RUN: %clang_cl -vctoolsdir "" /arm64EC /c -target x86_64-pc-windows-msvc -### -- %s 2>&1 | FileCheck --check-prefix=ARM64EC_OVERRIDE %s // ARM64EC_OVERRIDE: warning: /arm64EC has been overridden by specified target: x86_64-pc-windows-msvc; option ignored diff --git a/clang/test/Driver/clang-offload-bundler-zlib.c b/clang/test/Driver/clang-offload-bundler-zlib.c index c46c32a4a0537b4047b77d0e61db65cadcfac162..a57ee6da9a86a6d31ecb1091335a0acbb5ce8929 100644 --- a/clang/test/Driver/clang-offload-bundler-zlib.c +++ b/clang/test/Driver/clang-offload-bundler-zlib.c @@ -55,14 +55,15 @@ // Check unbundling archive. // // RUN: clang-offload-bundler -type=bc -targets=hip-amdgcn-amd-amdhsa--gfx900,hip-amdgcn-amd-amdhsa--gfx906 \ -// RUN: -input=%t.tgt1 -input=%t.tgt2 -output=%T/hip_bundle1.bc -compress +// RUN: -input=%t.tgt1 -input=%t.tgt2 -output=%t.hip_bundle1.bc -compress // RUN: clang-offload-bundler -type=bc -targets=hip-amdgcn-amd-amdhsa--gfx900,hip-amdgcn-amd-amdhsa--gfx906 \ -// RUN: -input=%t.tgt1 -input=%t.tgt2 -output=%T/hip_bundle2.bc -compress -// RUN: llvm-ar cr %T/hip_archive.a %T/hip_bundle1.bc %T/hip_bundle2.bc +// RUN: -input=%t.tgt1 -input=%t.tgt2 -output=%t.hip_bundle2.bc -compress +// RUN: rm -f %t.hip_archive.a +// RUN: llvm-ar cr %t.hip_archive.a %t.hip_bundle1.bc %t.hip_bundle2.bc // RUN: clang-offload-bundler -unbundle -type=a -targets=hip-amdgcn-amd-amdhsa--gfx900,hip-amdgcn-amd-amdhsa--gfx906 \ -// RUN: -output=%T/hip_900.a -output=%T/hip_906.a -input=%T/hip_archive.a -// RUN: llvm-ar t %T/hip_900.a | FileCheck -check-prefix=HIP-AR-900 %s -// RUN: llvm-ar t %T/hip_906.a | FileCheck -check-prefix=HIP-AR-906 %s +// RUN: -output=%t.hip_900.a -output=%t.hip_906.a -input=%t.hip_archive.a +// RUN: llvm-ar t %t.hip_900.a | FileCheck -check-prefix=HIP-AR-900 %s +// RUN: llvm-ar t %t.hip_906.a | FileCheck -check-prefix=HIP-AR-906 %s // HIP-AR-900-DAG: hip_bundle1-hip-amdgcn-amd-amdhsa--gfx900 // HIP-AR-900-DAG: hip_bundle2-hip-amdgcn-amd-amdhsa--gfx900 // HIP-AR-906-DAG: hip_bundle1-hip-amdgcn-amd-amdhsa--gfx906 diff --git a/clang/test/Driver/clang-offload-bundler-zstd.c b/clang/test/Driver/clang-offload-bundler-zstd.c index b2b588b72d4d6f282b376b5c734cba9ea1eeb614..3b577d4d166a3f5e8b6162d67bcb3f981ad4f9ae 100644 --- a/clang/test/Driver/clang-offload-bundler-zstd.c +++ b/clang/test/Driver/clang-offload-bundler-zstd.c @@ -48,18 +48,18 @@ // RUN: diff %t.tgt1 %t.res.tgt1 // RUN: diff %t.tgt2 %t.res.tgt2 -// // Check unbundling archive. // // RUN: clang-offload-bundler -type=bc -targets=hip-amdgcn-amd-amdhsa--gfx900,hip-amdgcn-amd-amdhsa--gfx906 \ -// RUN: -input=%t.tgt1 -input=%t.tgt2 -output=%T/hip_bundle1.bc -compress +// RUN: -input=%t.tgt1 -input=%t.tgt2 -output=%t.hip_bundle1.bc -compress // RUN: clang-offload-bundler -type=bc -targets=hip-amdgcn-amd-amdhsa--gfx900,hip-amdgcn-amd-amdhsa--gfx906 \ -// RUN: -input=%t.tgt1 -input=%t.tgt2 -output=%T/hip_bundle2.bc -compress -// RUN: llvm-ar cr %T/hip_archive.a %T/hip_bundle1.bc %T/hip_bundle2.bc +// RUN: -input=%t.tgt1 -input=%t.tgt2 -output=%t.hip_bundle2.bc -compress +// RUN: rm -f %t.hip_archive.a +// RUN: llvm-ar cr %t.hip_archive.a %t.hip_bundle1.bc %t.hip_bundle2.bc // RUN: clang-offload-bundler -unbundle -type=a -targets=hip-amdgcn-amd-amdhsa--gfx900,hip-amdgcn-amd-amdhsa--gfx906 \ -// RUN: -output=%T/hip_900.a -output=%T/hip_906.a -input=%T/hip_archive.a -// RUN: llvm-ar t %T/hip_900.a | FileCheck -check-prefix=HIP-AR-900 %s -// RUN: llvm-ar t %T/hip_906.a | FileCheck -check-prefix=HIP-AR-906 %s +// RUN: -output=%t.hip_900.a -output=%t.hip_906.a -input=%t.hip_archive.a +// RUN: llvm-ar t %t.hip_900.a | FileCheck -check-prefix=HIP-AR-900 %s +// RUN: llvm-ar t %t.hip_906.a | FileCheck -check-prefix=HIP-AR-906 %s // HIP-AR-900-DAG: hip_bundle1-hip-amdgcn-amd-amdhsa--gfx900 // HIP-AR-900-DAG: hip_bundle2-hip-amdgcn-amd-amdhsa--gfx900 // HIP-AR-906-DAG: hip_bundle1-hip-amdgcn-amd-amdhsa--gfx906 diff --git a/clang/test/Driver/fdefine-target-os-macros.c b/clang/test/Driver/fdefine-target-os-macros.c new file mode 100644 index 0000000000000000000000000000000000000000..030d4ce34cb282bd204eca00f21c9d20f854b9ea --- /dev/null +++ b/clang/test/Driver/fdefine-target-os-macros.c @@ -0,0 +1,250 @@ +// RUN: %clang -### --target=arm64-apple-darwin %s 2>&1 | FileCheck %s --check-prefix=DARWIN-DEFAULT +// DARWIN-DEFAULT-NOT: "-fdefine-target-os-macros" + +// RUN: %clang -### --target=arm-none-linux-gnu %s 2>&1 | FileCheck %s --check-prefix=NON-DARWIN-DEFAULT +// RUN: %clang -### --target=x86_64-pc-win32 %s 2>&1 | FileCheck %s --check-prefix=NON-DARWIN-DEFAULT +// NON-DARWIN-DEFAULT-NOT: "-fdefine-target-os-macros" + +// RUN: %clang -dM -E --target=arm64-apple-macos \ +// RUN: -fdefine-target-os-macros %s 2>&1 \ +// RUN: | FileCheck %s -DMAC=1 \ +// RUN: -DOSX=1 \ +// RUN: -DIPHONE=0 \ +// RUN: -DIOS=0 \ +// RUN: -DTV=0 \ +// RUN: -DWATCH=0 \ +// RUN: -DDRIVERKIT=0 \ +// RUN: -DMACCATALYST=0 \ +// RUN: -DEMBEDDED=0 \ +// RUN: -DSIMULATOR=0 \ +// RUN: -DWINDOWS=0 \ +// RUN: -DLINUX=0 \ +// RUN: -DUNIX=0 + +// RUN: %clang -dM -E --target=arm64-apple-ios \ +// RUN: -fdefine-target-os-macros %s 2>&1 \ +// RUN: | FileCheck %s -DMAC=1 \ +// RUN: -DOSX=0 \ +// RUN: -DIPHONE=1 \ +// RUN: -DIOS=1 \ +// RUN: -DTV=0 \ +// RUN: -DWATCH=0 \ +// RUN: -DDRIVERKIT=0 \ +// RUN: -DMACCATALYST=0 \ +// RUN: -DEMBEDDED=1 \ +// RUN: -DSIMULATOR=0 \ +// RUN: -DWINDOWS=0 \ +// RUN: -DLINUX=0 \ +// RUN: -DUNIX=0 + +// RUN: %clang -dM -E --target=arm64-apple-ios-macabi \ +// RUN: -fdefine-target-os-macros %s 2>&1 \ +// RUN: | FileCheck %s -DMAC=1 \ +// RUN: -DOSX=0 \ +// RUN: -DIPHONE=1 \ +// RUN: -DIOS=1 \ +// RUN: -DTV=0 \ +// RUN: -DWATCH=0 \ +// RUN: -DDRIVERKIT=0 \ +// RUN: -DMACCATALYST=1 \ +// RUN: -DEMBEDDED=0 \ +// RUN: -DSIMULATOR=0 \ +// RUN: -DWINDOWS=0 \ +// RUN: -DLINUX=0 \ +// RUN: -DUNIX=0 + +// RUN: %clang -dM -E --target=arm64-apple-ios-simulator \ +// RUN: -fdefine-target-os-macros %s 2>&1 \ +// RUN: | FileCheck %s -DMAC=1 \ +// RUN: -DOSX=0 \ +// RUN: -DIPHONE=1 \ +// RUN: -DIOS=1 \ +// RUN: -DTV=0 \ +// RUN: -DWATCH=0 \ +// RUN: -DDRIVERKIT=0 \ +// RUN: -DMACCATALYST=0 \ +// RUN: -DEMBEDDED=0 \ +// RUN: -DSIMULATOR=1 \ +// RUN: -DWINDOWS=0 \ +// RUN: -DLINUX=0 \ +// RUN: -DUNIX=0 + +// RUN: %clang -dM -E --target=arm64-apple-tvos \ +// RUN: -fdefine-target-os-macros %s 2>&1 \ +// RUN: | FileCheck %s -DMAC=1 \ +// RUN: -DOSX=0 \ +// RUN: -DIPHONE=1 \ +// RUN: -DIOS=0 \ +// RUN: -DTV=1 \ +// RUN: -DWATCH=0 \ +// RUN: -DDRIVERKIT=0 \ +// RUN: -DMACCATALYST=0 \ +// RUN: -DEMBEDDED=1 \ +// RUN: -DSIMULATOR=0 \ +// RUN: -DWINDOWS=0 \ +// RUN: -DLINUX=0 \ +// RUN: -DUNIX=0 + +// RUN: %clang -dM -E --target=arm64-apple-tvos-simulator \ +// RUN: -fdefine-target-os-macros %s 2>&1 \ +// RUN: | FileCheck %s -DMAC=1 \ +// RUN: -DOSX=0 \ +// RUN: -DIPHONE=1 \ +// RUN: -DIOS=0 \ +// RUN: -DTV=1 \ +// RUN: -DWATCH=0 \ +// RUN: -DDRIVERKIT=0 \ +// RUN: -DMACCATALYST=0 \ +// RUN: -DEMBEDDED=0 \ +// RUN: -DSIMULATOR=1 \ +// RUN: -DWINDOWS=0 \ +// RUN: -DLINUX=0 \ +// RUN: -DUNIX=0 + +// RUN: %clang -dM -E --target=arm64-apple-watchos \ +// RUN: -fdefine-target-os-macros %s 2>&1 \ +// RUN: | FileCheck %s -DMAC=1 \ +// RUN: -DOSX=0 \ +// RUN: -DIPHONE=1 \ +// RUN: -DIOS=0 \ +// RUN: -DTV=0 \ +// RUN: -DWATCH=1 \ +// RUN: -DDRIVERKIT=0 \ +// RUN: -DMACCATALYST=0 \ +// RUN: -DEMBEDDED=1 \ +// RUN: -DSIMULATOR=0 \ +// RUN: -DWINDOWS=0 \ +// RUN: -DLINUX=0 \ +// RUN: -DUNIX=0 + +// RUN: %clang -dM -E --target=arm64-apple-watchos-simulator \ +// RUN: -fdefine-target-os-macros %s 2>&1 \ +// RUN: | FileCheck %s -DMAC=1 \ +// RUN: -DOSX=0 \ +// RUN: -DIPHONE=1 \ +// RUN: -DIOS=0 \ +// RUN: -DTV=0 \ +// RUN: -DWATCH=1 \ +// RUN: -DDRIVERKIT=0 \ +// RUN: -DMACCATALYST=0 \ +// RUN: -DEMBEDDED=0 \ +// RUN: -DSIMULATOR=1 \ +// RUN: -DWINDOWS=0 \ +// RUN: -DLINUX=0 \ +// RUN: -DUNIX=0 + +// RUN: %clang -dM -E --target=arm64-apple-driverkit \ +// RUN: -fdefine-target-os-macros %s 2>&1 \ +// RUN: | FileCheck %s -DMAC=1 \ +// RUN: -DOSX=0 \ +// RUN: -DIPHONE=0 \ +// RUN: -DIOS=0 \ +// RUN: -DTV=0 \ +// RUN: -DWATCH=0 \ +// RUN: -DDRIVERKIT=1 \ +// RUN: -DMACCATALYST=0 \ +// RUN: -DEMBEDDED=0 \ +// RUN: -DSIMULATOR=0 \ +// RUN: -DWINDOWS=0 \ +// RUN: -DLINUX=0 \ +// RUN: -DUNIX=0 + +// RUN: %clang -dM -E --target=x86_64-pc-linux-gnu \ +// RUN: -fdefine-target-os-macros %s 2>&1 \ +// RUN: | FileCheck %s -DMAC=0 \ +// RUN: -DOSX=0 \ +// RUN: -DIPHONE=0 \ +// RUN: -DIOS=0 \ +// RUN: -DTV=0 \ +// RUN: -DWATCH=0 \ +// RUN: -DDRIVERKIT=0 \ +// RUN: -DMACCATALYST=0 \ +// RUN: -DEMBEDDED=0 \ +// RUN: -DSIMULATOR=0 \ +// RUN: -DWINDOWS=0 \ +// RUN: -DLINUX=1 \ +// RUN: -DUNIX=0 + +// RUN: %clang -dM -E --target=x86_64-pc-win32 \ +// RUN: -fdefine-target-os-macros %s 2>&1 \ +// RUN: | FileCheck %s -DMAC=0 \ +// RUN: -DOSX=0 \ +// RUN: -DIPHONE=0 \ +// RUN: -DIOS=0 \ +// RUN: -DTV=0 \ +// RUN: -DWATCH=0 \ +// RUN: -DDRIVERKIT=0 \ +// RUN: -DMACCATALYST=0 \ +// RUN: -DEMBEDDED=0 \ +// RUN: -DSIMULATOR=0 \ +// RUN: -DWINDOWS=1 \ +// RUN: -DLINUX=0 \ +// RUN: -DUNIX=0 + +// RUN: %clang -dM -E --target=x86_64-pc-windows-gnu \ +// RUN: -fdefine-target-os-macros %s 2>&1 \ +// RUN: | FileCheck %s -DMAC=0 \ +// RUN: -DOSX=0 \ +// RUN: -DIPHONE=0 \ +// RUN: -DIOS=0 \ +// RUN: -DTV=0 \ +// RUN: -DWATCH=0 \ +// RUN: -DDRIVERKIT=0 \ +// RUN: -DMACCATALYST=0 \ +// RUN: -DEMBEDDED=0 \ +// RUN: -DSIMULATOR=0 \ +// RUN: -DWINDOWS=1 \ +// RUN: -DLINUX=0 \ +// RUN: -DUNIX=0 + +// RUN: %clang -dM -E --target=sparc-none-solaris \ +// RUN: -fdefine-target-os-macros %s 2>&1 \ +// RUN: | FileCheck %s -DMAC=0 \ +// RUN: -DOSX=0 \ +// RUN: -DIPHONE=0 \ +// RUN: -DIOS=0 \ +// RUN: -DTV=0 \ +// RUN: -DWATCH=0 \ +// RUN: -DDRIVERKIT=0 \ +// RUN: -DMACCATALYST=0 \ +// RUN: -DEMBEDDED=0 \ +// RUN: -DSIMULATOR=0 \ +// RUN: -DWINDOWS=0 \ +// RUN: -DLINUX=0 \ +// RUN: -DUNIX=1 + +// RUN: %clang -dM -E --target=arm64-apple-macos \ +// RUN: -fno-define-target-os-macros %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=NEG + +// RUN: %clang -dM -E --target=arm64-apple-macos \ +// RUN: -fdefine-target-os-macros \ +// RUN: -fno-define-target-os-macros %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=NEG + +// RUN: %clang -dM -E --target=x86_64-pc-windows \ +// RUN: -fdefine-target-os-macros \ +// RUN: -fno-define-target-os-macros %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=NEG + +// NEG-NOT: #define TARGET_OS_ + +// CHECK-DAG: #define TARGET_OS_MAC [[MAC]] +// CHECK-DAG: #define TARGET_OS_OSX [[OSX]] +// CHECK-DAG: #define TARGET_OS_IPHONE [[IPHONE]] +// CHECK-DAG: #define TARGET_OS_IOS [[IOS]] +// CHECK-DAG: #define TARGET_OS_TV [[TV]] +// CHECK-DAG: #define TARGET_OS_WATCH [[WATCH]] +// CHECK-DAG: #define TARGET_OS_DRIVERKIT [[DRIVERKIT]] +// CHECK-DAG: #define TARGET_OS_MACCATALYST [[MACCATALYST]] +// CHECK-DAG: #define TARGET_OS_SIMULATOR [[SIMULATOR]] +// Deprecated +// CHECK-DAG: #define TARGET_OS_EMBEDDED [[EMBEDDED]] +// CHECK-DAG: #define TARGET_OS_NANO [[WATCH]] +// CHECK-DAG: #define TARGET_IPHONE_SIMULATOR [[SIMULATOR]] +// CHECK-DAG: #define TARGET_OS_UIKITFORMAC [[MACCATALYST]] +// Non-darwin OSes +// CHECK-DAG: #define TARGET_OS_WIN32 [[WINDOWS]] +// CHECK-DAG: #define TARGET_OS_WINDOWS [[WINDOWS]] +// CHECK-DAG: #define TARGET_OS_LINUX [[LINUX]] +// CHECK-DAG: #define TARGET_OS_UNIX [[UNIX]] diff --git a/clang/test/Driver/hip-offload-compress-zlib.hip b/clang/test/Driver/hip-offload-compress-zlib.hip index a29b6d037350d47774a892f370b1a7f04d3396b9..7557fdde8786c7bfda882718e98ee7e0b9db3718 100644 --- a/clang/test/Driver/hip-offload-compress-zlib.hip +++ b/clang/test/Driver/hip-offload-compress-zlib.hip @@ -4,13 +4,13 @@ // Test compress bundled bitcode. -// RUN: rm -rf %T/a.bc +// RUN: rm -rf %t.bc // RUN: %clang -c -v --target=x86_64-linux-gnu \ // RUN: -x hip --offload-arch=gfx1100 --offload-arch=gfx1101 \ // RUN: -fgpu-rdc -nogpuinc -nogpulib \ // RUN: %S/Inputs/hip_multiple_inputs/a.cu \ // RUN: --offload-compress --offload-device-only --gpu-bundle-output \ -// RUN: -o %T/a.bc \ +// RUN: -o %t.bc \ // RUN: 2>&1 | FileCheck %s // CHECK: clang-offload-bundler{{.*}} -type=bc @@ -23,7 +23,7 @@ // RUN: %clang --hip-link -### -v --target=x86_64-linux-gnu \ // RUN: --offload-arch=gfx1100 --offload-arch=gfx1101 \ // RUN: -fgpu-rdc -nogpulib \ -// RUN: %T/a.bc --offload-device-only \ +// RUN: %t.bc --offload-device-only \ // RUN: 2>&1 | FileCheck -check-prefix=UNBUNDLE %s // UNBUNDLE: clang-offload-bundler{{.*}} "-type=bc" diff --git a/clang/test/Driver/hip-offload-compress-zstd.hip b/clang/test/Driver/hip-offload-compress-zstd.hip index 688c2c85329c1921ed120d97bf779f5c8ada984c..3680ae47974a601f4fc2c017d46a331828a19e63 100644 --- a/clang/test/Driver/hip-offload-compress-zstd.hip +++ b/clang/test/Driver/hip-offload-compress-zstd.hip @@ -4,13 +4,13 @@ // Test compress bundled bitcode. -// RUN: rm -rf %T/a.bc +// RUN: rm -rf %t.bc // RUN: %clang -c -v --target=x86_64-linux-gnu \ // RUN: -x hip --offload-arch=gfx1100 --offload-arch=gfx1101 \ // RUN: -fgpu-rdc -nogpuinc -nogpulib \ // RUN: %S/Inputs/hip_multiple_inputs/a.cu \ // RUN: --offload-compress --offload-device-only --gpu-bundle-output \ -// RUN: -o %T/a.bc \ +// RUN: -o %t.bc \ // RUN: 2>&1 | FileCheck %s // CHECK: clang-offload-bundler{{.*}} -type=bc @@ -23,7 +23,7 @@ // RUN: %clang --hip-link -### -v --target=x86_64-linux-gnu \ // RUN: --offload-arch=gfx1100 --offload-arch=gfx1101 \ // RUN: -fgpu-rdc -nogpulib \ -// RUN: %T/a.bc --offload-device-only \ +// RUN: %t.bc --offload-device-only \ // RUN: 2>&1 | FileCheck -check-prefix=UNBUNDLE %s // UNBUNDLE: clang-offload-bundler{{.*}} "-type=bc" diff --git a/clang/test/Driver/linker-wrapper-image.c b/clang/test/Driver/linker-wrapper-image.c index 73d3c40810c35a8ec0bf33842a1d76e7906f9e49..a2a1996f66430900e8ea655e978b6fe49052fa5f 100644 --- a/clang/test/Driver/linker-wrapper-image.c +++ b/clang/test/Driver/linker-wrapper-image.c @@ -80,24 +80,33 @@ // CUDA-NEXT: br i1 icmp ne (ptr @__start_cuda_offloading_entries, ptr @__stop_cuda_offloading_entries), label %while.entry, label %while.end // CUDA: while.entry: -// CUDA-NEXT: %entry1 = phi ptr [ @__start_cuda_offloading_entries, %entry ], [ %7, %if.end ] -// CUDA-NEXT: %1 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 0, i32 0 -// CUDA-NEXT: %addr = load ptr, ptr %1, align 8 -// CUDA-NEXT: %2 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 0, i32 1 -// CUDA-NEXT: %name = load ptr, ptr %2, align 8 -// CUDA-NEXT: %3 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 0, i32 2 -// CUDA-NEXT: %size = load i64, ptr %3, align 4 -// CUDA-NEXT: %4 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 0, i32 3 -// CUDA-NEXT: %flag = load i32, ptr %4, align 4 -// CUDA-NEXT: %5 = icmp eq i64 %size, 0 -// CUDA-NEXT: br i1 %5, label %if.then, label %if.else +// CUDA-NEXT: %entry1 = phi ptr [ @__start_cuda_offloading_entries, %entry ], [ %11, %if.end ] +// CUDA-NEXT: %1 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 0, i32 0 +// CUDA-NEXT: %addr = load ptr, ptr %1, align 8 +// CUDA-NEXT: %2 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 0, i32 1 +// CUDA-NEXT: %name = load ptr, ptr %2, align 8 +// CUDA-NEXT: %3 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 0, i32 2 +// CUDA-NEXT: %size = load i64, ptr %3, align 4 +// CUDA-NEXT: %4 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 0, i32 3 +// CUDA-NEXT: %flags = load i32, ptr %4, align 4 +// CUDA-NEXT: %5 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 0, i32 4 +// CUDA-NEXT: %textype = load i32, ptr %5, align 4 +// CUDA-NEXT: %type = and i32 %flags, 7 +// CUDA-NEXT: %6 = and i32 %flags, 8 +// CUDA-NEXT: %extern = lshr i32 %6, 3 +// CUDA-NEXT: %7 = and i32 %flags, 16 +// CUDA-NEXT: %constant = lshr i32 %7, 4 +// CUDA-NEXT: %8 = and i32 %flags, 32 +// CUDA-NEXT: %normalized = lshr i32 %8, 5 +// CUDA-NEXT: %9 = icmp eq i64 %size, 0 +// CUDA-NEXT: br i1 %9, label %if.then, label %if.else // CUDA: if.then: -// CUDA-NEXT: %6 = call i32 @__cudaRegisterFunction(ptr %0, ptr %addr, ptr %name, ptr %name, i32 -1, ptr null, ptr null, ptr null, ptr null, ptr null) +// CUDA-NEXT: %10 = call i32 @__cudaRegisterFunction(ptr %0, ptr %addr, ptr %name, ptr %name, i32 -1, ptr null, ptr null, ptr null, ptr null, ptr null) // CUDA-NEXT: br label %if.end // CUDA: if.else: -// CUDA-NEXT: switch i32 %flag, label %if.end [ +// CUDA-NEXT: switch i32 %type, label %if.end [ // CUDA-NEXT: i32 0, label %sw.global // CUDA-NEXT: i32 1, label %sw.managed // CUDA-NEXT: i32 2, label %sw.surface @@ -105,22 +114,24 @@ // CUDA-NEXT: ] // CUDA: sw.global: -// CUDA-NEXT: call void @__cudaRegisterVar(ptr %0, ptr %addr, ptr %name, ptr %name, i32 0, i64 %size, i32 0, i32 0) +// CUDA-NEXT: call void @__cudaRegisterVar(ptr %0, ptr %addr, ptr %name, ptr %name, i32 %extern, i64 %size, i32 %constant, i32 0) // CUDA-NEXT: br label %if.end // CUDA: sw.managed: // CUDA-NEXT: br label %if.end // CUDA: sw.surface: +// CUDA-NEXT: call void @__cudaRegisterSurface(ptr %0, ptr %addr, ptr %name, ptr %name, i32 %textype, i32 %extern) // CUDA-NEXT: br label %if.end // CUDA: sw.texture: +// CUDA-NEXT: call void @__cudaRegisterTexture(ptr %0, ptr %addr, ptr %name, ptr %name, i32 %textype, i32 %normalized, i32 %extern) // CUDA-NEXT: br label %if.end // CUDA: if.end: -// CUDA-NEXT: %7 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 1 -// CUDA-NEXT: %8 = icmp eq ptr %7, @__stop_cuda_offloading_entries -// CUDA-NEXT: br i1 %8, label %while.end, label %while.entry +// CUDA-NEXT: %11 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 1 +// CUDA-NEXT: %12 = icmp eq ptr %11, @__stop_cuda_offloading_entries +// CUDA-NEXT: br i1 %12, label %while.end, label %while.entry // CUDA: while.end: // CUDA-NEXT: ret void @@ -168,7 +179,7 @@ // HIP-NEXT: br i1 icmp ne (ptr @__start_hip_offloading_entries, ptr @__stop_hip_offloading_entries), label %while.entry, label %while.end // HIP: while.entry: -// HIP-NEXT: %entry1 = phi ptr [ @__start_hip_offloading_entries, %entry ], [ %7, %if.end ] +// HIP-NEXT: %entry1 = phi ptr [ @__start_hip_offloading_entries, %entry ], [ %11, %if.end ] // HIP-NEXT: %1 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 0, i32 0 // HIP-NEXT: %addr = load ptr, ptr %1, align 8 // HIP-NEXT: %2 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 0, i32 1 @@ -176,16 +187,25 @@ // HIP-NEXT: %3 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 0, i32 2 // HIP-NEXT: %size = load i64, ptr %3, align 4 // HIP-NEXT: %4 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 0, i32 3 -// HIP-NEXT: %flag = load i32, ptr %4, align 4 -// HIP-NEXT: %5 = icmp eq i64 %size, 0 -// HIP-NEXT: br i1 %5, label %if.then, label %if.else +// HIP-NEXT: %flags = load i32, ptr %4, align 4 +// HIP-NEXT: %5 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 0, i32 4 +// HIP-NEXT: %textype = load i32, ptr %5, align 4 +// HIP-NEXT: %type = and i32 %flags, 7 +// HIP-NEXT: %6 = and i32 %flags, 8 +// HIP-NEXT: %extern = lshr i32 %6, 3 +// HIP-NEXT: %7 = and i32 %flags, 16 +// HIP-NEXT: %constant = lshr i32 %7, 4 +// HIP-NEXT: %8 = and i32 %flags, 32 +// HIP-NEXT: %normalized = lshr i32 %8, 5 +// HIP-NEXT: %9 = icmp eq i64 %size, 0 +// HIP-NEXT: br i1 %9, label %if.then, label %if.else // HIP: if.then: -// HIP-NEXT: %6 = call i32 @__hipRegisterFunction(ptr %0, ptr %addr, ptr %name, ptr %name, i32 -1, ptr null, ptr null, ptr null, ptr null, ptr null) +// HIP-NEXT: %10 = call i32 @__hipRegisterFunction(ptr %0, ptr %addr, ptr %name, ptr %name, i32 -1, ptr null, ptr null, ptr null, ptr null, ptr null) // HIP-NEXT: br label %if.end // HIP: if.else: -// HIP-NEXT: switch i32 %flag, label %if.end [ +// HIP-NEXT: switch i32 %type, label %if.end [ // HIP-NEXT: i32 0, label %sw.global // HIP-NEXT: i32 1, label %sw.managed // HIP-NEXT: i32 2, label %sw.surface @@ -193,22 +213,24 @@ // HIP-NEXT: ] // HIP: sw.global: -// HIP-NEXT: call void @__hipRegisterVar(ptr %0, ptr %addr, ptr %name, ptr %name, i32 0, i64 %size, i32 0, i32 0) +// HIP-NEXT: call void @__hipRegisterVar(ptr %0, ptr %addr, ptr %name, ptr %name, i32 %extern, i64 %size, i32 %constant, i32 0) // HIP-NEXT: br label %if.end // HIP: sw.managed: // HIP-NEXT: br label %if.end // HIP: sw.surface: +// HIP-NEXT: call void @__hipRegisterSurface(ptr %0, ptr %addr, ptr %name, ptr %name, i32 %textype, i32 %extern) // HIP-NEXT: br label %if.end // HIP: sw.texture: +// HIP-NEXT: call void @__hipRegisterTexture(ptr %0, ptr %addr, ptr %name, ptr %name, i32 %textype, i32 %normalized, i32 %extern) // HIP-NEXT: br label %if.end // HIP: if.end: -// HIP-NEXT: %7 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 1 -// HIP-NEXT: %8 = icmp eq ptr %7, @__stop_hip_offloading_entries -// HIP-NEXT: br i1 %8, label %while.end, label %while.entry +// HIP-NEXT: %11 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 1 +// HIP-NEXT: %12 = icmp eq ptr %11, @__stop_hip_offloading_entries +// HIP-NEXT: br i1 %12, label %while.end, label %while.entry // HIP: while.end: // HIP-NEXT: ret void diff --git a/clang/test/Driver/linker-wrapper.c b/clang/test/Driver/linker-wrapper.c index e82febd618231024ccb41384a93f5f4c1ba3a03d..b763a003452ba721cff3bb7248caa833ef6cf3dd 100644 --- a/clang/test/Driver/linker-wrapper.c +++ b/clang/test/Driver/linker-wrapper.c @@ -123,8 +123,8 @@ // RUN: --linker-path=/usr/bin/ld --device-linker=a --device-linker=nvptx64-nvidia-cuda=b -- \ // RUN: %t.o -o a.out 2>&1 | FileCheck %s --check-prefix=LINKER-ARGS -// LINKER-ARGS: clang{{.*}}--target=amdgcn-amd-amdhsa{{.*}}-Wl,a -// LINKER-ARGS: clang{{.*}}--target=nvptx64-nvidia-cuda{{.*}}-Wl,a -Wl,b +// LINKER-ARGS: clang{{.*}}--target=amdgcn-amd-amdhsa{{.*}}a +// LINKER-ARGS: clang{{.*}}--target=nvptx64-nvidia-cuda{{.*}}a b // RUN: not clang-linker-wrapper --dry-run --host-triple=x86_64-unknown-linux-gnu -ldummy \ // RUN: --linker-path=/usr/bin/ld --device-linker=a --device-linker=nvptx64-nvidia-cuda=b -- \ diff --git a/clang/test/Driver/range.c b/clang/test/Driver/range.c new file mode 100644 index 0000000000000000000000000000000000000000..8d456a997d6967e3371a8ac7289d95a7c46deec8 --- /dev/null +++ b/clang/test/Driver/range.c @@ -0,0 +1,39 @@ +// Test range options for complex multiplication and division. + +// RUN: %clang -### -target x86_64 -fcx-limited-range -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=LMTD %s + +// RUN: %clang -### -target x86_64 -fno-cx-limited-range -c %s 2>&1 \ +// RUN: | FileCheck %s + +// RUN: %clang -### -target x86_64 -fcx-fortran-rules -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=FRTRN %s + +// RUN: %clang -### -target x86_64 -fno-cx-fortran-rules -c %s 2>&1 \ +// RUN: | FileCheck %s + +// RUN: %clang -### -target x86_64 -fcx-limited-range \ +// RUN: -fcx-fortran-rules -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=WARN1 %s + +// RUN: %clang -### -target x86_64 -fcx-fortran-rules \ +// RUN: -fcx-limited-range -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=WARN2 %s + +// RUN: %clang -### -target x86_64 -ffast-math -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=LMTD %s + +// RUN: %clang -### -target x86_64 -ffast-math -fcx-limited-range -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=LMTD %s + +// RUN: %clang -### -target x86_64 -fcx-limited-range -ffast-math -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=LMTD %s + +// LMTD: -complex-range=limited +// LMTD-NOT: -complex-range=fortran +// CHECK-NOT: -complex-range=limited +// FRTRN: -complex-range=fortran +// FRTRN-NOT: -complex-range=limited +// CHECK-NOT: -complex-range=fortran +// WARN1: warning: overriding '-fcx-limited-range' option with '-fcx-fortran-rules' [-Woverriding-option] +// WARN2: warning: overriding '-fcx-fortran-rules' option with '-fcx-limited-range' [-Woverriding-option] diff --git a/clang/test/Driver/rocm-detect.hip b/clang/test/Driver/rocm-detect.hip index 947c4f995be171522d049ed9e28a4c703ee21ba1..3644f215a345b6ea5d10eef8675656b138acdfa6 100644 --- a/clang/test/Driver/rocm-detect.hip +++ b/clang/test/Driver/rocm-detect.hip @@ -78,39 +78,39 @@ // RUN: | FileCheck -check-prefixes=ROCM-ENV,HIP-PATH %s // Test detecting latest /opt/rocm-{release} directory. -// RUN: rm -rf %T/opt -// RUN: mkdir -p %T/opt -// RUN: cp -r %S/Inputs/rocm %T/opt/rocm-3.9.0-1234 -// RUN: cp -r %S/Inputs/rocm %T/opt/rocm-3.10.0 -// RUN: %clang -### --target=x86_64-linux-gnu --offload-arch=gfx1010 --sysroot=%T \ +// RUN: rm -rf %t/opt +// RUN: mkdir -p %t/opt +// RUN: cp -r %S/Inputs/rocm %t/opt/rocm-3.9.0-1234 +// RUN: cp -r %S/Inputs/rocm %t/opt/rocm-3.10.0 +// RUN: %clang -### --target=x86_64-linux-gnu --offload-arch=gfx1010 --sysroot=%t \ // RUN: --print-rocm-search-dirs %s 2>&1 \ // RUN: | FileCheck -check-prefixes=ROCM-REL %s -// Test ROCm installation built by SPACK by invoke clang at %T/rocm-spack/llvm-amdgpu-* +// Test ROCm installation built by SPACK by invoke clang at %t/rocm-spack/llvm-amdgpu-* // directory through a soft link. -// RUN: rm -rf %T/rocm-spack -// RUN: cp -r %S/Inputs/rocm-spack %T -// RUN: ln -fs %clang %T/rocm-spack/llvm-amdgpu-4.0.0-ieagcs7inf7runpyfvepqkurasoglq4z/bin/clang -// RUN: %T/rocm-spack/llvm-amdgpu-4.0.0-ieagcs7inf7runpyfvepqkurasoglq4z/bin/clang -### -v \ -// RUN: -resource-dir=%T/rocm-spack/llvm-amdgpu-4.0.0-ieagcs7inf7runpyfvepqkurasoglq4z/lib/clang \ +// RUN: rm -rf %t/rocm-spack +// RUN: cp -r %S/Inputs/rocm-spack %t +// RUN: ln -fs %clang %t/rocm-spack/llvm-amdgpu-4.0.0-ieagcs7inf7runpyfvepqkurasoglq4z/bin/clang +// RUN: %t/rocm-spack/llvm-amdgpu-4.0.0-ieagcs7inf7runpyfvepqkurasoglq4z/bin/clang -### -v \ +// RUN: -resource-dir=%t/rocm-spack/llvm-amdgpu-4.0.0-ieagcs7inf7runpyfvepqkurasoglq4z/lib/clang \ // RUN: -target x86_64-linux-gnu --cuda-gpu-arch=gfx900 --print-rocm-search-dirs %s 2>&1 \ // RUN: | FileCheck -check-prefixes=SPACK %s // Test SPACK installation with multiple hip and rocm-device-libs packages of the same // ROCm release. --hip-path and --rocm-device-lib-path can be used to specify them. -// RUN: cp -r %T/rocm-spack/hip-* %T/rocm-spack/hip-4.0.0-abcd -// RUN: %T/rocm-spack/llvm-amdgpu-4.0.0-ieagcs7inf7runpyfvepqkurasoglq4z/bin/clang -### -v \ +// RUN: cp -r %t/rocm-spack/hip-* %t/rocm-spack/hip-4.0.0-abcd +// RUN: %t/rocm-spack/llvm-amdgpu-4.0.0-ieagcs7inf7runpyfvepqkurasoglq4z/bin/clang -### -v \ // RUN: -target x86_64-linux-gnu --cuda-gpu-arch=gfx900 \ -// RUN: --hip-path=%T/rocm-spack/hip-4.0.0-abcd \ +// RUN: --hip-path=%t/rocm-spack/hip-4.0.0-abcd \ // RUN: %s 2>&1 | FileCheck -check-prefixes=SPACK-SET %s // Test invalid SPACK ROCm installation missing hip and rocm-device-libs packages. -// RUN: rm -rf %T/rocm-spack/hip-* -// RUN: rm -rf %T/rocm-spack/llvm-amdgpu-4.0.0-ieagcs7inf7runpyfvepqkurasoglq4z/amdgcn -// RUN: %T/rocm-spack/llvm-amdgpu-4.0.0-ieagcs7inf7runpyfvepqkurasoglq4z/bin/clang --version 2>&1 \ +// RUN: rm -rf %t/rocm-spack/hip-* +// RUN: rm -rf %t/rocm-spack/llvm-amdgpu-4.0.0-ieagcs7inf7runpyfvepqkurasoglq4z/amdgcn +// RUN: %t/rocm-spack/llvm-amdgpu-4.0.0-ieagcs7inf7runpyfvepqkurasoglq4z/bin/clang --version 2>&1 \ // RUN: | FileCheck -check-prefixes=SPACK-MISS-SILENT %s // GFX902-DEFAULTLIBS: error: cannot find ROCm device library for gfx902; provide its path via '--rocm-path' or '--rocm-device-lib-path', or pass '-nogpulib' to build without ROCm device library diff --git a/clang/test/ExtractAPI/language.c b/clang/test/ExtractAPI/language.c index 6facd18f5d98106bf4740181d436898571f87461..fe98626c84613e0dfcfd6c655f5a3c2b28eeab7a 100644 --- a/clang/test/ExtractAPI/language.c +++ b/clang/test/ExtractAPI/language.c @@ -4,29 +4,42 @@ // RUN: %t/c.reference.output.json.in >> %t/c.reference.output.json // RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \ // RUN: %t/objc.reference.output.json.in >> %t/objc.reference.output.json +// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \ +// RUN: %t/objcpp.reference.output.json.in >> %t/objcpp.reference.output.json -// RUN: %clang -extract-api -x c-header -target arm64-apple-macosx \ +// RUN: %clang_cc1 -extract-api -x c-header -triple arm64-apple-macosx \ // RUN: %t/c.h -o %t/c.output.json | FileCheck -allow-empty %s -// RUN: %clang -extract-api -x objective-c-header -target arm64-apple-macosx \ +// RUN: %clang_cc1 -extract-api -x objective-c-header -triple arm64-apple-macosx \ // RUN: %t/objc.h -o %t/objc.output.json | FileCheck -allow-empty %s +// RUN: %clang_cc1 -extract-api -x objective-c++-header -triple arm64-apple-macosx \ +// RUN: %t/objcpp.h -o %t/objcpp.output.json | FileCheck -allow-empty %s // Generator version is not consistent across test runs, normalize it. // RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \ // RUN: %t/c.output.json >> %t/c.output-normalized.json // RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \ // RUN: %t/objc.output.json >> %t/objc.output-normalized.json +// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \ +// RUN: %t/objcpp.output.json >> %t/objcpp.output-normalized.json // RUN: diff %t/c.reference.output.json %t/c.output-normalized.json // RUN: diff %t/objc.reference.output.json %t/objc.output-normalized.json +// RUN: diff %t/objcpp.reference.output.json %t/objcpp.output-normalized.json // CHECK-NOT: error: // CHECK-NOT: warning: //--- c.h char c; +///expected-no-diagnostics //--- objc.h char objc; +///expected-no-diagnostics + +//--- objcpp.h +char objcpp; +///expected-no-diagnostics //--- c.reference.output.json.in { @@ -196,3 +209,87 @@ char objc; } ] } +//--- objcpp.reference.output.json.in +{ + "metadata": { + "formatVersion": { + "major": 0, + "minor": 5, + "patch": 3 + }, + "generator": "?" + }, + "module": { + "name": "", + "platform": { + "architecture": "arm64", + "operatingSystem": { + "minimumVersion": { + "major": 11, + "minor": 0, + "patch": 0 + }, + "name": "macosx" + }, + "vendor": "apple" + } + }, + "relationships": [], + "symbols": [ + { + "accessLevel": "public", + "declarationFragments": [ + { + "kind": "typeIdentifier", + "preciseIdentifier": "c:C", + "spelling": "char" + }, + { + "kind": "text", + "spelling": " " + }, + { + "kind": "identifier", + "spelling": "objcpp" + }, + { + "kind": "text", + "spelling": ";" + } + ], + "identifier": { + "interfaceLanguage": "objective-c++", + "precise": "c:@objcpp" + }, + "kind": { + "displayName": "Global Variable", + "identifier": "objective-c++.var" + }, + "location": { + "position": { + "character": 5, + "line": 0 + }, + "uri": "file://INPUT_DIR/objcpp.h" + }, + "names": { + "navigator": [ + { + "kind": "identifier", + "spelling": "objcpp" + } + ], + "subHeading": [ + { + "kind": "identifier", + "spelling": "objcpp" + } + ], + "title": "objcpp" + }, + "pathComponents": [ + "objcpp" + ] + } + ] +} diff --git a/clang/test/Frontend/darwin-eabi.c b/clang/test/Frontend/darwin-eabi.c index 27471e6cfb0e6709e9c2fdc5f718de4ad6321837..9d62632891cbe69e494d4d569fc278d37ca28700 100644 --- a/clang/test/Frontend/darwin-eabi.c +++ b/clang/test/Frontend/darwin-eabi.c @@ -1,6 +1,6 @@ -// RUN: %clang -arch armv6m -dM -E %s | FileCheck %s -// RUN: %clang -arch armv7m -dM -E %s | FileCheck %s -// RUN: %clang -arch armv7em -dM -E %s | FileCheck %s +// RUN: %clang --target=armv6m-apple-darwin -dM -E %s | FileCheck %s +// RUN: %clang --target=armv7m-apple-darwin -dM -E %s | FileCheck %s +// RUN: %clang --target=armv7em-apple-darwin -dM -E %s | FileCheck %s // RUN: %clang_cc1 -triple thumbv7m-apple-unknown-macho -dM -E %s | FileCheck %s // CHECK-NOT: __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ diff --git a/clang/test/Frontend/sarif-diagnostics.cpp b/clang/test/Frontend/sarif-diagnostics.cpp index 9a4e686389a2ec1b32c52fdec2cc03bdec7d54ca..767c5802ca13d9e9da6d545493808b7e73088d01 100644 --- a/clang/test/Frontend/sarif-diagnostics.cpp +++ b/clang/test/Frontend/sarif-diagnostics.cpp @@ -64,5 +64,5 @@ void f1(t1 x, t1 y) { // CHECK: {"enabled":true,"level":"error","rank":50},"fullDescription":{"text":""},"id":"{{[0-9]+}}","name":""},{"defaultConfiguration": // CHECK: {"enabled":true,"level":"error","rank":50},"fullDescription":{"text":""},"id":"{{[0-9]+}}","name":""},{"defaultConfiguration": // CHECK: {"enabled":true,"level":"error","rank":50},"fullDescription": -// CHECK: {"text":""},"id":"{{[0-9]+}}","name":""}],"version":"{{[0-9]+\.[0-9]+\.[0-9]+}}"}}}],"version":"2.1.0"} -// CHECK: 2 warnings and 6 errors generated. \ No newline at end of file +// CHECK: {"text":""},"id":"{{[0-9]+}}","name":""}],"version":"{{[0-9]+\.[0-9]+\.[0-9]+[^" ]*}}"}}}],"version":"2.1.0"} +// CHECK: 2 warnings and 6 errors generated. diff --git a/clang/test/Headers/__clang_hip_math.hip b/clang/test/Headers/__clang_hip_math.hip index 68cbf86041e387d5e92e85be4274f3d7de348abd..fa13ddba425bdeb5c3004dc46ec8aa07f6e962ed 100644 --- a/clang/test/Headers/__clang_hip_math.hip +++ b/clang/test/Headers/__clang_hip_math.hip @@ -43,7 +43,7 @@ typedef unsigned long long uint64_t; // CHECK-NEXT: br i1 [[OR_COND_I]], label [[IF_THEN_I:%.*]], label [[CLEANUP_I]] // CHECK: if.then.i: // CHECK-NEXT: [[MUL_I:%.*]] = shl i64 [[__R_0_I]], 3 -// CHECK-NEXT: [[CONV5_I:%.*]] = sext i8 [[TMP0]] to i64 +// CHECK-NEXT: [[CONV5_I:%.*]] = zext nneg i8 [[TMP0]] to i64 // CHECK-NEXT: [[ADD_I:%.*]] = add i64 [[MUL_I]], -48 // CHECK-NEXT: [[SUB_I:%.*]] = add i64 [[ADD_I]], [[CONV5_I]] // CHECK-NEXT: [[INCDEC_PTR_I:%.*]] = getelementptr inbounds i8, ptr [[__TAGP_ADDR_0_I]], i64 1 @@ -75,7 +75,7 @@ extern "C" __device__ uint64_t test___make_mantissa_base8(const char *p) { // CHECK-NEXT: br i1 [[OR_COND_I]], label [[IF_THEN_I:%.*]], label [[CLEANUP_I]] // CHECK: if.then.i: // CHECK-NEXT: [[MUL_I:%.*]] = mul i64 [[__R_0_I]], 10 -// CHECK-NEXT: [[CONV5_I:%.*]] = sext i8 [[TMP0]] to i64 +// CHECK-NEXT: [[CONV5_I:%.*]] = zext nneg i8 [[TMP0]] to i64 // CHECK-NEXT: [[ADD_I:%.*]] = add i64 [[MUL_I]], -48 // CHECK-NEXT: [[SUB_I:%.*]] = add i64 [[ADD_I]], [[CONV5_I]] // CHECK-NEXT: [[INCDEC_PTR_I:%.*]] = getelementptr inbounds i8, ptr [[__TAGP_ADDR_0_I]], i64 1 @@ -116,7 +116,7 @@ extern "C" __device__ uint64_t test___make_mantissa_base10(const char *p) { // CHECK: if.end31.i: // CHECK-NEXT: [[DOTSINK:%.*]] = phi i64 [ -48, [[WHILE_BODY_I]] ], [ -87, [[IF_ELSE_I]] ], [ -55, [[IF_ELSE17_I]] ] // CHECK-NEXT: [[MUL24_I:%.*]] = shl i64 [[__R_0_I]], 4 -// CHECK-NEXT: [[CONV25_I:%.*]] = sext i8 [[TMP0]] to i64 +// CHECK-NEXT: [[CONV25_I:%.*]] = zext nneg i8 [[TMP0]] to i64 // CHECK-NEXT: [[ADD26_I:%.*]] = add i64 [[MUL24_I]], [[DOTSINK]] // CHECK-NEXT: [[ADD28_I:%.*]] = add i64 [[ADD26_I]], [[CONV25_I]] // CHECK-NEXT: [[INCDEC_PTR_I:%.*]] = getelementptr inbounds i8, ptr [[__TAGP_ADDR_0_I]], i64 1 @@ -169,7 +169,7 @@ extern "C" __device__ uint64_t test___make_mantissa_base16(const char *p) { // CHECK: if.end31.i.i: // CHECK-NEXT: [[DOTSINK:%.*]] = phi i64 [ -48, [[WHILE_BODY_I34_I]] ], [ -87, [[IF_ELSE_I_I]] ], [ -55, [[IF_ELSE17_I_I]] ] // CHECK-NEXT: [[MUL24_I_I:%.*]] = shl i64 [[__R_0_I32_I]], 4 -// CHECK-NEXT: [[CONV25_I_I:%.*]] = sext i8 [[TMP2]] to i64 +// CHECK-NEXT: [[CONV25_I_I:%.*]] = zext nneg i8 [[TMP2]] to i64 // CHECK-NEXT: [[ADD26_I_I:%.*]] = add i64 [[MUL24_I_I]], [[DOTSINK]] // CHECK-NEXT: [[ADD28_I_I:%.*]] = add i64 [[ADD26_I_I]], [[CONV25_I_I]] // CHECK-NEXT: [[INCDEC_PTR_I40_I:%.*]] = getelementptr inbounds i8, ptr [[__TAGP_ADDR_0_I31_I]], i64 1 @@ -191,7 +191,7 @@ extern "C" __device__ uint64_t test___make_mantissa_base16(const char *p) { // CHECK-NEXT: br i1 [[OR_COND_I_I]], label [[IF_THEN_I_I:%.*]], label [[CLEANUP_I_I]] // CHECK: if.then.i.i: // CHECK-NEXT: [[MUL_I_I:%.*]] = shl i64 [[__R_0_I_I]], 3 -// CHECK-NEXT: [[CONV5_I_I:%.*]] = sext i8 [[TMP6]] to i64 +// CHECK-NEXT: [[CONV5_I_I:%.*]] = zext nneg i8 [[TMP6]] to i64 // CHECK-NEXT: [[ADD_I_I:%.*]] = add i64 [[MUL_I_I]], -48 // CHECK-NEXT: [[SUB_I_I:%.*]] = add i64 [[ADD_I_I]], [[CONV5_I_I]] // CHECK-NEXT: [[INCDEC_PTR_I_I:%.*]] = getelementptr inbounds i8, ptr [[__TAGP_ADDR_0_I_I]], i64 1 @@ -212,7 +212,7 @@ extern "C" __device__ uint64_t test___make_mantissa_base16(const char *p) { // CHECK-NEXT: br i1 [[OR_COND_I19_I]], label [[IF_THEN_I24_I:%.*]], label [[CLEANUP_I20_I]] // CHECK: if.then.i24.i: // CHECK-NEXT: [[MUL_I25_I:%.*]] = mul i64 [[__R_0_I16_I]], 10 -// CHECK-NEXT: [[CONV5_I26_I:%.*]] = sext i8 [[TMP8]] to i64 +// CHECK-NEXT: [[CONV5_I26_I:%.*]] = zext nneg i8 [[TMP8]] to i64 // CHECK-NEXT: [[ADD_I27_I:%.*]] = add i64 [[MUL_I25_I]], -48 // CHECK-NEXT: [[SUB_I28_I:%.*]] = add i64 [[ADD_I27_I]], [[CONV5_I26_I]] // CHECK-NEXT: [[INCDEC_PTR_I29_I:%.*]] = getelementptr inbounds i8, ptr [[__TAGP_ADDR_0_I15_I]], i64 1 @@ -2395,7 +2395,7 @@ extern "C" __device__ double test_modf(double x, double* y) { // CHECK: if.end31.i.i.i: // CHECK-NEXT: [[DOTSINK:%.*]] = phi i64 [ -48, [[WHILE_BODY_I34_I_I]] ], [ -87, [[IF_ELSE_I_I_I]] ], [ -55, [[IF_ELSE17_I_I_I]] ] // CHECK-NEXT: [[MUL24_I_I_I:%.*]] = shl i64 [[__R_0_I32_I_I]], 4 -// CHECK-NEXT: [[CONV25_I_I_I:%.*]] = sext i8 [[TMP2]] to i64 +// CHECK-NEXT: [[CONV25_I_I_I:%.*]] = zext nneg i8 [[TMP2]] to i64 // CHECK-NEXT: [[ADD26_I_I_I:%.*]] = add i64 [[MUL24_I_I_I]], [[DOTSINK]] // CHECK-NEXT: [[ADD28_I_I_I:%.*]] = add i64 [[ADD26_I_I_I]], [[CONV25_I_I_I]] // CHECK-NEXT: [[INCDEC_PTR_I40_I_I:%.*]] = getelementptr inbounds i8, ptr [[__TAGP_ADDR_0_I31_I_I]], i64 1 @@ -2417,7 +2417,7 @@ extern "C" __device__ double test_modf(double x, double* y) { // CHECK-NEXT: br i1 [[OR_COND_I_I_I]], label [[IF_THEN_I_I_I:%.*]], label [[CLEANUP_I_I_I]] // CHECK: if.then.i.i.i: // CHECK-NEXT: [[MUL_I_I_I:%.*]] = shl i64 [[__R_0_I_I_I]], 3 -// CHECK-NEXT: [[CONV5_I_I_I:%.*]] = sext i8 [[TMP6]] to i64 +// CHECK-NEXT: [[CONV5_I_I_I:%.*]] = zext nneg i8 [[TMP6]] to i64 // CHECK-NEXT: [[ADD_I_I_I:%.*]] = add i64 [[MUL_I_I_I]], -48 // CHECK-NEXT: [[SUB_I_I_I:%.*]] = add i64 [[ADD_I_I_I]], [[CONV5_I_I_I]] // CHECK-NEXT: [[INCDEC_PTR_I_I_I:%.*]] = getelementptr inbounds i8, ptr [[__TAGP_ADDR_0_I_I_I]], i64 1 @@ -2438,7 +2438,7 @@ extern "C" __device__ double test_modf(double x, double* y) { // CHECK-NEXT: br i1 [[OR_COND_I19_I_I]], label [[IF_THEN_I24_I_I:%.*]], label [[CLEANUP_I20_I_I]] // CHECK: if.then.i24.i.i: // CHECK-NEXT: [[MUL_I25_I_I:%.*]] = mul i64 [[__R_0_I16_I_I]], 10 -// CHECK-NEXT: [[CONV5_I26_I_I:%.*]] = sext i8 [[TMP8]] to i64 +// CHECK-NEXT: [[CONV5_I26_I_I:%.*]] = zext nneg i8 [[TMP8]] to i64 // CHECK-NEXT: [[ADD_I27_I_I:%.*]] = add i64 [[MUL_I25_I_I]], -48 // CHECK-NEXT: [[SUB_I28_I_I:%.*]] = add i64 [[ADD_I27_I_I]], [[CONV5_I26_I_I]] // CHECK-NEXT: [[INCDEC_PTR_I29_I_I:%.*]] = getelementptr inbounds i8, ptr [[__TAGP_ADDR_0_I15_I_I]], i64 1 @@ -2494,7 +2494,7 @@ extern "C" __device__ float test_nanf(const char *tag) { // CHECK: if.end31.i.i.i: // CHECK-NEXT: [[DOTSINK:%.*]] = phi i64 [ -48, [[WHILE_BODY_I34_I_I]] ], [ -87, [[IF_ELSE_I_I_I]] ], [ -55, [[IF_ELSE17_I_I_I]] ] // CHECK-NEXT: [[MUL24_I_I_I:%.*]] = shl i64 [[__R_0_I32_I_I]], 4 -// CHECK-NEXT: [[CONV25_I_I_I:%.*]] = sext i8 [[TMP2]] to i64 +// CHECK-NEXT: [[CONV25_I_I_I:%.*]] = zext nneg i8 [[TMP2]] to i64 // CHECK-NEXT: [[ADD26_I_I_I:%.*]] = add i64 [[MUL24_I_I_I]], [[DOTSINK]] // CHECK-NEXT: [[ADD28_I_I_I:%.*]] = add i64 [[ADD26_I_I_I]], [[CONV25_I_I_I]] // CHECK-NEXT: [[INCDEC_PTR_I40_I_I:%.*]] = getelementptr inbounds i8, ptr [[__TAGP_ADDR_0_I31_I_I]], i64 1 @@ -2516,7 +2516,7 @@ extern "C" __device__ float test_nanf(const char *tag) { // CHECK-NEXT: br i1 [[OR_COND_I_I_I]], label [[IF_THEN_I_I_I:%.*]], label [[CLEANUP_I_I_I]] // CHECK: if.then.i.i.i: // CHECK-NEXT: [[MUL_I_I_I:%.*]] = shl i64 [[__R_0_I_I_I]], 3 -// CHECK-NEXT: [[CONV5_I_I_I:%.*]] = sext i8 [[TMP6]] to i64 +// CHECK-NEXT: [[CONV5_I_I_I:%.*]] = zext nneg i8 [[TMP6]] to i64 // CHECK-NEXT: [[ADD_I_I_I:%.*]] = add i64 [[MUL_I_I_I]], -48 // CHECK-NEXT: [[SUB_I_I_I:%.*]] = add i64 [[ADD_I_I_I]], [[CONV5_I_I_I]] // CHECK-NEXT: [[INCDEC_PTR_I_I_I:%.*]] = getelementptr inbounds i8, ptr [[__TAGP_ADDR_0_I_I_I]], i64 1 @@ -2537,7 +2537,7 @@ extern "C" __device__ float test_nanf(const char *tag) { // CHECK-NEXT: br i1 [[OR_COND_I19_I_I]], label [[IF_THEN_I24_I_I:%.*]], label [[CLEANUP_I20_I_I]] // CHECK: if.then.i24.i.i: // CHECK-NEXT: [[MUL_I25_I_I:%.*]] = mul i64 [[__R_0_I16_I_I]], 10 -// CHECK-NEXT: [[CONV5_I26_I_I:%.*]] = sext i8 [[TMP8]] to i64 +// CHECK-NEXT: [[CONV5_I26_I_I:%.*]] = zext nneg i8 [[TMP8]] to i64 // CHECK-NEXT: [[ADD_I27_I_I:%.*]] = add i64 [[MUL_I25_I_I]], -48 // CHECK-NEXT: [[SUB_I28_I_I:%.*]] = add i64 [[ADD_I27_I_I]], [[CONV5_I26_I_I]] // CHECK-NEXT: [[INCDEC_PTR_I29_I_I:%.*]] = getelementptr inbounds i8, ptr [[__TAGP_ADDR_0_I15_I_I]], i64 1 diff --git a/clang/test/Headers/arm-neon-header.c b/clang/test/Headers/arm-neon-header.c index 7e98d03dfc191932e63b2b5137a9705695912370..89bd5aaa2542090393f6fbcc6a73969d66ca5f65 100644 --- a/clang/test/Headers/arm-neon-header.c +++ b/clang/test/Headers/arm-neon-header.c @@ -22,7 +22,7 @@ // RUN: %clang -fsyntax-only -Wall -Werror -ffreestanding --target=aarch64-none-elf -march=armv8.2-a+fp16fml+crypto+dotprod -std=c11 -xc --sysroot=%S/Inputs -flax-vector-conversions=none %s // RUN: %clang -fsyntax-only -Wall -Werror -ffreestanding --target=aarch64_be-none-elf -march=armv8.2-a+fp16fml+crypto+dotprod -std=c11 -xc --sysroot=%S/Inputs -flax-vector-conversions=none %s -// RUN: %clang -fsyntax-only -Wall -Werror -ffreestanding --target=arm64-linux-gnu -arch +neon -std=c11 -xc --sysroot=%S/Inputs -flax-vector-conversions=none %s +// RUN: %clang -fsyntax-only -Wall -Werror -ffreestanding --target=arm64-linux-gnu -std=c11 -xc --sysroot=%S/Inputs -flax-vector-conversions=none %s // REQUIRES: aarch64-registered-target || arm-registered-target diff --git a/clang/test/Layout/ms-x86-declspec-empty_bases.cpp b/clang/test/Layout/ms-x86-declspec-empty_bases.cpp index cc13a980cb5dbd3bbe18b1d6dfa36eb34ae4ca4f..4738ce5720f7546de51f50a6e2f5ec36b016f9b7 100644 --- a/clang/test/Layout/ms-x86-declspec-empty_bases.cpp +++ b/clang/test/Layout/ms-x86-declspec-empty_bases.cpp @@ -264,3 +264,63 @@ int _ = sizeof(G); // CHECK-NEXT: | [sizeof=12, align=4, // CHECK-NEXT: | nvsize=12, nvalign=4] } + +namespace test5 { + +struct A { + int a; +}; +struct B { + int b; +}; +struct C {}; +struct __declspec(align(16)) D {}; +struct E { + [[msvc::no_unique_address]] C c; +}; +struct __declspec(empty_bases) X : A, D, B, C, E { +}; + +// CHECK: *** Dumping AST Record Layout +// CHECK-NEXT: 0 | struct test5::A +// CHECK-NEXT: 0 | int a +// CHECK-NEXT: | [sizeof=4, align=4, +// CHECK-NEXT: | nvsize=4, nvalign=4] + +// CHECK: *** Dumping AST Record Layout +// CHECK-NEXT: 0 | struct test5::D (empty) +// CHECK-NEXT: | [sizeof=16, align=16, +// CHECK-NEXT: | nvsize=0, nvalign=16] + +// CHECK: *** Dumping AST Record Layout +// CHECK-NEXT: 0 | struct test5::B +// CHECK-NEXT: 0 | int b +// CHECK-NEXT: | [sizeof=4, align=4, +// CHECK-NEXT: | nvsize=4, nvalign=4] + +// CHECK: *** Dumping AST Record Layout +// CHECK-NEXT: 0 | struct test5::C (empty) +// CHECK-NEXT: | [sizeof=1, align=1, +// CHECK-NEXT: | nvsize=0, nvalign=1] + +// CHECK: *** Dumping AST Record Layout +// CHECK-NEXT: 0 | struct test5::E (empty) +// CHECK-NEXT: 0 | struct test5::C c (empty) +// CHECK-NEXT: | [sizeof=1, align=1, +// CHECK-NEXT: | nvsize=1, nvalign=1] + +// CHECK: *** Dumping AST Record Layout +// CHECK-NEXT: 0 | struct test5::X +// CHECK-NEXT: 0 | struct test5::A (base) +// CHECK-NEXT: 0 | int a +// CHECK-NEXT: 0 | struct test5::D (base) (empty) +// CHECK-NEXT: 0 | struct test5::C (base) (empty) +// CHECK-NEXT: 4 | struct test5::B (base) +// CHECK-NEXT: 4 | int b +// CHECK-NEXT: 8 | struct test5::E (base) (empty) +// CHECK-NEXT: 8 | struct test5::C c (empty) +// CHECK-NEXT: | [sizeof=16, align=16, +// CHECK-NEXT: | nvsize=16, nvalign=16] + +int _ = sizeof(X); +} diff --git a/clang/test/Misc/pragma-attribute-supported-attributes-list.test b/clang/test/Misc/pragma-attribute-supported-attributes-list.test index dd91f4f88ad685bdcb56f3995b9859683536c1d1..bdfda430eea86c5ae5f4ff5a193ce225a29dabdf 100644 --- a/clang/test/Misc/pragma-attribute-supported-attributes-list.test +++ b/clang/test/Misc/pragma-attribute-supported-attributes-list.test @@ -23,6 +23,7 @@ // CHECK-NEXT: Availability ((SubjectMatchRule_record, SubjectMatchRule_enum, SubjectMatchRule_enum_constant, SubjectMatchRule_field, SubjectMatchRule_function, SubjectMatchRule_namespace, SubjectMatchRule_objc_category, SubjectMatchRule_objc_implementation, SubjectMatchRule_objc_interface, SubjectMatchRule_objc_method, SubjectMatchRule_objc_property, SubjectMatchRule_objc_protocol, SubjectMatchRule_record, SubjectMatchRule_type_alias, SubjectMatchRule_variable)) // CHECK-NEXT: AvailableOnlyInDefaultEvalMethod (SubjectMatchRule_type_alias) // CHECK-NEXT: BPFPreserveAccessIndex (SubjectMatchRule_record) +// CHECK-NEXT: BPFPreserveStaticOffset (SubjectMatchRule_record) // CHECK-NEXT: BTFDeclTag (SubjectMatchRule_variable, SubjectMatchRule_function, SubjectMatchRule_record, SubjectMatchRule_field, SubjectMatchRule_type_alias) // CHECK-NEXT: BuiltinAlias (SubjectMatchRule_function) // CHECK-NEXT: CFAuditedTransfer (SubjectMatchRule_function) @@ -89,6 +90,7 @@ // CHECK-NEXT: LoaderUninitialized (SubjectMatchRule_variable_is_global) // CHECK-NEXT: Lockable (SubjectMatchRule_record) // CHECK-NEXT: MIGServerRoutine (SubjectMatchRule_function, SubjectMatchRule_objc_method, SubjectMatchRule_block) +// CHECK-NEXT: MSConstexpr (SubjectMatchRule_function) // CHECK-NEXT: MSStruct (SubjectMatchRule_record) // CHECK-NEXT: MaybeUndef (SubjectMatchRule_variable_is_parameter) // CHECK-NEXT: MicroMips (SubjectMatchRule_function) diff --git a/clang/test/Misc/target-invalid-cpu-note.c b/clang/test/Misc/target-invalid-cpu-note.c index c7146e63add5f20df7de098da665244083e9ea49..e840a9208f5a4507f988618008bd1d1abd275709 100644 --- a/clang/test/Misc/target-invalid-cpu-note.c +++ b/clang/test/Misc/target-invalid-cpu-note.c @@ -1,7 +1,7 @@ // Use CHECK-NEXT instead of multiple CHECK-SAME to ensure we will fail if there is anything extra in the output. // RUN: not %clang_cc1 -triple armv5--- -target-cpu not-a-cpu -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix ARM // ARM: error: unknown target CPU 'not-a-cpu' -// ARM-NEXT: note: valid target CPU values are: arm8, arm810, strongarm, strongarm110, strongarm1100, strongarm1110, arm7tdmi, arm7tdmi-s, arm710t, arm720t, arm9, arm9tdmi, arm920, arm920t, arm922t, arm940t, ep9312, arm10tdmi, arm1020t, arm9e, arm946e-s, arm966e-s, arm968e-s, arm10e, arm1020e, arm1022e, arm926ej-s, arm1136j-s, arm1136jf-s, mpcore, mpcorenovfp, arm1176jz-s, arm1176jzf-s, arm1156t2-s, arm1156t2f-s, cortex-m0, cortex-m0plus, cortex-m1, sc000, cortex-a5, cortex-a7, cortex-a8, cortex-a9, cortex-a12, cortex-a15, cortex-a17, krait, cortex-r4, cortex-r4f, cortex-r5, cortex-r7, cortex-r8, cortex-r52, sc300, cortex-m3, cortex-m4, cortex-m7, cortex-m23, cortex-m33, cortex-m35p, cortex-m55, cortex-m85, cortex-a32, cortex-a35, cortex-a53, cortex-a55, cortex-a57, cortex-a72, cortex-a73, cortex-a75, cortex-a76, cortex-a76ae, cortex-a77, cortex-a78, cortex-a78c, cortex-a710, cortex-x1, cortex-x1c, neoverse-n1, neoverse-n2, neoverse-v1, cyclone, exynos-m3, exynos-m4, exynos-m5, kryo, iwmmxt, xscale, swift{{$}} +// ARM-NEXT: note: valid target CPU values are: arm8, arm810, strongarm, strongarm110, strongarm1100, strongarm1110, arm7tdmi, arm7tdmi-s, arm710t, arm720t, arm9, arm9tdmi, arm920, arm920t, arm922t, arm940t, ep9312, arm10tdmi, arm1020t, arm9e, arm946e-s, arm966e-s, arm968e-s, arm10e, arm1020e, arm1022e, arm926ej-s, arm1136j-s, arm1136jf-s, mpcore, mpcorenovfp, arm1176jz-s, arm1176jzf-s, arm1156t2-s, arm1156t2f-s, cortex-m0, cortex-m0plus, cortex-m1, sc000, cortex-a5, cortex-a7, cortex-a8, cortex-a9, cortex-a12, cortex-a15, cortex-a17, krait, cortex-r4, cortex-r4f, cortex-r5, cortex-r7, cortex-r8, cortex-r52, sc300, cortex-m3, cortex-m4, cortex-m7, cortex-m23, cortex-m33, cortex-m35p, cortex-m55, cortex-m85, cortex-m52, cortex-a32, cortex-a35, cortex-a53, cortex-a55, cortex-a57, cortex-a72, cortex-a73, cortex-a75, cortex-a76, cortex-a76ae, cortex-a77, cortex-a78, cortex-a78c, cortex-a710, cortex-x1, cortex-x1c, neoverse-n1, neoverse-n2, neoverse-v1, cyclone, exynos-m3, exynos-m4, exynos-m5, kryo, iwmmxt, xscale, swift{{$}} // RUN: not %clang_cc1 -triple arm64--- -target-cpu not-a-cpu -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix AARCH64 // AARCH64: error: unknown target CPU 'not-a-cpu' @@ -29,7 +29,7 @@ // RUN: not %clang_cc1 -triple nvptx--- -target-cpu not-a-cpu -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix NVPTX // NVPTX: error: unknown target CPU 'not-a-cpu' -// NVPTX-NEXT: note: valid target CPU values are: sm_20, sm_21, sm_30, sm_32, sm_35, sm_37, sm_50, sm_52, sm_53, sm_60, sm_61, sm_62, sm_70, sm_72, sm_75, sm_80, sm_86, sm_87, sm_89, sm_90, gfx600, gfx601, gfx602, gfx700, gfx701, gfx702, gfx703, gfx704, gfx705, gfx801, gfx802, gfx803, gfx805, gfx810, gfx900, gfx902, gfx904, gfx906, gfx908, gfx909, gfx90a, gfx90c, gfx940, gfx941, gfx942, gfx1010, gfx1011, gfx1012, gfx1013, gfx1030, gfx1031, gfx1032, gfx1033, gfx1034, gfx1035, gfx1036, gfx1100, gfx1101, gfx1102, gfx1103, gfx1150, gfx1151, gfx1200, gfx1201{{$}} +// NVPTX-NEXT: note: valid target CPU values are: sm_20, sm_21, sm_30, sm_32, sm_35, sm_37, sm_50, sm_52, sm_53, sm_60, sm_61, sm_62, sm_70, sm_72, sm_75, sm_80, sm_86, sm_87, sm_89, sm_90, sm_90a, gfx600, gfx601, gfx602, gfx700, gfx701, gfx702, gfx703, gfx704, gfx705, gfx801, gfx802, gfx803, gfx805, gfx810, gfx900, gfx902, gfx904, gfx906, gfx908, gfx909, gfx90a, gfx90c, gfx940, gfx941, gfx942, gfx1010, gfx1011, gfx1012, gfx1013, gfx1030, gfx1031, gfx1032, gfx1033, gfx1034, gfx1035, gfx1036, gfx1100, gfx1101, gfx1102, gfx1103, gfx1150, gfx1151, gfx1200, gfx1201{{$}} // RUN: not %clang_cc1 -triple r600--- -target-cpu not-a-cpu -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix R600 // R600: error: unknown target CPU 'not-a-cpu' diff --git a/clang/test/Modules/decl-params-determinisim.m b/clang/test/Modules/decl-params-determinisim.m index 351403d9af947e2f43f5c1bfef0a78578b3287ef..9cf37ac4334cf103a14ce09902a629d976420c45 100644 --- a/clang/test/Modules/decl-params-determinisim.m +++ b/clang/test/Modules/decl-params-determinisim.m @@ -28,23 +28,23 @@ // CHECK: +struct S { + T f; + S(T a) : f(a) {} + S() : f() {} + operator T() { return T(); } + ~S() {} +}; + +template +T tmain() { + S test; + T t_var = T(); + T vec[] = {1, 2}; + S s_arr[] = {1, 2}; + S &var = test; +#pragma omp taskloop simd private(t_var, vec, s_arr, s_arr, var, var) + for (int i = 0; i < 2; ++i) { + vec[i] = t_var; + s_arr[i] = var; + } + return T(); +} + +int main() { + static int svar; + volatile double g; + volatile double &g1 = g; + + #ifdef LAMBDA + [&]() { + static float sfvar; + +#pragma omp taskloop simd private(g, g1, svar, sfvar) + for (int i = 0; i < 2; ++i) { + g = 1; + g1 = 1; + svar = 3; + sfvar = 4.0; + [&]() { + g = 2; + g1 = 2; + svar = 4; + sfvar = 8.0; + + }(); + } + }(); + return 0; + #else + S test; + int t_var = 0; + int vec[] = {1, 2}; + S s_arr[] = {1, 2}; + S &var = test; + +#pragma omp taskloop simd private(t_var, vec, s_arr, s_arr, var, var, svar) + for (int i = 0; i < 2; ++i) { + vec[i] = t_var; + s_arr[i] = var; + } + int i; + +#pragma omp taskloop simd + for (i = 0; i < 2; ++i) { + ; + } + return tmain(); + #endif +} + + + + + + +#endif +// CHECK1-LABEL: define {{[^@]+}}@main +// CHECK1-SAME: () #[[ATTR0:[0-9]+]] { +// CHECK1-NEXT: entry: +// CHECK1-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 +// CHECK1-NEXT: [[G:%.*]] = alloca double, align 8 +// CHECK1-NEXT: [[G1:%.*]] = alloca ptr, align 8 +// CHECK1-NEXT: [[REF_TMP:%.*]] = alloca [[CLASS_ANON:%.*]], align 8 +// CHECK1-NEXT: store i32 0, ptr [[RETVAL]], align 4 +// CHECK1-NEXT: store ptr [[G]], ptr [[G1]], align 8 +// CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[CLASS_ANON]], ptr [[REF_TMP]], i32 0, i32 0 +// CHECK1-NEXT: store ptr [[G]], ptr [[TMP0]], align 8 +// CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[CLASS_ANON]], ptr [[REF_TMP]], i32 0, i32 1 +// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[G1]], align 8 +// CHECK1-NEXT: store ptr [[TMP2]], ptr [[TMP1]], align 8 +// CHECK1-NEXT: call void @"_ZZ4mainENK3$_0clEv"(ptr noundef nonnull align 8 dereferenceable(16) [[REF_TMP]]) +// CHECK1-NEXT: ret i32 0 +// +// +// CHECK1-LABEL: define {{[^@]+}}@.omp_task_privates_map. +// CHECK1-SAME: (ptr noalias noundef [[TMP0:%.*]], ptr noalias noundef [[TMP1:%.*]], ptr noalias noundef [[TMP2:%.*]], ptr noalias noundef [[TMP3:%.*]], ptr noalias noundef [[TMP4:%.*]]) #[[ATTR4:[0-9]+]] { +// CHECK1-NEXT: entry: +// CHECK1-NEXT: [[DOTADDR:%.*]] = alloca ptr, align 8 +// CHECK1-NEXT: [[DOTADDR1:%.*]] = alloca ptr, align 8 +// CHECK1-NEXT: [[DOTADDR2:%.*]] = alloca ptr, align 8 +// CHECK1-NEXT: [[DOTADDR3:%.*]] = alloca ptr, align 8 +// CHECK1-NEXT: [[DOTADDR4:%.*]] = alloca ptr, align 8 +// CHECK1-NEXT: store ptr [[TMP0]], ptr [[DOTADDR]], align 8 +// CHECK1-NEXT: store ptr [[TMP1]], ptr [[DOTADDR1]], align 8 +// CHECK1-NEXT: store ptr [[TMP2]], ptr [[DOTADDR2]], align 8 +// CHECK1-NEXT: store ptr [[TMP3]], ptr [[DOTADDR3]], align 8 +// CHECK1-NEXT: store ptr [[TMP4]], ptr [[DOTADDR4]], align 8 +// CHECK1-NEXT: [[TMP5:%.*]] = load ptr, ptr [[DOTADDR]], align 8 +// CHECK1-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT__KMP_PRIVATES_T:%.*]], ptr [[TMP5]], i32 0, i32 0 +// CHECK1-NEXT: [[TMP7:%.*]] = load ptr, ptr [[DOTADDR1]], align 8 +// CHECK1-NEXT: store ptr [[TMP6]], ptr [[TMP7]], align 8 +// CHECK1-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT__KMP_PRIVATES_T]], ptr [[TMP5]], i32 0, i32 1 +// CHECK1-NEXT: [[TMP9:%.*]] = load ptr, ptr [[DOTADDR2]], align 8 +// CHECK1-NEXT: store ptr [[TMP8]], ptr [[TMP9]], align 8 +// CHECK1-NEXT: [[TMP10:%.*]] = getelementptr inbounds [[STRUCT__KMP_PRIVATES_T]], ptr [[TMP5]], i32 0, i32 2 +// CHECK1-NEXT: [[TMP11:%.*]] = load ptr, ptr [[DOTADDR3]], align 8 +// CHECK1-NEXT: store ptr [[TMP10]], ptr [[TMP11]], align 8 +// CHECK1-NEXT: [[TMP12:%.*]] = getelementptr inbounds [[STRUCT__KMP_PRIVATES_T]], ptr [[TMP5]], i32 0, i32 3 +// CHECK1-NEXT: [[TMP13:%.*]] = load ptr, ptr [[DOTADDR4]], align 8 +// CHECK1-NEXT: store ptr [[TMP12]], ptr [[TMP13]], align 8 +// CHECK1-NEXT: ret void +// +// +// CHECK1-LABEL: define {{[^@]+}}@.omp_task_entry. +// CHECK1-SAME: (i32 noundef signext [[TMP0:%.*]], ptr noalias noundef [[TMP1:%.*]]) #[[ATTR5:[0-9]+]] { +// CHECK1-NEXT: entry: +// CHECK1-NEXT: [[DOTGLOBAL_TID__ADDR_I:%.*]] = alloca i32, align 4 +// CHECK1-NEXT: [[DOTPART_ID__ADDR_I:%.*]] = alloca ptr, align 8 +// CHECK1-NEXT: [[DOTPRIVATES__ADDR_I:%.*]] = alloca ptr, align 8 +// CHECK1-NEXT: [[DOTCOPY_FN__ADDR_I:%.*]] = alloca ptr, align 8 +// CHECK1-NEXT: [[DOTTASK_T__ADDR_I:%.*]] = alloca ptr, align 8 +// CHECK1-NEXT: [[DOTLB__ADDR_I:%.*]] = alloca i64, align 8 +// CHECK1-NEXT: [[DOTUB__ADDR_I:%.*]] = alloca i64, align 8 +// CHECK1-NEXT: [[DOTST__ADDR_I:%.*]] = alloca i64, align 8 +// CHECK1-NEXT: [[DOTLITER__ADDR_I:%.*]] = alloca i32, align 4 +// CHECK1-NEXT: [[DOTREDUCTIONS__ADDR_I:%.*]] = alloca ptr, align 8 +// CHECK1-NEXT: [[__CONTEXT_ADDR_I:%.*]] = alloca ptr, align 8 +// CHECK1-NEXT: [[DOTPRIV_PTR_ADDR_I:%.*]] = alloca ptr, align 8 +// CHECK1-NEXT: [[DOTPRIV_PTR_ADDR1_I:%.*]] = alloca ptr, align 8 +// CHECK1-NEXT: [[DOTPRIV_PTR_ADDR2_I:%.*]] = alloca ptr, align 8 +// CHECK1-NEXT: [[DOTPRIV_PTR_ADDR3_I:%.*]] = alloca ptr, align 8 +// CHECK1-NEXT: [[TMP_I:%.*]] = alloca ptr, align 8 +// CHECK1-NEXT: [[TMP5_I:%.*]] = alloca ptr, align 8 +// CHECK1-NEXT: [[I_I:%.*]] = alloca i32, align 4 +// CHECK1-NEXT: [[DOTOMP_IV_I:%.*]] = alloca i32, align 4 +// CHECK1-NEXT: [[REF_TMP_I:%.*]] = alloca [[CLASS_ANON_0:%.*]], align 8 +// CHECK1-NEXT: [[DOTADDR:%.*]] = alloca i32, align 4 +// CHECK1-NEXT: [[DOTADDR1:%.*]] = alloca ptr, align 8 +// CHECK1-NEXT: store i32 [[TMP0]], ptr [[DOTADDR]], align 4 +// CHECK1-NEXT: store ptr [[TMP1]], ptr [[DOTADDR1]], align 8 +// CHECK1-NEXT: [[TMP2:%.*]] = load i32, ptr [[DOTADDR]], align 4 +// CHECK1-NEXT: [[TMP3:%.*]] = load ptr, ptr [[DOTADDR1]], align 8 +// CHECK1-NEXT: [[TMP4:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T_WITH_PRIVATES:%.*]], ptr [[TMP3]], i32 0, i32 0 +// CHECK1-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T:%.*]], ptr [[TMP4]], i32 0, i32 2 +// CHECK1-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP4]], i32 0, i32 0 +// CHECK1-NEXT: [[TMP7:%.*]] = load ptr, ptr [[TMP6]], align 8 +// CHECK1-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T_WITH_PRIVATES]], ptr [[TMP3]], i32 0, i32 1 +// CHECK1-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP4]], i32 0, i32 5 +// CHECK1-NEXT: [[TMP10:%.*]] = load i64, ptr [[TMP9]], align 8 +// CHECK1-NEXT: [[TMP11:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP4]], i32 0, i32 6 +// CHECK1-NEXT: [[TMP12:%.*]] = load i64, ptr [[TMP11]], align 8 +// CHECK1-NEXT: [[TMP13:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP4]], i32 0, i32 7 +// CHECK1-NEXT: [[TMP14:%.*]] = load i64, ptr [[TMP13]], align 8 +// CHECK1-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP4]], i32 0, i32 8 +// CHECK1-NEXT: [[TMP16:%.*]] = load i32, ptr [[TMP15]], align 8 +// CHECK1-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP4]], i32 0, i32 9 +// CHECK1-NEXT: [[TMP18:%.*]] = load ptr, ptr [[TMP17]], align 8 +// CHECK1-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META3:![0-9]+]]) +// CHECK1-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META6:![0-9]+]]) +// CHECK1-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META8:![0-9]+]]) +// CHECK1-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META10:![0-9]+]]) +// CHECK1-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META12:![0-9]+]]) +// CHECK1-NEXT: store i32 [[TMP2]], ptr [[DOTGLOBAL_TID__ADDR_I]], align 4, !noalias [[META14:![0-9]+]] +// CHECK1-NEXT: store ptr [[TMP5]], ptr [[DOTPART_ID__ADDR_I]], align 8, !noalias [[META14]] +// CHECK1-NEXT: store ptr [[TMP8]], ptr [[DOTPRIVATES__ADDR_I]], align 8, !noalias [[META14]] +// CHECK1-NEXT: store ptr @.omp_task_privates_map., ptr [[DOTCOPY_FN__ADDR_I]], align 8, !noalias [[META14]] +// CHECK1-NEXT: store ptr [[TMP3]], ptr [[DOTTASK_T__ADDR_I]], align 8, !noalias [[META14]] +// CHECK1-NEXT: store i64 [[TMP10]], ptr [[DOTLB__ADDR_I]], align 8, !noalias [[META14]] +// CHECK1-NEXT: store i64 [[TMP12]], ptr [[DOTUB__ADDR_I]], align 8, !noalias [[META14]] +// CHECK1-NEXT: store i64 [[TMP14]], ptr [[DOTST__ADDR_I]], align 8, !noalias [[META14]] +// CHECK1-NEXT: store i32 [[TMP16]], ptr [[DOTLITER__ADDR_I]], align 4, !noalias [[META14]] +// CHECK1-NEXT: store ptr [[TMP18]], ptr [[DOTREDUCTIONS__ADDR_I]], align 8, !noalias [[META14]] +// CHECK1-NEXT: store ptr [[TMP7]], ptr [[__CONTEXT_ADDR_I]], align 8, !noalias [[META14]] +// CHECK1-NEXT: [[TMP19:%.*]] = load ptr, ptr [[__CONTEXT_ADDR_I]], align 8, !noalias [[META14]] +// CHECK1-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTCOPY_FN__ADDR_I]], align 8, !noalias [[META14]] +// CHECK1-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTPRIVATES__ADDR_I]], align 8, !noalias [[META14]] +// CHECK1-NEXT: call void [[TMP20]](ptr [[TMP21]], ptr [[DOTPRIV_PTR_ADDR_I]], ptr [[DOTPRIV_PTR_ADDR1_I]], ptr [[DOTPRIV_PTR_ADDR2_I]], ptr [[DOTPRIV_PTR_ADDR3_I]]) #[[ATTR2:[0-9]+]] +// CHECK1-NEXT: [[TMP22:%.*]] = load ptr, ptr [[DOTPRIV_PTR_ADDR_I]], align 8, !noalias [[META14]] +// CHECK1-NEXT: [[TMP23:%.*]] = load ptr, ptr [[DOTPRIV_PTR_ADDR1_I]], align 8, !noalias [[META14]] +// CHECK1-NEXT: store ptr [[TMP23]], ptr [[TMP_I]], align 8, !noalias [[META14]] +// CHECK1-NEXT: [[TMP24:%.*]] = load ptr, ptr [[DOTPRIV_PTR_ADDR2_I]], align 8, !noalias [[META14]] +// CHECK1-NEXT: [[TMP25:%.*]] = load ptr, ptr [[DOTPRIV_PTR_ADDR3_I]], align 8, !noalias [[META14]] +// CHECK1-NEXT: store ptr undef, ptr [[TMP5_I]], align 8, !noalias [[META14]] +// CHECK1-NEXT: [[TMP26:%.*]] = load i64, ptr [[DOTLB__ADDR_I]], align 8, !noalias [[META14]] +// CHECK1-NEXT: [[CONV_I:%.*]] = trunc i64 [[TMP26]] to i32 +// CHECK1-NEXT: store i32 [[CONV_I]], ptr [[DOTOMP_IV_I]], align 4, !noalias [[META14]] +// CHECK1-NEXT: br label [[OMP_INNER_FOR_COND_I:%.*]] +// CHECK1: omp.inner.for.cond.i: +// CHECK1-NEXT: [[TMP27:%.*]] = load i32, ptr [[DOTOMP_IV_I]], align 4, !noalias [[META14]], !llvm.access.group [[ACC_GRP15:![0-9]+]] +// CHECK1-NEXT: [[CONV6_I:%.*]] = sext i32 [[TMP27]] to i64 +// CHECK1-NEXT: [[TMP28:%.*]] = load i64, ptr [[DOTUB__ADDR_I]], align 8, !noalias [[META14]], !llvm.access.group [[ACC_GRP15]] +// CHECK1-NEXT: [[CMP_I:%.*]] = icmp ule i64 [[CONV6_I]], [[TMP28]] +// CHECK1-NEXT: br i1 [[CMP_I]], label [[OMP_INNER_FOR_BODY_I:%.*]], label [[DOTOMP_OUTLINED__EXIT:%.*]] +// CHECK1: omp.inner.for.body.i: +// CHECK1-NEXT: [[TMP29:%.*]] = load i32, ptr [[DOTOMP_IV_I]], align 4, !noalias [[META14]], !llvm.access.group [[ACC_GRP15]] +// CHECK1-NEXT: store i32 [[TMP29]], ptr [[I_I]], align 4, !noalias [[META14]], !llvm.access.group [[ACC_GRP15]] +// CHECK1-NEXT: store double 1.000000e+00, ptr [[TMP22]], align 8, !llvm.access.group [[ACC_GRP15]] +// CHECK1-NEXT: [[TMP30:%.*]] = load ptr, ptr [[TMP_I]], align 8, !noalias [[META14]], !llvm.access.group [[ACC_GRP15]] +// CHECK1-NEXT: store volatile double 1.000000e+00, ptr [[TMP30]], align 8, !llvm.access.group [[ACC_GRP15]] +// CHECK1-NEXT: store i32 3, ptr [[TMP24]], align 4, !llvm.access.group [[ACC_GRP15]] +// CHECK1-NEXT: store float 4.000000e+00, ptr [[TMP25]], align 4, !llvm.access.group [[ACC_GRP15]] +// CHECK1-NEXT: store ptr [[TMP22]], ptr [[REF_TMP_I]], align 8, !noalias [[META14]], !llvm.access.group [[ACC_GRP15]] +// CHECK1-NEXT: [[TMP31:%.*]] = getelementptr inbounds [[CLASS_ANON_0]], ptr [[REF_TMP_I]], i32 0, i32 1 +// CHECK1-NEXT: [[TMP32:%.*]] = load ptr, ptr [[TMP_I]], align 8, !noalias [[META14]], !llvm.access.group [[ACC_GRP15]] +// CHECK1-NEXT: store ptr [[TMP32]], ptr [[TMP31]], align 8, !noalias [[META14]], !llvm.access.group [[ACC_GRP15]] +// CHECK1-NEXT: [[TMP33:%.*]] = getelementptr inbounds [[CLASS_ANON_0]], ptr [[REF_TMP_I]], i32 0, i32 2 +// CHECK1-NEXT: store ptr [[TMP24]], ptr [[TMP33]], align 8, !noalias [[META14]], !llvm.access.group [[ACC_GRP15]] +// CHECK1-NEXT: [[TMP34:%.*]] = getelementptr inbounds [[CLASS_ANON_0]], ptr [[REF_TMP_I]], i32 0, i32 3 +// CHECK1-NEXT: store ptr [[TMP25]], ptr [[TMP34]], align 8, !noalias [[META14]], !llvm.access.group [[ACC_GRP15]] +// CHECK1-NEXT: call void @"_ZZZ4mainENK3$_0clEvENKUlvE_clEv"(ptr noundef nonnull align 8 dereferenceable(32) [[REF_TMP_I]]), !llvm.access.group [[ACC_GRP15]] +// CHECK1-NEXT: [[TMP35:%.*]] = load i32, ptr [[DOTOMP_IV_I]], align 4, !noalias [[META14]], !llvm.access.group [[ACC_GRP15]] +// CHECK1-NEXT: [[ADD7_I:%.*]] = add nsw i32 [[TMP35]], 1 +// CHECK1-NEXT: store i32 [[ADD7_I]], ptr [[DOTOMP_IV_I]], align 4, !noalias [[META14]], !llvm.access.group [[ACC_GRP15]] +// CHECK1-NEXT: br label [[OMP_INNER_FOR_COND_I]], !llvm.loop [[LOOP16:![0-9]+]] +// CHECK1: .omp_outlined..exit: +// CHECK1-NEXT: ret i32 0 +// +// +// CHECK3-LABEL: define {{[^@]+}}@main +// CHECK3-SAME: () #[[ATTR0:[0-9]+]] { +// CHECK3-NEXT: entry: +// CHECK3-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 +// CHECK3-NEXT: [[G:%.*]] = alloca double, align 8 +// CHECK3-NEXT: [[G1:%.*]] = alloca ptr, align 4 +// CHECK3-NEXT: [[REF_TMP:%.*]] = alloca [[CLASS_ANON:%.*]], align 4 +// CHECK3-NEXT: store i32 0, ptr [[RETVAL]], align 4 +// CHECK3-NEXT: store ptr [[G]], ptr [[G1]], align 4 +// CHECK3-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[CLASS_ANON]], ptr [[REF_TMP]], i32 0, i32 0 +// CHECK3-NEXT: store ptr [[G]], ptr [[TMP0]], align 4 +// CHECK3-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[CLASS_ANON]], ptr [[REF_TMP]], i32 0, i32 1 +// CHECK3-NEXT: [[TMP2:%.*]] = load ptr, ptr [[G1]], align 4 +// CHECK3-NEXT: store ptr [[TMP2]], ptr [[TMP1]], align 4 +// CHECK3-NEXT: call void @"_ZZ4mainENK3$_0clEv"(ptr noundef nonnull align 4 dereferenceable(8) [[REF_TMP]]) +// CHECK3-NEXT: ret i32 0 +// +// +// CHECK3-LABEL: define {{[^@]+}}@.omp_task_privates_map. +// CHECK3-SAME: (ptr noalias noundef [[TMP0:%.*]], ptr noalias noundef [[TMP1:%.*]], ptr noalias noundef [[TMP2:%.*]], ptr noalias noundef [[TMP3:%.*]], ptr noalias noundef [[TMP4:%.*]]) #[[ATTR4:[0-9]+]] { +// CHECK3-NEXT: entry: +// CHECK3-NEXT: [[DOTADDR:%.*]] = alloca ptr, align 4 +// CHECK3-NEXT: [[DOTADDR1:%.*]] = alloca ptr, align 4 +// CHECK3-NEXT: [[DOTADDR2:%.*]] = alloca ptr, align 4 +// CHECK3-NEXT: [[DOTADDR3:%.*]] = alloca ptr, align 4 +// CHECK3-NEXT: [[DOTADDR4:%.*]] = alloca ptr, align 4 +// CHECK3-NEXT: store ptr [[TMP0]], ptr [[DOTADDR]], align 4 +// CHECK3-NEXT: store ptr [[TMP1]], ptr [[DOTADDR1]], align 4 +// CHECK3-NEXT: store ptr [[TMP2]], ptr [[DOTADDR2]], align 4 +// CHECK3-NEXT: store ptr [[TMP3]], ptr [[DOTADDR3]], align 4 +// CHECK3-NEXT: store ptr [[TMP4]], ptr [[DOTADDR4]], align 4 +// CHECK3-NEXT: [[TMP5:%.*]] = load ptr, ptr [[DOTADDR]], align 4 +// CHECK3-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT__KMP_PRIVATES_T:%.*]], ptr [[TMP5]], i32 0, i32 0 +// CHECK3-NEXT: [[TMP7:%.*]] = load ptr, ptr [[DOTADDR1]], align 4 +// CHECK3-NEXT: store ptr [[TMP6]], ptr [[TMP7]], align 4 +// CHECK3-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT__KMP_PRIVATES_T]], ptr [[TMP5]], i32 0, i32 1 +// CHECK3-NEXT: [[TMP9:%.*]] = load ptr, ptr [[DOTADDR2]], align 4 +// CHECK3-NEXT: store ptr [[TMP8]], ptr [[TMP9]], align 4 +// CHECK3-NEXT: [[TMP10:%.*]] = getelementptr inbounds [[STRUCT__KMP_PRIVATES_T]], ptr [[TMP5]], i32 0, i32 2 +// CHECK3-NEXT: [[TMP11:%.*]] = load ptr, ptr [[DOTADDR3]], align 4 +// CHECK3-NEXT: store ptr [[TMP10]], ptr [[TMP11]], align 4 +// CHECK3-NEXT: [[TMP12:%.*]] = getelementptr inbounds [[STRUCT__KMP_PRIVATES_T]], ptr [[TMP5]], i32 0, i32 3 +// CHECK3-NEXT: [[TMP13:%.*]] = load ptr, ptr [[DOTADDR4]], align 4 +// CHECK3-NEXT: store ptr [[TMP12]], ptr [[TMP13]], align 4 +// CHECK3-NEXT: ret void +// +// +// CHECK3-LABEL: define {{[^@]+}}@.omp_task_entry. +// CHECK3-SAME: (i32 noundef [[TMP0:%.*]], ptr noalias noundef [[TMP1:%.*]]) #[[ATTR5:[0-9]+]] { +// CHECK3-NEXT: entry: +// CHECK3-NEXT: [[DOTGLOBAL_TID__ADDR_I:%.*]] = alloca i32, align 4 +// CHECK3-NEXT: [[DOTPART_ID__ADDR_I:%.*]] = alloca ptr, align 4 +// CHECK3-NEXT: [[DOTPRIVATES__ADDR_I:%.*]] = alloca ptr, align 4 +// CHECK3-NEXT: [[DOTCOPY_FN__ADDR_I:%.*]] = alloca ptr, align 4 +// CHECK3-NEXT: [[DOTTASK_T__ADDR_I:%.*]] = alloca ptr, align 4 +// CHECK3-NEXT: [[DOTLB__ADDR_I:%.*]] = alloca i64, align 8 +// CHECK3-NEXT: [[DOTUB__ADDR_I:%.*]] = alloca i64, align 8 +// CHECK3-NEXT: [[DOTST__ADDR_I:%.*]] = alloca i64, align 8 +// CHECK3-NEXT: [[DOTLITER__ADDR_I:%.*]] = alloca i32, align 4 +// CHECK3-NEXT: [[DOTREDUCTIONS__ADDR_I:%.*]] = alloca ptr, align 4 +// CHECK3-NEXT: [[__CONTEXT_ADDR_I:%.*]] = alloca ptr, align 4 +// CHECK3-NEXT: [[DOTPRIV_PTR_ADDR_I:%.*]] = alloca ptr, align 4 +// CHECK3-NEXT: [[DOTPRIV_PTR_ADDR1_I:%.*]] = alloca ptr, align 4 +// CHECK3-NEXT: [[DOTPRIV_PTR_ADDR2_I:%.*]] = alloca ptr, align 4 +// CHECK3-NEXT: [[DOTPRIV_PTR_ADDR3_I:%.*]] = alloca ptr, align 4 +// CHECK3-NEXT: [[TMP_I:%.*]] = alloca ptr, align 4 +// CHECK3-NEXT: [[TMP5_I:%.*]] = alloca ptr, align 4 +// CHECK3-NEXT: [[I_I:%.*]] = alloca i32, align 4 +// CHECK3-NEXT: [[DOTOMP_IV_I:%.*]] = alloca i32, align 4 +// CHECK3-NEXT: [[REF_TMP_I:%.*]] = alloca [[CLASS_ANON_0:%.*]], align 4 +// CHECK3-NEXT: [[DOTADDR:%.*]] = alloca i32, align 4 +// CHECK3-NEXT: [[DOTADDR1:%.*]] = alloca ptr, align 4 +// CHECK3-NEXT: store i32 [[TMP0]], ptr [[DOTADDR]], align 4 +// CHECK3-NEXT: store ptr [[TMP1]], ptr [[DOTADDR1]], align 4 +// CHECK3-NEXT: [[TMP2:%.*]] = load i32, ptr [[DOTADDR]], align 4 +// CHECK3-NEXT: [[TMP3:%.*]] = load ptr, ptr [[DOTADDR1]], align 4 +// CHECK3-NEXT: [[TMP4:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T_WITH_PRIVATES:%.*]], ptr [[TMP3]], i32 0, i32 0 +// CHECK3-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T:%.*]], ptr [[TMP4]], i32 0, i32 2 +// CHECK3-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP4]], i32 0, i32 0 +// CHECK3-NEXT: [[TMP7:%.*]] = load ptr, ptr [[TMP6]], align 4 +// CHECK3-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T_WITH_PRIVATES]], ptr [[TMP3]], i32 0, i32 1 +// CHECK3-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP4]], i32 0, i32 5 +// CHECK3-NEXT: [[TMP10:%.*]] = load i64, ptr [[TMP9]], align 4 +// CHECK3-NEXT: [[TMP11:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP4]], i32 0, i32 6 +// CHECK3-NEXT: [[TMP12:%.*]] = load i64, ptr [[TMP11]], align 4 +// CHECK3-NEXT: [[TMP13:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP4]], i32 0, i32 7 +// CHECK3-NEXT: [[TMP14:%.*]] = load i64, ptr [[TMP13]], align 4 +// CHECK3-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP4]], i32 0, i32 8 +// CHECK3-NEXT: [[TMP16:%.*]] = load i32, ptr [[TMP15]], align 4 +// CHECK3-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP4]], i32 0, i32 9 +// CHECK3-NEXT: [[TMP18:%.*]] = load ptr, ptr [[TMP17]], align 4 +// CHECK3-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META4:![0-9]+]]) +// CHECK3-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META7:![0-9]+]]) +// CHECK3-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META9:![0-9]+]]) +// CHECK3-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META11:![0-9]+]]) +// CHECK3-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META13:![0-9]+]]) +// CHECK3-NEXT: store i32 [[TMP2]], ptr [[DOTGLOBAL_TID__ADDR_I]], align 4, !noalias [[META15:![0-9]+]] +// CHECK3-NEXT: store ptr [[TMP5]], ptr [[DOTPART_ID__ADDR_I]], align 4, !noalias [[META15]] +// CHECK3-NEXT: store ptr [[TMP8]], ptr [[DOTPRIVATES__ADDR_I]], align 4, !noalias [[META15]] +// CHECK3-NEXT: store ptr @.omp_task_privates_map., ptr [[DOTCOPY_FN__ADDR_I]], align 4, !noalias [[META15]] +// CHECK3-NEXT: store ptr [[TMP3]], ptr [[DOTTASK_T__ADDR_I]], align 4, !noalias [[META15]] +// CHECK3-NEXT: store i64 [[TMP10]], ptr [[DOTLB__ADDR_I]], align 8, !noalias [[META15]] +// CHECK3-NEXT: store i64 [[TMP12]], ptr [[DOTUB__ADDR_I]], align 8, !noalias [[META15]] +// CHECK3-NEXT: store i64 [[TMP14]], ptr [[DOTST__ADDR_I]], align 8, !noalias [[META15]] +// CHECK3-NEXT: store i32 [[TMP16]], ptr [[DOTLITER__ADDR_I]], align 4, !noalias [[META15]] +// CHECK3-NEXT: store ptr [[TMP18]], ptr [[DOTREDUCTIONS__ADDR_I]], align 4, !noalias [[META15]] +// CHECK3-NEXT: store ptr [[TMP7]], ptr [[__CONTEXT_ADDR_I]], align 4, !noalias [[META15]] +// CHECK3-NEXT: [[TMP19:%.*]] = load ptr, ptr [[__CONTEXT_ADDR_I]], align 4, !noalias [[META15]] +// CHECK3-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTCOPY_FN__ADDR_I]], align 4, !noalias [[META15]] +// CHECK3-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTPRIVATES__ADDR_I]], align 4, !noalias [[META15]] +// CHECK3-NEXT: call void [[TMP20]](ptr [[TMP21]], ptr [[DOTPRIV_PTR_ADDR_I]], ptr [[DOTPRIV_PTR_ADDR1_I]], ptr [[DOTPRIV_PTR_ADDR2_I]], ptr [[DOTPRIV_PTR_ADDR3_I]]) #[[ATTR2:[0-9]+]] +// CHECK3-NEXT: [[TMP22:%.*]] = load ptr, ptr [[DOTPRIV_PTR_ADDR_I]], align 4, !noalias [[META15]] +// CHECK3-NEXT: [[TMP23:%.*]] = load ptr, ptr [[DOTPRIV_PTR_ADDR1_I]], align 4, !noalias [[META15]] +// CHECK3-NEXT: store ptr [[TMP23]], ptr [[TMP_I]], align 4, !noalias [[META15]] +// CHECK3-NEXT: [[TMP24:%.*]] = load ptr, ptr [[DOTPRIV_PTR_ADDR2_I]], align 4, !noalias [[META15]] +// CHECK3-NEXT: [[TMP25:%.*]] = load ptr, ptr [[DOTPRIV_PTR_ADDR3_I]], align 4, !noalias [[META15]] +// CHECK3-NEXT: store ptr undef, ptr [[TMP5_I]], align 4, !noalias [[META15]] +// CHECK3-NEXT: [[TMP26:%.*]] = load i64, ptr [[DOTLB__ADDR_I]], align 8, !noalias [[META15]] +// CHECK3-NEXT: [[CONV_I:%.*]] = trunc i64 [[TMP26]] to i32 +// CHECK3-NEXT: store i32 [[CONV_I]], ptr [[DOTOMP_IV_I]], align 4, !noalias [[META15]] +// CHECK3-NEXT: br label [[OMP_INNER_FOR_COND_I:%.*]] +// CHECK3: omp.inner.for.cond.i: +// CHECK3-NEXT: [[TMP27:%.*]] = load i32, ptr [[DOTOMP_IV_I]], align 4, !noalias [[META15]], !llvm.access.group [[ACC_GRP16:![0-9]+]] +// CHECK3-NEXT: [[CONV6_I:%.*]] = sext i32 [[TMP27]] to i64 +// CHECK3-NEXT: [[TMP28:%.*]] = load i64, ptr [[DOTUB__ADDR_I]], align 8, !noalias [[META15]], !llvm.access.group [[ACC_GRP16]] +// CHECK3-NEXT: [[CMP_I:%.*]] = icmp ule i64 [[CONV6_I]], [[TMP28]] +// CHECK3-NEXT: br i1 [[CMP_I]], label [[OMP_INNER_FOR_BODY_I:%.*]], label [[DOTOMP_OUTLINED__EXIT:%.*]] +// CHECK3: omp.inner.for.body.i: +// CHECK3-NEXT: [[TMP29:%.*]] = load i32, ptr [[DOTOMP_IV_I]], align 4, !noalias [[META15]], !llvm.access.group [[ACC_GRP16]] +// CHECK3-NEXT: store i32 [[TMP29]], ptr [[I_I]], align 4, !noalias [[META15]], !llvm.access.group [[ACC_GRP16]] +// CHECK3-NEXT: store double 1.000000e+00, ptr [[TMP22]], align 8, !llvm.access.group [[ACC_GRP16]] +// CHECK3-NEXT: [[TMP30:%.*]] = load ptr, ptr [[TMP_I]], align 4, !noalias [[META15]], !llvm.access.group [[ACC_GRP16]] +// CHECK3-NEXT: store volatile double 1.000000e+00, ptr [[TMP30]], align 4, !llvm.access.group [[ACC_GRP16]] +// CHECK3-NEXT: store i32 3, ptr [[TMP24]], align 4, !llvm.access.group [[ACC_GRP16]] +// CHECK3-NEXT: store float 4.000000e+00, ptr [[TMP25]], align 4, !llvm.access.group [[ACC_GRP16]] +// CHECK3-NEXT: store ptr [[TMP22]], ptr [[REF_TMP_I]], align 4, !noalias [[META15]], !llvm.access.group [[ACC_GRP16]] +// CHECK3-NEXT: [[TMP31:%.*]] = getelementptr inbounds [[CLASS_ANON_0]], ptr [[REF_TMP_I]], i32 0, i32 1 +// CHECK3-NEXT: [[TMP32:%.*]] = load ptr, ptr [[TMP_I]], align 4, !noalias [[META15]], !llvm.access.group [[ACC_GRP16]] +// CHECK3-NEXT: store ptr [[TMP32]], ptr [[TMP31]], align 4, !noalias [[META15]], !llvm.access.group [[ACC_GRP16]] +// CHECK3-NEXT: [[TMP33:%.*]] = getelementptr inbounds [[CLASS_ANON_0]], ptr [[REF_TMP_I]], i32 0, i32 2 +// CHECK3-NEXT: store ptr [[TMP24]], ptr [[TMP33]], align 4, !noalias [[META15]], !llvm.access.group [[ACC_GRP16]] +// CHECK3-NEXT: [[TMP34:%.*]] = getelementptr inbounds [[CLASS_ANON_0]], ptr [[REF_TMP_I]], i32 0, i32 3 +// CHECK3-NEXT: store ptr [[TMP25]], ptr [[TMP34]], align 4, !noalias [[META15]], !llvm.access.group [[ACC_GRP16]] +// CHECK3-NEXT: call void @"_ZZZ4mainENK3$_0clEvENKUlvE_clEv"(ptr noundef nonnull align 4 dereferenceable(16) [[REF_TMP_I]]), !llvm.access.group [[ACC_GRP16]] +// CHECK3-NEXT: [[TMP35:%.*]] = load i32, ptr [[DOTOMP_IV_I]], align 4, !noalias [[META15]], !llvm.access.group [[ACC_GRP16]] +// CHECK3-NEXT: [[ADD7_I:%.*]] = add nsw i32 [[TMP35]], 1 +// CHECK3-NEXT: store i32 [[ADD7_I]], ptr [[DOTOMP_IV_I]], align 4, !noalias [[META15]], !llvm.access.group [[ACC_GRP16]] +// CHECK3-NEXT: br label [[OMP_INNER_FOR_COND_I]], !llvm.loop [[LOOP17:![0-9]+]] +// CHECK3: .omp_outlined..exit: +// CHECK3-NEXT: ret i32 0 +// +// +// CHECK5-LABEL: define {{[^@]+}}@main +// CHECK5-SAME: () #[[ATTR0:[0-9]+]] { +// CHECK5-NEXT: entry: +// CHECK5-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 +// CHECK5-NEXT: [[G:%.*]] = alloca double, align 8 +// CHECK5-NEXT: [[G1:%.*]] = alloca ptr, align 8 +// CHECK5-NEXT: [[REF_TMP:%.*]] = alloca [[CLASS_ANON:%.*]], align 8 +// CHECK5-NEXT: store i32 0, ptr [[RETVAL]], align 4 +// CHECK5-NEXT: store ptr [[G]], ptr [[G1]], align 8 +// CHECK5-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[CLASS_ANON]], ptr [[REF_TMP]], i32 0, i32 0 +// CHECK5-NEXT: store ptr [[G]], ptr [[TMP0]], align 8 +// CHECK5-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[CLASS_ANON]], ptr [[REF_TMP]], i32 0, i32 1 +// CHECK5-NEXT: [[TMP2:%.*]] = load ptr, ptr [[G1]], align 8 +// CHECK5-NEXT: store ptr [[TMP2]], ptr [[TMP1]], align 8 +// CHECK5-NEXT: call void @"_ZZ4mainENK3$_0clEv"(ptr noundef nonnull align 8 dereferenceable(16) [[REF_TMP]]) +// CHECK5-NEXT: ret i32 0 +// +// +// CHECK7-LABEL: define {{[^@]+}}@main +// CHECK7-SAME: () #[[ATTR0:[0-9]+]] { +// CHECK7-NEXT: entry: +// CHECK7-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 +// CHECK7-NEXT: [[G:%.*]] = alloca double, align 8 +// CHECK7-NEXT: [[G1:%.*]] = alloca ptr, align 4 +// CHECK7-NEXT: [[REF_TMP:%.*]] = alloca [[CLASS_ANON:%.*]], align 4 +// CHECK7-NEXT: store i32 0, ptr [[RETVAL]], align 4 +// CHECK7-NEXT: store ptr [[G]], ptr [[G1]], align 4 +// CHECK7-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[CLASS_ANON]], ptr [[REF_TMP]], i32 0, i32 0 +// CHECK7-NEXT: store ptr [[G]], ptr [[TMP0]], align 4 +// CHECK7-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[CLASS_ANON]], ptr [[REF_TMP]], i32 0, i32 1 +// CHECK7-NEXT: [[TMP2:%.*]] = load ptr, ptr [[G1]], align 4 +// CHECK7-NEXT: store ptr [[TMP2]], ptr [[TMP1]], align 4 +// CHECK7-NEXT: call void @"_ZZ4mainENK3$_0clEv"(ptr noundef nonnull align 4 dereferenceable(8) [[REF_TMP]]) +// CHECK7-NEXT: ret i32 0 +// +// +// CHECK9-LABEL: define {{[^@]+}}@main +// CHECK9-SAME: () #[[ATTR0:[0-9]+]] { +// CHECK9-NEXT: entry: +// CHECK9-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 +// CHECK9-NEXT: [[G:%.*]] = alloca double, align 8 +// CHECK9-NEXT: [[G1:%.*]] = alloca ptr, align 8 +// CHECK9-NEXT: [[TEST:%.*]] = alloca [[STRUCT_S:%.*]], align 4 +// CHECK9-NEXT: [[T_VAR:%.*]] = alloca i32, align 4 +// CHECK9-NEXT: [[VEC:%.*]] = alloca [2 x i32], align 4 +// CHECK9-NEXT: [[S_ARR:%.*]] = alloca [2 x %struct.S], align 4 +// CHECK9-NEXT: [[VAR:%.*]] = alloca ptr, align 8 +// CHECK9-NEXT: [[AGG_CAPTURED:%.*]] = alloca [[STRUCT_ANON:%.*]], align 1 +// CHECK9-NEXT: [[TMP:%.*]] = alloca i32, align 4 +// CHECK9-NEXT: [[_TMP1:%.*]] = alloca ptr, align 8 +// CHECK9-NEXT: [[I:%.*]] = alloca i32, align 4 +// CHECK9-NEXT: [[AGG_CAPTURED2:%.*]] = alloca [[STRUCT_ANON_0:%.*]], align 1 +// CHECK9-NEXT: [[_TMP3:%.*]] = alloca i32, align 4 +// CHECK9-NEXT: [[TMP0:%.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GLOB1:[0-9]+]]) +// CHECK9-NEXT: store i32 0, ptr [[RETVAL]], align 4 +// CHECK9-NEXT: store ptr [[G]], ptr [[G1]], align 8 +// CHECK9-NEXT: call void @_ZN1SIfEC1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[TEST]]) +// CHECK9-NEXT: store i32 0, ptr [[T_VAR]], align 4 +// CHECK9-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[VEC]], ptr align 4 @__const.main.vec, i64 8, i1 false) +// CHECK9-NEXT: [[ARRAYINIT_BEGIN:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[S_ARR]], i64 0, i64 0 +// CHECK9-NEXT: call void @_ZN1SIfEC1Ef(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYINIT_BEGIN]], float noundef 1.000000e+00) +// CHECK9-NEXT: [[ARRAYINIT_ELEMENT:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAYINIT_BEGIN]], i64 1 +// CHECK9-NEXT: call void @_ZN1SIfEC1Ef(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYINIT_ELEMENT]], float noundef 2.000000e+00) +// CHECK9-NEXT: store ptr [[TEST]], ptr [[VAR]], align 8 +// CHECK9-NEXT: call void @__kmpc_taskgroup(ptr @[[GLOB1]], i32 [[TMP0]]) +// CHECK9-NEXT: store ptr undef, ptr [[_TMP1]], align 8 +// CHECK9-NEXT: [[TMP1:%.*]] = call ptr @__kmpc_omp_task_alloc(ptr @[[GLOB1]], i32 [[TMP0]], i32 9, i64 112, i64 1, ptr @.omp_task_entry.) +// CHECK9-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T_WITH_PRIVATES:%.*]], ptr [[TMP1]], i32 0, i32 0 +// CHECK9-NEXT: [[TMP3:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T_WITH_PRIVATES]], ptr [[TMP1]], i32 0, i32 1 +// CHECK9-NEXT: [[TMP4:%.*]] = getelementptr inbounds [[STRUCT__KMP_PRIVATES_T:%.*]], ptr [[TMP3]], i32 0, i32 0 +// CHECK9-NEXT: call void @_ZN1SIfEC1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[TMP4]]) +// CHECK9-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT__KMP_PRIVATES_T]], ptr [[TMP3]], i32 0, i32 3 +// CHECK9-NEXT: [[ARRAY_BEGIN:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[TMP5]], i32 0, i32 0 +// CHECK9-NEXT: [[ARRAYCTOR_END:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAY_BEGIN]], i64 2 +// CHECK9-NEXT: br label [[ARRAYCTOR_LOOP:%.*]] +// CHECK9: arrayctor.loop: +// CHECK9-NEXT: [[ARRAYCTOR_CUR:%.*]] = phi ptr [ [[ARRAY_BEGIN]], [[ENTRY:%.*]] ], [ [[ARRAYCTOR_NEXT:%.*]], [[ARRAYCTOR_LOOP]] ] +// CHECK9-NEXT: call void @_ZN1SIfEC1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYCTOR_CUR]]) +// CHECK9-NEXT: [[ARRAYCTOR_NEXT]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAYCTOR_CUR]], i64 1 +// CHECK9-NEXT: [[ARRAYCTOR_DONE:%.*]] = icmp eq ptr [[ARRAYCTOR_NEXT]], [[ARRAYCTOR_END]] +// CHECK9-NEXT: br i1 [[ARRAYCTOR_DONE]], label [[ARRAYCTOR_CONT:%.*]], label [[ARRAYCTOR_LOOP]] +// CHECK9: arrayctor.cont: +// CHECK9-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T:%.*]], ptr [[TMP2]], i32 0, i32 3 +// CHECK9-NEXT: store ptr @.omp_task_destructor., ptr [[TMP6]], align 8 +// CHECK9-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP2]], i32 0, i32 5 +// CHECK9-NEXT: store i64 0, ptr [[TMP7]], align 8 +// CHECK9-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP2]], i32 0, i32 6 +// CHECK9-NEXT: store i64 1, ptr [[TMP8]], align 8 +// CHECK9-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP2]], i32 0, i32 7 +// CHECK9-NEXT: store i64 1, ptr [[TMP9]], align 8 +// CHECK9-NEXT: [[TMP10:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP2]], i32 0, i32 9 +// CHECK9-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[TMP10]], i8 0, i64 8, i1 false) +// CHECK9-NEXT: [[TMP11:%.*]] = load i64, ptr [[TMP9]], align 8 +// CHECK9-NEXT: call void @__kmpc_taskloop(ptr @[[GLOB1]], i32 [[TMP0]], ptr [[TMP1]], i32 1, ptr [[TMP7]], ptr [[TMP8]], i64 [[TMP11]], i32 1, i32 0, i64 0, ptr @.omp_task_dup.) +// CHECK9-NEXT: call void @__kmpc_end_taskgroup(ptr @[[GLOB1]], i32 [[TMP0]]) +// CHECK9-NEXT: call void @__kmpc_taskgroup(ptr @[[GLOB1]], i32 [[TMP0]]) +// CHECK9-NEXT: [[TMP12:%.*]] = call ptr @__kmpc_omp_task_alloc(ptr @[[GLOB1]], i32 [[TMP0]], i32 1, i64 80, i64 1, ptr @.omp_task_entry..2) +// CHECK9-NEXT: [[TMP13:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T_WITH_PRIVATES_1:%.*]], ptr [[TMP12]], i32 0, i32 0 +// CHECK9-NEXT: [[TMP14:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP13]], i32 0, i32 5 +// CHECK9-NEXT: store i64 0, ptr [[TMP14]], align 8 +// CHECK9-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP13]], i32 0, i32 6 +// CHECK9-NEXT: store i64 1, ptr [[TMP15]], align 8 +// CHECK9-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP13]], i32 0, i32 7 +// CHECK9-NEXT: store i64 1, ptr [[TMP16]], align 8 +// CHECK9-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP13]], i32 0, i32 9 +// CHECK9-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[TMP17]], i8 0, i64 8, i1 false) +// CHECK9-NEXT: [[TMP18:%.*]] = load i64, ptr [[TMP16]], align 8 +// CHECK9-NEXT: call void @__kmpc_taskloop(ptr @[[GLOB1]], i32 [[TMP0]], ptr [[TMP12]], i32 1, ptr [[TMP14]], ptr [[TMP15]], i64 [[TMP18]], i32 1, i32 0, i64 0, ptr null) +// CHECK9-NEXT: call void @__kmpc_end_taskgroup(ptr @[[GLOB1]], i32 [[TMP0]]) +// CHECK9-NEXT: [[CALL:%.*]] = call noundef signext i32 @_Z5tmainIiET_v() +// CHECK9-NEXT: store i32 [[CALL]], ptr [[RETVAL]], align 4 +// CHECK9-NEXT: [[ARRAY_BEGIN4:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[S_ARR]], i32 0, i32 0 +// CHECK9-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAY_BEGIN4]], i64 2 +// CHECK9-NEXT: br label [[ARRAYDESTROY_BODY:%.*]] +// CHECK9: arraydestroy.body: +// CHECK9-NEXT: [[ARRAYDESTROY_ELEMENTPAST:%.*]] = phi ptr [ [[TMP19]], [[ARRAYCTOR_CONT]] ], [ [[ARRAYDESTROY_ELEMENT:%.*]], [[ARRAYDESTROY_BODY]] ] +// CHECK9-NEXT: [[ARRAYDESTROY_ELEMENT]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAYDESTROY_ELEMENTPAST]], i64 -1 +// CHECK9-NEXT: call void @_ZN1SIfED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYDESTROY_ELEMENT]]) #[[ATTR3:[0-9]+]] +// CHECK9-NEXT: [[ARRAYDESTROY_DONE:%.*]] = icmp eq ptr [[ARRAYDESTROY_ELEMENT]], [[ARRAY_BEGIN4]] +// CHECK9-NEXT: br i1 [[ARRAYDESTROY_DONE]], label [[ARRAYDESTROY_DONE5:%.*]], label [[ARRAYDESTROY_BODY]] +// CHECK9: arraydestroy.done5: +// CHECK9-NEXT: call void @_ZN1SIfED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[TEST]]) #[[ATTR3]] +// CHECK9-NEXT: [[TMP20:%.*]] = load i32, ptr [[RETVAL]], align 4 +// CHECK9-NEXT: ret i32 [[TMP20]] +// +// +// CHECK9-LABEL: define {{[^@]+}}@_ZN1SIfEC1Ev +// CHECK9-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]]) unnamed_addr #[[ATTR1:[0-9]+]] comdat { +// CHECK9-NEXT: entry: +// CHECK9-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK9-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 +// CHECK9-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK9-NEXT: call void @_ZN1SIfEC2Ev(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]]) +// CHECK9-NEXT: ret void +// +// +// CHECK9-LABEL: define {{[^@]+}}@_ZN1SIfEC1Ef +// CHECK9-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]], float noundef [[A:%.*]]) unnamed_addr #[[ATTR1]] comdat { +// CHECK9-NEXT: entry: +// CHECK9-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK9-NEXT: [[A_ADDR:%.*]] = alloca float, align 4 +// CHECK9-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 +// CHECK9-NEXT: store float [[A]], ptr [[A_ADDR]], align 4 +// CHECK9-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK9-NEXT: [[TMP0:%.*]] = load float, ptr [[A_ADDR]], align 4 +// CHECK9-NEXT: call void @_ZN1SIfEC2Ef(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]], float noundef [[TMP0]]) +// CHECK9-NEXT: ret void +// +// +// CHECK9-LABEL: define {{[^@]+}}@.omp_task_privates_map. +// CHECK9-SAME: (ptr noalias noundef [[TMP0:%.*]], ptr noalias noundef [[TMP1:%.*]], ptr noalias noundef [[TMP2:%.*]], ptr noalias noundef [[TMP3:%.*]], ptr noalias noundef [[TMP4:%.*]], ptr noalias noundef [[TMP5:%.*]]) #[[ATTR5:[0-9]+]] { +// CHECK9-NEXT: entry: +// CHECK9-NEXT: [[DOTADDR:%.*]] = alloca ptr, align 8 +// CHECK9-NEXT: [[DOTADDR1:%.*]] = alloca ptr, align 8 +// CHECK9-NEXT: [[DOTADDR2:%.*]] = alloca ptr, align 8 +// CHECK9-NEXT: [[DOTADDR3:%.*]] = alloca ptr, align 8 +// CHECK9-NEXT: [[DOTADDR4:%.*]] = alloca ptr, align 8 +// CHECK9-NEXT: [[DOTADDR5:%.*]] = alloca ptr, align 8 +// CHECK9-NEXT: store ptr [[TMP0]], ptr [[DOTADDR]], align 8 +// CHECK9-NEXT: store ptr [[TMP1]], ptr [[DOTADDR1]], align 8 +// CHECK9-NEXT: store ptr [[TMP2]], ptr [[DOTADDR2]], align 8 +// CHECK9-NEXT: store ptr [[TMP3]], ptr [[DOTADDR3]], align 8 +// CHECK9-NEXT: store ptr [[TMP4]], ptr [[DOTADDR4]], align 8 +// CHECK9-NEXT: store ptr [[TMP5]], ptr [[DOTADDR5]], align 8 +// CHECK9-NEXT: [[TMP6:%.*]] = load ptr, ptr [[DOTADDR]], align 8 +// CHECK9-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT__KMP_PRIVATES_T:%.*]], ptr [[TMP6]], i32 0, i32 0 +// CHECK9-NEXT: [[TMP8:%.*]] = load ptr, ptr [[DOTADDR4]], align 8 +// CHECK9-NEXT: store ptr [[TMP7]], ptr [[TMP8]], align 8 +// CHECK9-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT__KMP_PRIVATES_T]], ptr [[TMP6]], i32 0, i32 1 +// CHECK9-NEXT: [[TMP10:%.*]] = load ptr, ptr [[DOTADDR1]], align 8 +// CHECK9-NEXT: store ptr [[TMP9]], ptr [[TMP10]], align 8 +// CHECK9-NEXT: [[TMP11:%.*]] = getelementptr inbounds [[STRUCT__KMP_PRIVATES_T]], ptr [[TMP6]], i32 0, i32 2 +// CHECK9-NEXT: [[TMP12:%.*]] = load ptr, ptr [[DOTADDR2]], align 8 +// CHECK9-NEXT: store ptr [[TMP11]], ptr [[TMP12]], align 8 +// CHECK9-NEXT: [[TMP13:%.*]] = getelementptr inbounds [[STRUCT__KMP_PRIVATES_T]], ptr [[TMP6]], i32 0, i32 3 +// CHECK9-NEXT: [[TMP14:%.*]] = load ptr, ptr [[DOTADDR3]], align 8 +// CHECK9-NEXT: store ptr [[TMP13]], ptr [[TMP14]], align 8 +// CHECK9-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT__KMP_PRIVATES_T]], ptr [[TMP6]], i32 0, i32 4 +// CHECK9-NEXT: [[TMP16:%.*]] = load ptr, ptr [[DOTADDR5]], align 8 +// CHECK9-NEXT: store ptr [[TMP15]], ptr [[TMP16]], align 8 +// CHECK9-NEXT: ret void +// +// +// CHECK9-LABEL: define {{[^@]+}}@.omp_task_entry. +// CHECK9-SAME: (i32 noundef signext [[TMP0:%.*]], ptr noalias noundef [[TMP1:%.*]]) #[[ATTR6:[0-9]+]] { +// CHECK9-NEXT: entry: +// CHECK9-NEXT: [[DOTGLOBAL_TID__ADDR_I:%.*]] = alloca i32, align 4 +// CHECK9-NEXT: [[DOTPART_ID__ADDR_I:%.*]] = alloca ptr, align 8 +// CHECK9-NEXT: [[DOTPRIVATES__ADDR_I:%.*]] = alloca ptr, align 8 +// CHECK9-NEXT: [[DOTCOPY_FN__ADDR_I:%.*]] = alloca ptr, align 8 +// CHECK9-NEXT: [[DOTTASK_T__ADDR_I:%.*]] = alloca ptr, align 8 +// CHECK9-NEXT: [[DOTLB__ADDR_I:%.*]] = alloca i64, align 8 +// CHECK9-NEXT: [[DOTUB__ADDR_I:%.*]] = alloca i64, align 8 +// CHECK9-NEXT: [[DOTST__ADDR_I:%.*]] = alloca i64, align 8 +// CHECK9-NEXT: [[DOTLITER__ADDR_I:%.*]] = alloca i32, align 4 +// CHECK9-NEXT: [[DOTREDUCTIONS__ADDR_I:%.*]] = alloca ptr, align 8 +// CHECK9-NEXT: [[__CONTEXT_ADDR_I:%.*]] = alloca ptr, align 8 +// CHECK9-NEXT: [[DOTPRIV_PTR_ADDR_I:%.*]] = alloca ptr, align 8 +// CHECK9-NEXT: [[DOTPRIV_PTR_ADDR1_I:%.*]] = alloca ptr, align 8 +// CHECK9-NEXT: [[DOTPRIV_PTR_ADDR2_I:%.*]] = alloca ptr, align 8 +// CHECK9-NEXT: [[DOTPRIV_PTR_ADDR3_I:%.*]] = alloca ptr, align 8 +// CHECK9-NEXT: [[DOTPRIV_PTR_ADDR4_I:%.*]] = alloca ptr, align 8 +// CHECK9-NEXT: [[TMP_I:%.*]] = alloca ptr, align 8 +// CHECK9-NEXT: [[TMP6_I:%.*]] = alloca ptr, align 8 +// CHECK9-NEXT: [[I_I:%.*]] = alloca i32, align 4 +// CHECK9-NEXT: [[DOTOMP_IV_I:%.*]] = alloca i32, align 4 +// CHECK9-NEXT: [[DOTADDR:%.*]] = alloca i32, align 4 +// CHECK9-NEXT: [[DOTADDR1:%.*]] = alloca ptr, align 8 +// CHECK9-NEXT: store i32 [[TMP0]], ptr [[DOTADDR]], align 4 +// CHECK9-NEXT: store ptr [[TMP1]], ptr [[DOTADDR1]], align 8 +// CHECK9-NEXT: [[TMP2:%.*]] = load i32, ptr [[DOTADDR]], align 4 +// CHECK9-NEXT: [[TMP3:%.*]] = load ptr, ptr [[DOTADDR1]], align 8 +// CHECK9-NEXT: [[TMP4:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T_WITH_PRIVATES:%.*]], ptr [[TMP3]], i32 0, i32 0 +// CHECK9-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T:%.*]], ptr [[TMP4]], i32 0, i32 2 +// CHECK9-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP4]], i32 0, i32 0 +// CHECK9-NEXT: [[TMP7:%.*]] = load ptr, ptr [[TMP6]], align 8 +// CHECK9-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T_WITH_PRIVATES]], ptr [[TMP3]], i32 0, i32 1 +// CHECK9-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP4]], i32 0, i32 5 +// CHECK9-NEXT: [[TMP10:%.*]] = load i64, ptr [[TMP9]], align 8 +// CHECK9-NEXT: [[TMP11:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP4]], i32 0, i32 6 +// CHECK9-NEXT: [[TMP12:%.*]] = load i64, ptr [[TMP11]], align 8 +// CHECK9-NEXT: [[TMP13:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP4]], i32 0, i32 7 +// CHECK9-NEXT: [[TMP14:%.*]] = load i64, ptr [[TMP13]], align 8 +// CHECK9-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP4]], i32 0, i32 8 +// CHECK9-NEXT: [[TMP16:%.*]] = load i32, ptr [[TMP15]], align 8 +// CHECK9-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP4]], i32 0, i32 9 +// CHECK9-NEXT: [[TMP18:%.*]] = load ptr, ptr [[TMP17]], align 8 +// CHECK9-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META3:![0-9]+]]) +// CHECK9-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META6:![0-9]+]]) +// CHECK9-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META8:![0-9]+]]) +// CHECK9-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META10:![0-9]+]]) +// CHECK9-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META12:![0-9]+]]) +// CHECK9-NEXT: store i32 [[TMP2]], ptr [[DOTGLOBAL_TID__ADDR_I]], align 4, !noalias [[META14:![0-9]+]] +// CHECK9-NEXT: store ptr [[TMP5]], ptr [[DOTPART_ID__ADDR_I]], align 8, !noalias [[META14]] +// CHECK9-NEXT: store ptr [[TMP8]], ptr [[DOTPRIVATES__ADDR_I]], align 8, !noalias [[META14]] +// CHECK9-NEXT: store ptr @.omp_task_privates_map., ptr [[DOTCOPY_FN__ADDR_I]], align 8, !noalias [[META14]] +// CHECK9-NEXT: store ptr [[TMP3]], ptr [[DOTTASK_T__ADDR_I]], align 8, !noalias [[META14]] +// CHECK9-NEXT: store i64 [[TMP10]], ptr [[DOTLB__ADDR_I]], align 8, !noalias [[META14]] +// CHECK9-NEXT: store i64 [[TMP12]], ptr [[DOTUB__ADDR_I]], align 8, !noalias [[META14]] +// CHECK9-NEXT: store i64 [[TMP14]], ptr [[DOTST__ADDR_I]], align 8, !noalias [[META14]] +// CHECK9-NEXT: store i32 [[TMP16]], ptr [[DOTLITER__ADDR_I]], align 4, !noalias [[META14]] +// CHECK9-NEXT: store ptr [[TMP18]], ptr [[DOTREDUCTIONS__ADDR_I]], align 8, !noalias [[META14]] +// CHECK9-NEXT: store ptr [[TMP7]], ptr [[__CONTEXT_ADDR_I]], align 8, !noalias [[META14]] +// CHECK9-NEXT: [[TMP19:%.*]] = load ptr, ptr [[__CONTEXT_ADDR_I]], align 8, !noalias [[META14]] +// CHECK9-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTCOPY_FN__ADDR_I]], align 8, !noalias [[META14]] +// CHECK9-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTPRIVATES__ADDR_I]], align 8, !noalias [[META14]] +// CHECK9-NEXT: call void [[TMP20]](ptr [[TMP21]], ptr [[DOTPRIV_PTR_ADDR_I]], ptr [[DOTPRIV_PTR_ADDR1_I]], ptr [[DOTPRIV_PTR_ADDR2_I]], ptr [[DOTPRIV_PTR_ADDR3_I]], ptr [[DOTPRIV_PTR_ADDR4_I]]) #[[ATTR3]] +// CHECK9-NEXT: [[TMP22:%.*]] = load ptr, ptr [[DOTPRIV_PTR_ADDR_I]], align 8, !noalias [[META14]] +// CHECK9-NEXT: [[TMP23:%.*]] = load ptr, ptr [[DOTPRIV_PTR_ADDR1_I]], align 8, !noalias [[META14]] +// CHECK9-NEXT: [[TMP24:%.*]] = load ptr, ptr [[DOTPRIV_PTR_ADDR2_I]], align 8, !noalias [[META14]] +// CHECK9-NEXT: [[TMP25:%.*]] = load ptr, ptr [[DOTPRIV_PTR_ADDR3_I]], align 8, !noalias [[META14]] +// CHECK9-NEXT: store ptr [[TMP25]], ptr [[TMP_I]], align 8, !noalias [[META14]] +// CHECK9-NEXT: [[TMP26:%.*]] = load ptr, ptr [[DOTPRIV_PTR_ADDR4_I]], align 8, !noalias [[META14]] +// CHECK9-NEXT: store ptr undef, ptr [[TMP6_I]], align 8, !noalias [[META14]] +// CHECK9-NEXT: [[TMP27:%.*]] = load i64, ptr [[DOTLB__ADDR_I]], align 8, !noalias [[META14]] +// CHECK9-NEXT: [[CONV_I:%.*]] = trunc i64 [[TMP27]] to i32 +// CHECK9-NEXT: store i32 [[CONV_I]], ptr [[DOTOMP_IV_I]], align 4, !noalias [[META14]] +// CHECK9-NEXT: br label [[OMP_INNER_FOR_COND_I:%.*]] +// CHECK9: omp.inner.for.cond.i: +// CHECK9-NEXT: [[TMP28:%.*]] = load i32, ptr [[DOTOMP_IV_I]], align 4, !noalias [[META14]], !llvm.access.group [[ACC_GRP15:![0-9]+]] +// CHECK9-NEXT: [[CONV7_I:%.*]] = sext i32 [[TMP28]] to i64 +// CHECK9-NEXT: [[TMP29:%.*]] = load i64, ptr [[DOTUB__ADDR_I]], align 8, !noalias [[META14]], !llvm.access.group [[ACC_GRP15]] +// CHECK9-NEXT: [[CMP_I:%.*]] = icmp ule i64 [[CONV7_I]], [[TMP29]] +// CHECK9-NEXT: br i1 [[CMP_I]], label [[OMP_INNER_FOR_BODY_I:%.*]], label [[DOTOMP_OUTLINED__EXIT:%.*]] +// CHECK9: omp.inner.for.body.i: +// CHECK9-NEXT: [[TMP30:%.*]] = load i32, ptr [[DOTOMP_IV_I]], align 4, !noalias [[META14]], !llvm.access.group [[ACC_GRP15]] +// CHECK9-NEXT: store i32 [[TMP30]], ptr [[I_I]], align 4, !noalias [[META14]], !llvm.access.group [[ACC_GRP15]] +// CHECK9-NEXT: [[TMP31:%.*]] = load i32, ptr [[TMP22]], align 4, !llvm.access.group [[ACC_GRP15]] +// CHECK9-NEXT: [[TMP32:%.*]] = load i32, ptr [[I_I]], align 4, !noalias [[META14]], !llvm.access.group [[ACC_GRP15]] +// CHECK9-NEXT: [[IDXPROM_I:%.*]] = sext i32 [[TMP32]] to i64 +// CHECK9-NEXT: [[ARRAYIDX_I:%.*]] = getelementptr inbounds [2 x i32], ptr [[TMP23]], i64 0, i64 [[IDXPROM_I]] +// CHECK9-NEXT: store i32 [[TMP31]], ptr [[ARRAYIDX_I]], align 4, !llvm.access.group [[ACC_GRP15]] +// CHECK9-NEXT: [[TMP33:%.*]] = load ptr, ptr [[TMP_I]], align 8, !noalias [[META14]], !llvm.access.group [[ACC_GRP15]] +// CHECK9-NEXT: [[TMP34:%.*]] = load i32, ptr [[I_I]], align 4, !noalias [[META14]], !llvm.access.group [[ACC_GRP15]] +// CHECK9-NEXT: [[IDXPROM8_I:%.*]] = sext i32 [[TMP34]] to i64 +// CHECK9-NEXT: [[ARRAYIDX9_I:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[TMP24]], i64 0, i64 [[IDXPROM8_I]] +// CHECK9-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[ARRAYIDX9_I]], ptr align 4 [[TMP33]], i64 4, i1 false), !llvm.access.group [[ACC_GRP15]] +// CHECK9-NEXT: [[TMP35:%.*]] = load i32, ptr [[DOTOMP_IV_I]], align 4, !noalias [[META14]], !llvm.access.group [[ACC_GRP15]] +// CHECK9-NEXT: [[ADD10_I:%.*]] = add nsw i32 [[TMP35]], 1 +// CHECK9-NEXT: store i32 [[ADD10_I]], ptr [[DOTOMP_IV_I]], align 4, !noalias [[META14]], !llvm.access.group [[ACC_GRP15]] +// CHECK9-NEXT: br label [[OMP_INNER_FOR_COND_I]], !llvm.loop [[LOOP16:![0-9]+]] +// CHECK9: .omp_outlined..exit: +// CHECK9-NEXT: ret i32 0 +// +// +// CHECK9-LABEL: define {{[^@]+}}@.omp_task_dup. +// CHECK9-SAME: (ptr noundef [[TMP0:%.*]], ptr noundef [[TMP1:%.*]], i32 noundef signext [[TMP2:%.*]]) #[[ATTR6]] { +// CHECK9-NEXT: entry: +// CHECK9-NEXT: [[DOTADDR:%.*]] = alloca ptr, align 8 +// CHECK9-NEXT: [[DOTADDR1:%.*]] = alloca ptr, align 8 +// CHECK9-NEXT: [[DOTADDR2:%.*]] = alloca i32, align 4 +// CHECK9-NEXT: store ptr [[TMP0]], ptr [[DOTADDR]], align 8 +// CHECK9-NEXT: store ptr [[TMP1]], ptr [[DOTADDR1]], align 8 +// CHECK9-NEXT: store i32 [[TMP2]], ptr [[DOTADDR2]], align 4 +// CHECK9-NEXT: [[TMP3:%.*]] = load ptr, ptr [[DOTADDR]], align 8 +// CHECK9-NEXT: [[TMP4:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T_WITH_PRIVATES:%.*]], ptr [[TMP3]], i32 0, i32 1 +// CHECK9-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT__KMP_PRIVATES_T:%.*]], ptr [[TMP4]], i32 0, i32 0 +// CHECK9-NEXT: call void @_ZN1SIfEC1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[TMP5]]) +// CHECK9-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT__KMP_PRIVATES_T]], ptr [[TMP4]], i32 0, i32 3 +// CHECK9-NEXT: [[ARRAY_BEGIN:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[TMP6]], i32 0, i32 0 +// CHECK9-NEXT: [[ARRAYCTOR_END:%.*]] = getelementptr inbounds [[STRUCT_S:%.*]], ptr [[ARRAY_BEGIN]], i64 2 +// CHECK9-NEXT: br label [[ARRAYCTOR_LOOP:%.*]] +// CHECK9: arrayctor.loop: +// CHECK9-NEXT: [[ARRAYCTOR_CUR:%.*]] = phi ptr [ [[ARRAY_BEGIN]], [[ENTRY:%.*]] ], [ [[ARRAYCTOR_NEXT:%.*]], [[ARRAYCTOR_LOOP]] ] +// CHECK9-NEXT: call void @_ZN1SIfEC1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYCTOR_CUR]]) +// CHECK9-NEXT: [[ARRAYCTOR_NEXT]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAYCTOR_CUR]], i64 1 +// CHECK9-NEXT: [[ARRAYCTOR_DONE:%.*]] = icmp eq ptr [[ARRAYCTOR_NEXT]], [[ARRAYCTOR_END]] +// CHECK9-NEXT: br i1 [[ARRAYCTOR_DONE]], label [[ARRAYCTOR_CONT:%.*]], label [[ARRAYCTOR_LOOP]] +// CHECK9: arrayctor.cont: +// CHECK9-NEXT: ret void +// +// +// CHECK9-LABEL: define {{[^@]+}}@.omp_task_destructor. +// CHECK9-SAME: (i32 noundef signext [[TMP0:%.*]], ptr noalias noundef [[TMP1:%.*]]) #[[ATTR6]] { +// CHECK9-NEXT: entry: +// CHECK9-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 +// CHECK9-NEXT: [[DOTADDR:%.*]] = alloca i32, align 4 +// CHECK9-NEXT: [[DOTADDR1:%.*]] = alloca ptr, align 8 +// CHECK9-NEXT: store i32 [[TMP0]], ptr [[DOTADDR]], align 4 +// CHECK9-NEXT: store ptr [[TMP1]], ptr [[DOTADDR1]], align 8 +// CHECK9-NEXT: [[TMP2:%.*]] = load ptr, ptr [[DOTADDR1]], align 8 +// CHECK9-NEXT: [[TMP3:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T_WITH_PRIVATES:%.*]], ptr [[TMP2]], i32 0, i32 1 +// CHECK9-NEXT: [[TMP4:%.*]] = getelementptr inbounds [[STRUCT__KMP_PRIVATES_T:%.*]], ptr [[TMP3]], i32 0, i32 0 +// CHECK9-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT__KMP_PRIVATES_T]], ptr [[TMP3]], i32 0, i32 3 +// CHECK9-NEXT: [[ARRAY_BEGIN:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[TMP5]], i32 0, i32 0 +// CHECK9-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT_S:%.*]], ptr [[ARRAY_BEGIN]], i64 2 +// CHECK9-NEXT: br label [[ARRAYDESTROY_BODY:%.*]] +// CHECK9: arraydestroy.body: +// CHECK9-NEXT: [[ARRAYDESTROY_ELEMENTPAST:%.*]] = phi ptr [ [[TMP6]], [[ENTRY:%.*]] ], [ [[ARRAYDESTROY_ELEMENT:%.*]], [[ARRAYDESTROY_BODY]] ] +// CHECK9-NEXT: [[ARRAYDESTROY_ELEMENT]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAYDESTROY_ELEMENTPAST]], i64 -1 +// CHECK9-NEXT: call void @_ZN1SIfED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYDESTROY_ELEMENT]]) #[[ATTR3]] +// CHECK9-NEXT: [[ARRAYDESTROY_DONE:%.*]] = icmp eq ptr [[ARRAYDESTROY_ELEMENT]], [[ARRAY_BEGIN]] +// CHECK9-NEXT: br i1 [[ARRAYDESTROY_DONE]], label [[ARRAYDESTROY_DONE2:%.*]], label [[ARRAYDESTROY_BODY]] +// CHECK9: arraydestroy.done2: +// CHECK9-NEXT: call void @_ZN1SIfED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[TMP4]]) #[[ATTR3]] +// CHECK9-NEXT: [[TMP7:%.*]] = load i32, ptr [[RETVAL]], align 4 +// CHECK9-NEXT: ret i32 [[TMP7]] +// +// +// CHECK9-LABEL: define {{[^@]+}}@_ZN1SIfED1Ev +// CHECK9-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]]) unnamed_addr #[[ATTR1]] comdat { +// CHECK9-NEXT: entry: +// CHECK9-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK9-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 +// CHECK9-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK9-NEXT: call void @_ZN1SIfED2Ev(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]]) #[[ATTR3]] +// CHECK9-NEXT: ret void +// +// +// CHECK9-LABEL: define {{[^@]+}}@.omp_task_entry..2 +// CHECK9-SAME: (i32 noundef signext [[TMP0:%.*]], ptr noalias noundef [[TMP1:%.*]]) #[[ATTR6]] { +// CHECK9-NEXT: entry: +// CHECK9-NEXT: [[DOTGLOBAL_TID__ADDR_I:%.*]] = alloca i32, align 4 +// CHECK9-NEXT: [[DOTPART_ID__ADDR_I:%.*]] = alloca ptr, align 8 +// CHECK9-NEXT: [[DOTPRIVATES__ADDR_I:%.*]] = alloca ptr, align 8 +// CHECK9-NEXT: [[DOTCOPY_FN__ADDR_I:%.*]] = alloca ptr, align 8 +// CHECK9-NEXT: [[DOTTASK_T__ADDR_I:%.*]] = alloca ptr, align 8 +// CHECK9-NEXT: [[DOTLB__ADDR_I:%.*]] = alloca i64, align 8 +// CHECK9-NEXT: [[DOTUB__ADDR_I:%.*]] = alloca i64, align 8 +// CHECK9-NEXT: [[DOTST__ADDR_I:%.*]] = alloca i64, align 8 +// CHECK9-NEXT: [[DOTLITER__ADDR_I:%.*]] = alloca i32, align 4 +// CHECK9-NEXT: [[DOTREDUCTIONS__ADDR_I:%.*]] = alloca ptr, align 8 +// CHECK9-NEXT: [[__CONTEXT_ADDR_I:%.*]] = alloca ptr, align 8 +// CHECK9-NEXT: [[I_I:%.*]] = alloca i32, align 4 +// CHECK9-NEXT: [[DOTOMP_IV_I:%.*]] = alloca i32, align 4 +// CHECK9-NEXT: [[DOTADDR:%.*]] = alloca i32, align 4 +// CHECK9-NEXT: [[DOTADDR1:%.*]] = alloca ptr, align 8 +// CHECK9-NEXT: store i32 [[TMP0]], ptr [[DOTADDR]], align 4 +// CHECK9-NEXT: store ptr [[TMP1]], ptr [[DOTADDR1]], align 8 +// CHECK9-NEXT: [[TMP2:%.*]] = load i32, ptr [[DOTADDR]], align 4 +// CHECK9-NEXT: [[TMP3:%.*]] = load ptr, ptr [[DOTADDR1]], align 8 +// CHECK9-NEXT: [[TMP4:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T_WITH_PRIVATES_1:%.*]], ptr [[TMP3]], i32 0, i32 0 +// CHECK9-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T:%.*]], ptr [[TMP4]], i32 0, i32 2 +// CHECK9-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP4]], i32 0, i32 0 +// CHECK9-NEXT: [[TMP7:%.*]] = load ptr, ptr [[TMP6]], align 8 +// CHECK9-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP4]], i32 0, i32 5 +// CHECK9-NEXT: [[TMP9:%.*]] = load i64, ptr [[TMP8]], align 8 +// CHECK9-NEXT: [[TMP10:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP4]], i32 0, i32 6 +// CHECK9-NEXT: [[TMP11:%.*]] = load i64, ptr [[TMP10]], align 8 +// CHECK9-NEXT: [[TMP12:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP4]], i32 0, i32 7 +// CHECK9-NEXT: [[TMP13:%.*]] = load i64, ptr [[TMP12]], align 8 +// CHECK9-NEXT: [[TMP14:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP4]], i32 0, i32 8 +// CHECK9-NEXT: [[TMP15:%.*]] = load i32, ptr [[TMP14]], align 8 +// CHECK9-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP4]], i32 0, i32 9 +// CHECK9-NEXT: [[TMP17:%.*]] = load ptr, ptr [[TMP16]], align 8 +// CHECK9-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META19:![0-9]+]]) +// CHECK9-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META22:![0-9]+]]) +// CHECK9-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META24:![0-9]+]]) +// CHECK9-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META26:![0-9]+]]) +// CHECK9-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META28:![0-9]+]]) +// CHECK9-NEXT: store i32 [[TMP2]], ptr [[DOTGLOBAL_TID__ADDR_I]], align 4, !noalias [[META30:![0-9]+]] +// CHECK9-NEXT: store ptr [[TMP5]], ptr [[DOTPART_ID__ADDR_I]], align 8, !noalias [[META30]] +// CHECK9-NEXT: store ptr null, ptr [[DOTPRIVATES__ADDR_I]], align 8, !noalias [[META30]] +// CHECK9-NEXT: store ptr null, ptr [[DOTCOPY_FN__ADDR_I]], align 8, !noalias [[META30]] +// CHECK9-NEXT: store ptr [[TMP3]], ptr [[DOTTASK_T__ADDR_I]], align 8, !noalias [[META30]] +// CHECK9-NEXT: store i64 [[TMP9]], ptr [[DOTLB__ADDR_I]], align 8, !noalias [[META30]] +// CHECK9-NEXT: store i64 [[TMP11]], ptr [[DOTUB__ADDR_I]], align 8, !noalias [[META30]] +// CHECK9-NEXT: store i64 [[TMP13]], ptr [[DOTST__ADDR_I]], align 8, !noalias [[META30]] +// CHECK9-NEXT: store i32 [[TMP15]], ptr [[DOTLITER__ADDR_I]], align 4, !noalias [[META30]] +// CHECK9-NEXT: store ptr [[TMP17]], ptr [[DOTREDUCTIONS__ADDR_I]], align 8, !noalias [[META30]] +// CHECK9-NEXT: store ptr [[TMP7]], ptr [[__CONTEXT_ADDR_I]], align 8, !noalias [[META30]] +// CHECK9-NEXT: [[TMP18:%.*]] = load ptr, ptr [[__CONTEXT_ADDR_I]], align 8, !noalias [[META30]] +// CHECK9-NEXT: [[TMP19:%.*]] = load i64, ptr [[DOTLB__ADDR_I]], align 8, !noalias [[META30]] +// CHECK9-NEXT: [[CONV_I:%.*]] = trunc i64 [[TMP19]] to i32 +// CHECK9-NEXT: store i32 [[CONV_I]], ptr [[DOTOMP_IV_I]], align 4, !noalias [[META30]] +// CHECK9-NEXT: br label [[OMP_INNER_FOR_COND_I:%.*]] +// CHECK9: omp.inner.for.cond.i: +// CHECK9-NEXT: [[TMP20:%.*]] = load i32, ptr [[DOTOMP_IV_I]], align 4, !noalias [[META30]], !llvm.access.group [[ACC_GRP31:![0-9]+]] +// CHECK9-NEXT: [[CONV1_I:%.*]] = sext i32 [[TMP20]] to i64 +// CHECK9-NEXT: [[TMP21:%.*]] = load i64, ptr [[DOTUB__ADDR_I]], align 8, !noalias [[META30]], !llvm.access.group [[ACC_GRP31]] +// CHECK9-NEXT: [[CMP_I:%.*]] = icmp ule i64 [[CONV1_I]], [[TMP21]] +// CHECK9-NEXT: br i1 [[CMP_I]], label [[OMP_INNER_FOR_BODY_I:%.*]], label [[DOTOMP_OUTLINED__1_EXIT:%.*]] +// CHECK9: omp.inner.for.body.i: +// CHECK9-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IV_I]], align 4, !noalias [[META30]], !llvm.access.group [[ACC_GRP31]] +// CHECK9-NEXT: store i32 [[TMP22]], ptr [[I_I]], align 4, !noalias [[META30]], !llvm.access.group [[ACC_GRP31]] +// CHECK9-NEXT: [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IV_I]], align 4, !noalias [[META30]], !llvm.access.group [[ACC_GRP31]] +// CHECK9-NEXT: [[ADD2_I:%.*]] = add nsw i32 [[TMP23]], 1 +// CHECK9-NEXT: store i32 [[ADD2_I]], ptr [[DOTOMP_IV_I]], align 4, !noalias [[META30]], !llvm.access.group [[ACC_GRP31]] +// CHECK9-NEXT: br label [[OMP_INNER_FOR_COND_I]], !llvm.loop [[LOOP32:![0-9]+]] +// CHECK9: .omp_outlined..1.exit: +// CHECK9-NEXT: ret i32 0 +// +// +// CHECK9-LABEL: define {{[^@]+}}@_Z5tmainIiET_v +// CHECK9-SAME: () #[[ATTR1]] comdat { +// CHECK9-NEXT: entry: +// CHECK9-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 +// CHECK9-NEXT: [[TEST:%.*]] = alloca [[STRUCT_S_2:%.*]], align 4 +// CHECK9-NEXT: [[T_VAR:%.*]] = alloca i32, align 4 +// CHECK9-NEXT: [[VEC:%.*]] = alloca [2 x i32], align 4 +// CHECK9-NEXT: [[S_ARR:%.*]] = alloca [2 x %struct.S.2], align 4 +// CHECK9-NEXT: [[VAR:%.*]] = alloca ptr, align 8 +// CHECK9-NEXT: [[AGG_CAPTURED:%.*]] = alloca [[STRUCT_ANON_3:%.*]], align 1 +// CHECK9-NEXT: [[TMP:%.*]] = alloca i32, align 4 +// CHECK9-NEXT: [[_TMP1:%.*]] = alloca ptr, align 8 +// CHECK9-NEXT: [[TMP0:%.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GLOB1]]) +// CHECK9-NEXT: call void @_ZN1SIiEC1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[TEST]]) +// CHECK9-NEXT: store i32 0, ptr [[T_VAR]], align 4 +// CHECK9-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[VEC]], ptr align 4 @__const._Z5tmainIiET_v.vec, i64 8, i1 false) +// CHECK9-NEXT: [[ARRAYINIT_BEGIN:%.*]] = getelementptr inbounds [2 x %struct.S.2], ptr [[S_ARR]], i64 0, i64 0 +// CHECK9-NEXT: call void @_ZN1SIiEC1Ei(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYINIT_BEGIN]], i32 noundef signext 1) +// CHECK9-NEXT: [[ARRAYINIT_ELEMENT:%.*]] = getelementptr inbounds [[STRUCT_S_2]], ptr [[ARRAYINIT_BEGIN]], i64 1 +// CHECK9-NEXT: call void @_ZN1SIiEC1Ei(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYINIT_ELEMENT]], i32 noundef signext 2) +// CHECK9-NEXT: store ptr [[TEST]], ptr [[VAR]], align 8 +// CHECK9-NEXT: call void @__kmpc_taskgroup(ptr @[[GLOB1]], i32 [[TMP0]]) +// CHECK9-NEXT: store ptr undef, ptr [[_TMP1]], align 8 +// CHECK9-NEXT: [[TMP1:%.*]] = call ptr @__kmpc_omp_task_alloc(ptr @[[GLOB1]], i32 [[TMP0]], i32 9, i64 104, i64 1, ptr @.omp_task_entry..5) +// CHECK9-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T_WITH_PRIVATES_4:%.*]], ptr [[TMP1]], i32 0, i32 0 +// CHECK9-NEXT: [[TMP3:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T_WITH_PRIVATES_4]], ptr [[TMP1]], i32 0, i32 1 +// CHECK9-NEXT: [[TMP4:%.*]] = getelementptr inbounds [[STRUCT__KMP_PRIVATES_T_5:%.*]], ptr [[TMP3]], i32 0, i32 0 +// CHECK9-NEXT: call void @_ZN1SIiEC1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[TMP4]]) +// CHECK9-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT__KMP_PRIVATES_T_5]], ptr [[TMP3]], i32 0, i32 3 +// CHECK9-NEXT: [[ARRAY_BEGIN:%.*]] = getelementptr inbounds [2 x %struct.S.2], ptr [[TMP5]], i32 0, i32 0 +// CHECK9-NEXT: [[ARRAYCTOR_END:%.*]] = getelementptr inbounds [[STRUCT_S_2]], ptr [[ARRAY_BEGIN]], i64 2 +// CHECK9-NEXT: br label [[ARRAYCTOR_LOOP:%.*]] +// CHECK9: arrayctor.loop: +// CHECK9-NEXT: [[ARRAYCTOR_CUR:%.*]] = phi ptr [ [[ARRAY_BEGIN]], [[ENTRY:%.*]] ], [ [[ARRAYCTOR_NEXT:%.*]], [[ARRAYCTOR_LOOP]] ] +// CHECK9-NEXT: call void @_ZN1SIiEC1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYCTOR_CUR]]) +// CHECK9-NEXT: [[ARRAYCTOR_NEXT]] = getelementptr inbounds [[STRUCT_S_2]], ptr [[ARRAYCTOR_CUR]], i64 1 +// CHECK9-NEXT: [[ARRAYCTOR_DONE:%.*]] = icmp eq ptr [[ARRAYCTOR_NEXT]], [[ARRAYCTOR_END]] +// CHECK9-NEXT: br i1 [[ARRAYCTOR_DONE]], label [[ARRAYCTOR_CONT:%.*]], label [[ARRAYCTOR_LOOP]] +// CHECK9: arrayctor.cont: +// CHECK9-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T:%.*]], ptr [[TMP2]], i32 0, i32 3 +// CHECK9-NEXT: store ptr @.omp_task_destructor..7, ptr [[TMP6]], align 8 +// CHECK9-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP2]], i32 0, i32 5 +// CHECK9-NEXT: store i64 0, ptr [[TMP7]], align 8 +// CHECK9-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP2]], i32 0, i32 6 +// CHECK9-NEXT: store i64 1, ptr [[TMP8]], align 8 +// CHECK9-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP2]], i32 0, i32 7 +// CHECK9-NEXT: store i64 1, ptr [[TMP9]], align 8 +// CHECK9-NEXT: [[TMP10:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP2]], i32 0, i32 9 +// CHECK9-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[TMP10]], i8 0, i64 8, i1 false) +// CHECK9-NEXT: [[TMP11:%.*]] = load i64, ptr [[TMP9]], align 8 +// CHECK9-NEXT: call void @__kmpc_taskloop(ptr @[[GLOB1]], i32 [[TMP0]], ptr [[TMP1]], i32 1, ptr [[TMP7]], ptr [[TMP8]], i64 [[TMP11]], i32 1, i32 0, i64 0, ptr @.omp_task_dup..6) +// CHECK9-NEXT: call void @__kmpc_end_taskgroup(ptr @[[GLOB1]], i32 [[TMP0]]) +// CHECK9-NEXT: store i32 0, ptr [[RETVAL]], align 4 +// CHECK9-NEXT: [[ARRAY_BEGIN2:%.*]] = getelementptr inbounds [2 x %struct.S.2], ptr [[S_ARR]], i32 0, i32 0 +// CHECK9-NEXT: [[TMP12:%.*]] = getelementptr inbounds [[STRUCT_S_2]], ptr [[ARRAY_BEGIN2]], i64 2 +// CHECK9-NEXT: br label [[ARRAYDESTROY_BODY:%.*]] +// CHECK9: arraydestroy.body: +// CHECK9-NEXT: [[ARRAYDESTROY_ELEMENTPAST:%.*]] = phi ptr [ [[TMP12]], [[ARRAYCTOR_CONT]] ], [ [[ARRAYDESTROY_ELEMENT:%.*]], [[ARRAYDESTROY_BODY]] ] +// CHECK9-NEXT: [[ARRAYDESTROY_ELEMENT]] = getelementptr inbounds [[STRUCT_S_2]], ptr [[ARRAYDESTROY_ELEMENTPAST]], i64 -1 +// CHECK9-NEXT: call void @_ZN1SIiED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYDESTROY_ELEMENT]]) #[[ATTR3]] +// CHECK9-NEXT: [[ARRAYDESTROY_DONE:%.*]] = icmp eq ptr [[ARRAYDESTROY_ELEMENT]], [[ARRAY_BEGIN2]] +// CHECK9-NEXT: br i1 [[ARRAYDESTROY_DONE]], label [[ARRAYDESTROY_DONE3:%.*]], label [[ARRAYDESTROY_BODY]] +// CHECK9: arraydestroy.done3: +// CHECK9-NEXT: call void @_ZN1SIiED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[TEST]]) #[[ATTR3]] +// CHECK9-NEXT: [[TMP13:%.*]] = load i32, ptr [[RETVAL]], align 4 +// CHECK9-NEXT: ret i32 [[TMP13]] +// +// +// CHECK9-LABEL: define {{[^@]+}}@_ZN1SIfEC2Ev +// CHECK9-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]]) unnamed_addr #[[ATTR1]] comdat { +// CHECK9-NEXT: entry: +// CHECK9-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK9-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 +// CHECK9-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK9-NEXT: [[F:%.*]] = getelementptr inbounds [[STRUCT_S:%.*]], ptr [[THIS1]], i32 0, i32 0 +// CHECK9-NEXT: store float 0.000000e+00, ptr [[F]], align 4 +// CHECK9-NEXT: ret void +// +// +// CHECK9-LABEL: define {{[^@]+}}@_ZN1SIfEC2Ef +// CHECK9-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]], float noundef [[A:%.*]]) unnamed_addr #[[ATTR1]] comdat { +// CHECK9-NEXT: entry: +// CHECK9-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK9-NEXT: [[A_ADDR:%.*]] = alloca float, align 4 +// CHECK9-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 +// CHECK9-NEXT: store float [[A]], ptr [[A_ADDR]], align 4 +// CHECK9-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK9-NEXT: [[F:%.*]] = getelementptr inbounds [[STRUCT_S:%.*]], ptr [[THIS1]], i32 0, i32 0 +// CHECK9-NEXT: [[TMP0:%.*]] = load float, ptr [[A_ADDR]], align 4 +// CHECK9-NEXT: store float [[TMP0]], ptr [[F]], align 4 +// CHECK9-NEXT: ret void +// +// +// CHECK9-LABEL: define {{[^@]+}}@_ZN1SIfED2Ev +// CHECK9-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]]) unnamed_addr #[[ATTR1]] comdat { +// CHECK9-NEXT: entry: +// CHECK9-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK9-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 +// CHECK9-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK9-NEXT: ret void +// +// +// CHECK9-LABEL: define {{[^@]+}}@_ZN1SIiEC1Ev +// CHECK9-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]]) unnamed_addr #[[ATTR1]] comdat { +// CHECK9-NEXT: entry: +// CHECK9-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK9-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 +// CHECK9-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK9-NEXT: call void @_ZN1SIiEC2Ev(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]]) +// CHECK9-NEXT: ret void +// +// +// CHECK9-LABEL: define {{[^@]+}}@_ZN1SIiEC1Ei +// CHECK9-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]], i32 noundef signext [[A:%.*]]) unnamed_addr #[[ATTR1]] comdat { +// CHECK9-NEXT: entry: +// CHECK9-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK9-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 +// CHECK9-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 +// CHECK9-NEXT: store i32 [[A]], ptr [[A_ADDR]], align 4 +// CHECK9-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK9-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4 +// CHECK9-NEXT: call void @_ZN1SIiEC2Ei(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]], i32 noundef signext [[TMP0]]) +// CHECK9-NEXT: ret void +// +// +// CHECK9-LABEL: define {{[^@]+}}@.omp_task_privates_map..4 +// CHECK9-SAME: (ptr noalias noundef [[TMP0:%.*]], ptr noalias noundef [[TMP1:%.*]], ptr noalias noundef [[TMP2:%.*]], ptr noalias noundef [[TMP3:%.*]], ptr noalias noundef [[TMP4:%.*]]) #[[ATTR5]] { +// CHECK9-NEXT: entry: +// CHECK9-NEXT: [[DOTADDR:%.*]] = alloca ptr, align 8 +// CHECK9-NEXT: [[DOTADDR1:%.*]] = alloca ptr, align 8 +// CHECK9-NEXT: [[DOTADDR2:%.*]] = alloca ptr, align 8 +// CHECK9-NEXT: [[DOTADDR3:%.*]] = alloca ptr, align 8 +// CHECK9-NEXT: [[DOTADDR4:%.*]] = alloca ptr, align 8 +// CHECK9-NEXT: store ptr [[TMP0]], ptr [[DOTADDR]], align 8 +// CHECK9-NEXT: store ptr [[TMP1]], ptr [[DOTADDR1]], align 8 +// CHECK9-NEXT: store ptr [[TMP2]], ptr [[DOTADDR2]], align 8 +// CHECK9-NEXT: store ptr [[TMP3]], ptr [[DOTADDR3]], align 8 +// CHECK9-NEXT: store ptr [[TMP4]], ptr [[DOTADDR4]], align 8 +// CHECK9-NEXT: [[TMP5:%.*]] = load ptr, ptr [[DOTADDR]], align 8 +// CHECK9-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT__KMP_PRIVATES_T_5:%.*]], ptr [[TMP5]], i32 0, i32 0 +// CHECK9-NEXT: [[TMP7:%.*]] = load ptr, ptr [[DOTADDR4]], align 8 +// CHECK9-NEXT: store ptr [[TMP6]], ptr [[TMP7]], align 8 +// CHECK9-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT__KMP_PRIVATES_T_5]], ptr [[TMP5]], i32 0, i32 1 +// CHECK9-NEXT: [[TMP9:%.*]] = load ptr, ptr [[DOTADDR1]], align 8 +// CHECK9-NEXT: store ptr [[TMP8]], ptr [[TMP9]], align 8 +// CHECK9-NEXT: [[TMP10:%.*]] = getelementptr inbounds [[STRUCT__KMP_PRIVATES_T_5]], ptr [[TMP5]], i32 0, i32 2 +// CHECK9-NEXT: [[TMP11:%.*]] = load ptr, ptr [[DOTADDR2]], align 8 +// CHECK9-NEXT: store ptr [[TMP10]], ptr [[TMP11]], align 8 +// CHECK9-NEXT: [[TMP12:%.*]] = getelementptr inbounds [[STRUCT__KMP_PRIVATES_T_5]], ptr [[TMP5]], i32 0, i32 3 +// CHECK9-NEXT: [[TMP13:%.*]] = load ptr, ptr [[DOTADDR3]], align 8 +// CHECK9-NEXT: store ptr [[TMP12]], ptr [[TMP13]], align 8 +// CHECK9-NEXT: ret void +// +// +// CHECK9-LABEL: define {{[^@]+}}@.omp_task_entry..5 +// CHECK9-SAME: (i32 noundef signext [[TMP0:%.*]], ptr noalias noundef [[TMP1:%.*]]) #[[ATTR6]] { +// CHECK9-NEXT: entry: +// CHECK9-NEXT: [[DOTGLOBAL_TID__ADDR_I:%.*]] = alloca i32, align 4 +// CHECK9-NEXT: [[DOTPART_ID__ADDR_I:%.*]] = alloca ptr, align 8 +// CHECK9-NEXT: [[DOTPRIVATES__ADDR_I:%.*]] = alloca ptr, align 8 +// CHECK9-NEXT: [[DOTCOPY_FN__ADDR_I:%.*]] = alloca ptr, align 8 +// CHECK9-NEXT: [[DOTTASK_T__ADDR_I:%.*]] = alloca ptr, align 8 +// CHECK9-NEXT: [[DOTLB__ADDR_I:%.*]] = alloca i64, align 8 +// CHECK9-NEXT: [[DOTUB__ADDR_I:%.*]] = alloca i64, align 8 +// CHECK9-NEXT: [[DOTST__ADDR_I:%.*]] = alloca i64, align 8 +// CHECK9-NEXT: [[DOTLITER__ADDR_I:%.*]] = alloca i32, align 4 +// CHECK9-NEXT: [[DOTREDUCTIONS__ADDR_I:%.*]] = alloca ptr, align 8 +// CHECK9-NEXT: [[__CONTEXT_ADDR_I:%.*]] = alloca ptr, align 8 +// CHECK9-NEXT: [[DOTPRIV_PTR_ADDR_I:%.*]] = alloca ptr, align 8 +// CHECK9-NEXT: [[DOTPRIV_PTR_ADDR1_I:%.*]] = alloca ptr, align 8 +// CHECK9-NEXT: [[DOTPRIV_PTR_ADDR2_I:%.*]] = alloca ptr, align 8 +// CHECK9-NEXT: [[DOTPRIV_PTR_ADDR3_I:%.*]] = alloca ptr, align 8 +// CHECK9-NEXT: [[TMP_I:%.*]] = alloca ptr, align 8 +// CHECK9-NEXT: [[TMP5_I:%.*]] = alloca ptr, align 8 +// CHECK9-NEXT: [[I_I:%.*]] = alloca i32, align 4 +// CHECK9-NEXT: [[DOTOMP_IV_I:%.*]] = alloca i32, align 4 +// CHECK9-NEXT: [[DOTADDR:%.*]] = alloca i32, align 4 +// CHECK9-NEXT: [[DOTADDR1:%.*]] = alloca ptr, align 8 +// CHECK9-NEXT: store i32 [[TMP0]], ptr [[DOTADDR]], align 4 +// CHECK9-NEXT: store ptr [[TMP1]], ptr [[DOTADDR1]], align 8 +// CHECK9-NEXT: [[TMP2:%.*]] = load i32, ptr [[DOTADDR]], align 4 +// CHECK9-NEXT: [[TMP3:%.*]] = load ptr, ptr [[DOTADDR1]], align 8 +// CHECK9-NEXT: [[TMP4:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T_WITH_PRIVATES_4:%.*]], ptr [[TMP3]], i32 0, i32 0 +// CHECK9-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T:%.*]], ptr [[TMP4]], i32 0, i32 2 +// CHECK9-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP4]], i32 0, i32 0 +// CHECK9-NEXT: [[TMP7:%.*]] = load ptr, ptr [[TMP6]], align 8 +// CHECK9-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T_WITH_PRIVATES_4]], ptr [[TMP3]], i32 0, i32 1 +// CHECK9-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP4]], i32 0, i32 5 +// CHECK9-NEXT: [[TMP10:%.*]] = load i64, ptr [[TMP9]], align 8 +// CHECK9-NEXT: [[TMP11:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP4]], i32 0, i32 6 +// CHECK9-NEXT: [[TMP12:%.*]] = load i64, ptr [[TMP11]], align 8 +// CHECK9-NEXT: [[TMP13:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP4]], i32 0, i32 7 +// CHECK9-NEXT: [[TMP14:%.*]] = load i64, ptr [[TMP13]], align 8 +// CHECK9-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP4]], i32 0, i32 8 +// CHECK9-NEXT: [[TMP16:%.*]] = load i32, ptr [[TMP15]], align 8 +// CHECK9-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP4]], i32 0, i32 9 +// CHECK9-NEXT: [[TMP18:%.*]] = load ptr, ptr [[TMP17]], align 8 +// CHECK9-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META34:![0-9]+]]) +// CHECK9-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META37:![0-9]+]]) +// CHECK9-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META39:![0-9]+]]) +// CHECK9-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META41:![0-9]+]]) +// CHECK9-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META43:![0-9]+]]) +// CHECK9-NEXT: store i32 [[TMP2]], ptr [[DOTGLOBAL_TID__ADDR_I]], align 4, !noalias [[META45:![0-9]+]] +// CHECK9-NEXT: store ptr [[TMP5]], ptr [[DOTPART_ID__ADDR_I]], align 8, !noalias [[META45]] +// CHECK9-NEXT: store ptr [[TMP8]], ptr [[DOTPRIVATES__ADDR_I]], align 8, !noalias [[META45]] +// CHECK9-NEXT: store ptr @.omp_task_privates_map..4, ptr [[DOTCOPY_FN__ADDR_I]], align 8, !noalias [[META45]] +// CHECK9-NEXT: store ptr [[TMP3]], ptr [[DOTTASK_T__ADDR_I]], align 8, !noalias [[META45]] +// CHECK9-NEXT: store i64 [[TMP10]], ptr [[DOTLB__ADDR_I]], align 8, !noalias [[META45]] +// CHECK9-NEXT: store i64 [[TMP12]], ptr [[DOTUB__ADDR_I]], align 8, !noalias [[META45]] +// CHECK9-NEXT: store i64 [[TMP14]], ptr [[DOTST__ADDR_I]], align 8, !noalias [[META45]] +// CHECK9-NEXT: store i32 [[TMP16]], ptr [[DOTLITER__ADDR_I]], align 4, !noalias [[META45]] +// CHECK9-NEXT: store ptr [[TMP18]], ptr [[DOTREDUCTIONS__ADDR_I]], align 8, !noalias [[META45]] +// CHECK9-NEXT: store ptr [[TMP7]], ptr [[__CONTEXT_ADDR_I]], align 8, !noalias [[META45]] +// CHECK9-NEXT: [[TMP19:%.*]] = load ptr, ptr [[__CONTEXT_ADDR_I]], align 8, !noalias [[META45]] +// CHECK9-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTCOPY_FN__ADDR_I]], align 8, !noalias [[META45]] +// CHECK9-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTPRIVATES__ADDR_I]], align 8, !noalias [[META45]] +// CHECK9-NEXT: call void [[TMP20]](ptr [[TMP21]], ptr [[DOTPRIV_PTR_ADDR_I]], ptr [[DOTPRIV_PTR_ADDR1_I]], ptr [[DOTPRIV_PTR_ADDR2_I]], ptr [[DOTPRIV_PTR_ADDR3_I]]) #[[ATTR3]] +// CHECK9-NEXT: [[TMP22:%.*]] = load ptr, ptr [[DOTPRIV_PTR_ADDR_I]], align 8, !noalias [[META45]] +// CHECK9-NEXT: [[TMP23:%.*]] = load ptr, ptr [[DOTPRIV_PTR_ADDR1_I]], align 8, !noalias [[META45]] +// CHECK9-NEXT: [[TMP24:%.*]] = load ptr, ptr [[DOTPRIV_PTR_ADDR2_I]], align 8, !noalias [[META45]] +// CHECK9-NEXT: [[TMP25:%.*]] = load ptr, ptr [[DOTPRIV_PTR_ADDR3_I]], align 8, !noalias [[META45]] +// CHECK9-NEXT: store ptr [[TMP25]], ptr [[TMP_I]], align 8, !noalias [[META45]] +// CHECK9-NEXT: store ptr undef, ptr [[TMP5_I]], align 8, !noalias [[META45]] +// CHECK9-NEXT: [[TMP26:%.*]] = load i64, ptr [[DOTLB__ADDR_I]], align 8, !noalias [[META45]] +// CHECK9-NEXT: [[CONV_I:%.*]] = trunc i64 [[TMP26]] to i32 +// CHECK9-NEXT: store i32 [[CONV_I]], ptr [[DOTOMP_IV_I]], align 4, !noalias [[META45]] +// CHECK9-NEXT: br label [[OMP_INNER_FOR_COND_I:%.*]] +// CHECK9: omp.inner.for.cond.i: +// CHECK9-NEXT: [[TMP27:%.*]] = load i32, ptr [[DOTOMP_IV_I]], align 4, !noalias [[META45]], !llvm.access.group [[ACC_GRP46:![0-9]+]] +// CHECK9-NEXT: [[CONV6_I:%.*]] = sext i32 [[TMP27]] to i64 +// CHECK9-NEXT: [[TMP28:%.*]] = load i64, ptr [[DOTUB__ADDR_I]], align 8, !noalias [[META45]], !llvm.access.group [[ACC_GRP46]] +// CHECK9-NEXT: [[CMP_I:%.*]] = icmp ule i64 [[CONV6_I]], [[TMP28]] +// CHECK9-NEXT: br i1 [[CMP_I]], label [[OMP_INNER_FOR_BODY_I:%.*]], label [[DOTOMP_OUTLINED__3_EXIT:%.*]] +// CHECK9: omp.inner.for.body.i: +// CHECK9-NEXT: [[TMP29:%.*]] = load i32, ptr [[DOTOMP_IV_I]], align 4, !noalias [[META45]], !llvm.access.group [[ACC_GRP46]] +// CHECK9-NEXT: store i32 [[TMP29]], ptr [[I_I]], align 4, !noalias [[META45]], !llvm.access.group [[ACC_GRP46]] +// CHECK9-NEXT: [[TMP30:%.*]] = load i32, ptr [[TMP22]], align 4, !llvm.access.group [[ACC_GRP46]] +// CHECK9-NEXT: [[TMP31:%.*]] = load i32, ptr [[I_I]], align 4, !noalias [[META45]], !llvm.access.group [[ACC_GRP46]] +// CHECK9-NEXT: [[IDXPROM_I:%.*]] = sext i32 [[TMP31]] to i64 +// CHECK9-NEXT: [[ARRAYIDX_I:%.*]] = getelementptr inbounds [2 x i32], ptr [[TMP23]], i64 0, i64 [[IDXPROM_I]] +// CHECK9-NEXT: store i32 [[TMP30]], ptr [[ARRAYIDX_I]], align 4, !llvm.access.group [[ACC_GRP46]] +// CHECK9-NEXT: [[TMP32:%.*]] = load ptr, ptr [[TMP_I]], align 8, !noalias [[META45]], !llvm.access.group [[ACC_GRP46]] +// CHECK9-NEXT: [[TMP33:%.*]] = load i32, ptr [[I_I]], align 4, !noalias [[META45]], !llvm.access.group [[ACC_GRP46]] +// CHECK9-NEXT: [[IDXPROM7_I:%.*]] = sext i32 [[TMP33]] to i64 +// CHECK9-NEXT: [[ARRAYIDX8_I:%.*]] = getelementptr inbounds [2 x %struct.S.2], ptr [[TMP24]], i64 0, i64 [[IDXPROM7_I]] +// CHECK9-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[ARRAYIDX8_I]], ptr align 4 [[TMP32]], i64 4, i1 false), !llvm.access.group [[ACC_GRP46]] +// CHECK9-NEXT: [[TMP34:%.*]] = load i32, ptr [[DOTOMP_IV_I]], align 4, !noalias [[META45]], !llvm.access.group [[ACC_GRP46]] +// CHECK9-NEXT: [[ADD9_I:%.*]] = add nsw i32 [[TMP34]], 1 +// CHECK9-NEXT: store i32 [[ADD9_I]], ptr [[DOTOMP_IV_I]], align 4, !noalias [[META45]], !llvm.access.group [[ACC_GRP46]] +// CHECK9-NEXT: br label [[OMP_INNER_FOR_COND_I]], !llvm.loop [[LOOP47:![0-9]+]] +// CHECK9: .omp_outlined..3.exit: +// CHECK9-NEXT: ret i32 0 +// +// +// CHECK9-LABEL: define {{[^@]+}}@.omp_task_dup..6 +// CHECK9-SAME: (ptr noundef [[TMP0:%.*]], ptr noundef [[TMP1:%.*]], i32 noundef signext [[TMP2:%.*]]) #[[ATTR6]] { +// CHECK9-NEXT: entry: +// CHECK9-NEXT: [[DOTADDR:%.*]] = alloca ptr, align 8 +// CHECK9-NEXT: [[DOTADDR1:%.*]] = alloca ptr, align 8 +// CHECK9-NEXT: [[DOTADDR2:%.*]] = alloca i32, align 4 +// CHECK9-NEXT: store ptr [[TMP0]], ptr [[DOTADDR]], align 8 +// CHECK9-NEXT: store ptr [[TMP1]], ptr [[DOTADDR1]], align 8 +// CHECK9-NEXT: store i32 [[TMP2]], ptr [[DOTADDR2]], align 4 +// CHECK9-NEXT: [[TMP3:%.*]] = load ptr, ptr [[DOTADDR]], align 8 +// CHECK9-NEXT: [[TMP4:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T_WITH_PRIVATES_4:%.*]], ptr [[TMP3]], i32 0, i32 1 +// CHECK9-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT__KMP_PRIVATES_T_5:%.*]], ptr [[TMP4]], i32 0, i32 0 +// CHECK9-NEXT: call void @_ZN1SIiEC1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[TMP5]]) +// CHECK9-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT__KMP_PRIVATES_T_5]], ptr [[TMP4]], i32 0, i32 3 +// CHECK9-NEXT: [[ARRAY_BEGIN:%.*]] = getelementptr inbounds [2 x %struct.S.2], ptr [[TMP6]], i32 0, i32 0 +// CHECK9-NEXT: [[ARRAYCTOR_END:%.*]] = getelementptr inbounds [[STRUCT_S_2:%.*]], ptr [[ARRAY_BEGIN]], i64 2 +// CHECK9-NEXT: br label [[ARRAYCTOR_LOOP:%.*]] +// CHECK9: arrayctor.loop: +// CHECK9-NEXT: [[ARRAYCTOR_CUR:%.*]] = phi ptr [ [[ARRAY_BEGIN]], [[ENTRY:%.*]] ], [ [[ARRAYCTOR_NEXT:%.*]], [[ARRAYCTOR_LOOP]] ] +// CHECK9-NEXT: call void @_ZN1SIiEC1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYCTOR_CUR]]) +// CHECK9-NEXT: [[ARRAYCTOR_NEXT]] = getelementptr inbounds [[STRUCT_S_2]], ptr [[ARRAYCTOR_CUR]], i64 1 +// CHECK9-NEXT: [[ARRAYCTOR_DONE:%.*]] = icmp eq ptr [[ARRAYCTOR_NEXT]], [[ARRAYCTOR_END]] +// CHECK9-NEXT: br i1 [[ARRAYCTOR_DONE]], label [[ARRAYCTOR_CONT:%.*]], label [[ARRAYCTOR_LOOP]] +// CHECK9: arrayctor.cont: +// CHECK9-NEXT: ret void +// +// +// CHECK9-LABEL: define {{[^@]+}}@.omp_task_destructor..7 +// CHECK9-SAME: (i32 noundef signext [[TMP0:%.*]], ptr noalias noundef [[TMP1:%.*]]) #[[ATTR6]] { +// CHECK9-NEXT: entry: +// CHECK9-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 +// CHECK9-NEXT: [[DOTADDR:%.*]] = alloca i32, align 4 +// CHECK9-NEXT: [[DOTADDR1:%.*]] = alloca ptr, align 8 +// CHECK9-NEXT: store i32 [[TMP0]], ptr [[DOTADDR]], align 4 +// CHECK9-NEXT: store ptr [[TMP1]], ptr [[DOTADDR1]], align 8 +// CHECK9-NEXT: [[TMP2:%.*]] = load ptr, ptr [[DOTADDR1]], align 8 +// CHECK9-NEXT: [[TMP3:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T_WITH_PRIVATES_4:%.*]], ptr [[TMP2]], i32 0, i32 1 +// CHECK9-NEXT: [[TMP4:%.*]] = getelementptr inbounds [[STRUCT__KMP_PRIVATES_T_5:%.*]], ptr [[TMP3]], i32 0, i32 0 +// CHECK9-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT__KMP_PRIVATES_T_5]], ptr [[TMP3]], i32 0, i32 3 +// CHECK9-NEXT: [[ARRAY_BEGIN:%.*]] = getelementptr inbounds [2 x %struct.S.2], ptr [[TMP5]], i32 0, i32 0 +// CHECK9-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT_S_2:%.*]], ptr [[ARRAY_BEGIN]], i64 2 +// CHECK9-NEXT: br label [[ARRAYDESTROY_BODY:%.*]] +// CHECK9: arraydestroy.body: +// CHECK9-NEXT: [[ARRAYDESTROY_ELEMENTPAST:%.*]] = phi ptr [ [[TMP6]], [[ENTRY:%.*]] ], [ [[ARRAYDESTROY_ELEMENT:%.*]], [[ARRAYDESTROY_BODY]] ] +// CHECK9-NEXT: [[ARRAYDESTROY_ELEMENT]] = getelementptr inbounds [[STRUCT_S_2]], ptr [[ARRAYDESTROY_ELEMENTPAST]], i64 -1 +// CHECK9-NEXT: call void @_ZN1SIiED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYDESTROY_ELEMENT]]) #[[ATTR3]] +// CHECK9-NEXT: [[ARRAYDESTROY_DONE:%.*]] = icmp eq ptr [[ARRAYDESTROY_ELEMENT]], [[ARRAY_BEGIN]] +// CHECK9-NEXT: br i1 [[ARRAYDESTROY_DONE]], label [[ARRAYDESTROY_DONE2:%.*]], label [[ARRAYDESTROY_BODY]] +// CHECK9: arraydestroy.done2: +// CHECK9-NEXT: call void @_ZN1SIiED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[TMP4]]) #[[ATTR3]] +// CHECK9-NEXT: [[TMP7:%.*]] = load i32, ptr [[RETVAL]], align 4 +// CHECK9-NEXT: ret i32 [[TMP7]] +// +// +// CHECK9-LABEL: define {{[^@]+}}@_ZN1SIiED1Ev +// CHECK9-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]]) unnamed_addr #[[ATTR1]] comdat { +// CHECK9-NEXT: entry: +// CHECK9-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK9-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 +// CHECK9-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK9-NEXT: call void @_ZN1SIiED2Ev(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]]) #[[ATTR3]] +// CHECK9-NEXT: ret void +// +// +// CHECK9-LABEL: define {{[^@]+}}@_ZN1SIiEC2Ev +// CHECK9-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]]) unnamed_addr #[[ATTR1]] comdat { +// CHECK9-NEXT: entry: +// CHECK9-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK9-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 +// CHECK9-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK9-NEXT: [[F:%.*]] = getelementptr inbounds [[STRUCT_S_2:%.*]], ptr [[THIS1]], i32 0, i32 0 +// CHECK9-NEXT: store i32 0, ptr [[F]], align 4 +// CHECK9-NEXT: ret void +// +// +// CHECK9-LABEL: define {{[^@]+}}@_ZN1SIiEC2Ei +// CHECK9-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]], i32 noundef signext [[A:%.*]]) unnamed_addr #[[ATTR1]] comdat { +// CHECK9-NEXT: entry: +// CHECK9-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK9-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 +// CHECK9-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 +// CHECK9-NEXT: store i32 [[A]], ptr [[A_ADDR]], align 4 +// CHECK9-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK9-NEXT: [[F:%.*]] = getelementptr inbounds [[STRUCT_S_2:%.*]], ptr [[THIS1]], i32 0, i32 0 +// CHECK9-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4 +// CHECK9-NEXT: store i32 [[TMP0]], ptr [[F]], align 4 +// CHECK9-NEXT: ret void +// +// +// CHECK9-LABEL: define {{[^@]+}}@_ZN1SIiED2Ev +// CHECK9-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]]) unnamed_addr #[[ATTR1]] comdat { +// CHECK9-NEXT: entry: +// CHECK9-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK9-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 +// CHECK9-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK9-NEXT: ret void +// +// +// CHECK11-LABEL: define {{[^@]+}}@main +// CHECK11-SAME: () #[[ATTR0:[0-9]+]] { +// CHECK11-NEXT: entry: +// CHECK11-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 +// CHECK11-NEXT: [[G:%.*]] = alloca double, align 8 +// CHECK11-NEXT: [[G1:%.*]] = alloca ptr, align 4 +// CHECK11-NEXT: [[TEST:%.*]] = alloca [[STRUCT_S:%.*]], align 4 +// CHECK11-NEXT: [[T_VAR:%.*]] = alloca i32, align 4 +// CHECK11-NEXT: [[VEC:%.*]] = alloca [2 x i32], align 4 +// CHECK11-NEXT: [[S_ARR:%.*]] = alloca [2 x %struct.S], align 4 +// CHECK11-NEXT: [[VAR:%.*]] = alloca ptr, align 4 +// CHECK11-NEXT: [[AGG_CAPTURED:%.*]] = alloca [[STRUCT_ANON:%.*]], align 1 +// CHECK11-NEXT: [[TMP:%.*]] = alloca i32, align 4 +// CHECK11-NEXT: [[_TMP1:%.*]] = alloca ptr, align 4 +// CHECK11-NEXT: [[I:%.*]] = alloca i32, align 4 +// CHECK11-NEXT: [[AGG_CAPTURED2:%.*]] = alloca [[STRUCT_ANON_0:%.*]], align 1 +// CHECK11-NEXT: [[_TMP3:%.*]] = alloca i32, align 4 +// CHECK11-NEXT: [[TMP0:%.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GLOB1:[0-9]+]]) +// CHECK11-NEXT: store i32 0, ptr [[RETVAL]], align 4 +// CHECK11-NEXT: store ptr [[G]], ptr [[G1]], align 4 +// CHECK11-NEXT: call void @_ZN1SIfEC1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[TEST]]) +// CHECK11-NEXT: store i32 0, ptr [[T_VAR]], align 4 +// CHECK11-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[VEC]], ptr align 4 @__const.main.vec, i32 8, i1 false) +// CHECK11-NEXT: [[ARRAYINIT_BEGIN:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[S_ARR]], i32 0, i32 0 +// CHECK11-NEXT: call void @_ZN1SIfEC1Ef(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYINIT_BEGIN]], float noundef 1.000000e+00) +// CHECK11-NEXT: [[ARRAYINIT_ELEMENT:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAYINIT_BEGIN]], i32 1 +// CHECK11-NEXT: call void @_ZN1SIfEC1Ef(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYINIT_ELEMENT]], float noundef 2.000000e+00) +// CHECK11-NEXT: store ptr [[TEST]], ptr [[VAR]], align 4 +// CHECK11-NEXT: call void @__kmpc_taskgroup(ptr @[[GLOB1]], i32 [[TMP0]]) +// CHECK11-NEXT: store ptr undef, ptr [[_TMP1]], align 4 +// CHECK11-NEXT: [[TMP1:%.*]] = call ptr @__kmpc_omp_task_alloc(ptr @[[GLOB1]], i32 [[TMP0]], i32 9, i32 80, i32 1, ptr @.omp_task_entry.) +// CHECK11-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T_WITH_PRIVATES:%.*]], ptr [[TMP1]], i32 0, i32 0 +// CHECK11-NEXT: [[TMP3:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T_WITH_PRIVATES]], ptr [[TMP1]], i32 0, i32 1 +// CHECK11-NEXT: [[TMP4:%.*]] = getelementptr inbounds [[STRUCT__KMP_PRIVATES_T:%.*]], ptr [[TMP3]], i32 0, i32 2 +// CHECK11-NEXT: [[ARRAY_BEGIN:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[TMP4]], i32 0, i32 0 +// CHECK11-NEXT: [[ARRAYCTOR_END:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAY_BEGIN]], i32 2 +// CHECK11-NEXT: br label [[ARRAYCTOR_LOOP:%.*]] +// CHECK11: arrayctor.loop: +// CHECK11-NEXT: [[ARRAYCTOR_CUR:%.*]] = phi ptr [ [[ARRAY_BEGIN]], [[ENTRY:%.*]] ], [ [[ARRAYCTOR_NEXT:%.*]], [[ARRAYCTOR_LOOP]] ] +// CHECK11-NEXT: call void @_ZN1SIfEC1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYCTOR_CUR]]) +// CHECK11-NEXT: [[ARRAYCTOR_NEXT]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAYCTOR_CUR]], i32 1 +// CHECK11-NEXT: [[ARRAYCTOR_DONE:%.*]] = icmp eq ptr [[ARRAYCTOR_NEXT]], [[ARRAYCTOR_END]] +// CHECK11-NEXT: br i1 [[ARRAYCTOR_DONE]], label [[ARRAYCTOR_CONT:%.*]], label [[ARRAYCTOR_LOOP]] +// CHECK11: arrayctor.cont: +// CHECK11-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT__KMP_PRIVATES_T]], ptr [[TMP3]], i32 0, i32 3 +// CHECK11-NEXT: call void @_ZN1SIfEC1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[TMP5]]) +// CHECK11-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T:%.*]], ptr [[TMP2]], i32 0, i32 3 +// CHECK11-NEXT: store ptr @.omp_task_destructor., ptr [[TMP6]], align 4 +// CHECK11-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP2]], i32 0, i32 5 +// CHECK11-NEXT: store i64 0, ptr [[TMP7]], align 4 +// CHECK11-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP2]], i32 0, i32 6 +// CHECK11-NEXT: store i64 1, ptr [[TMP8]], align 4 +// CHECK11-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP2]], i32 0, i32 7 +// CHECK11-NEXT: store i64 1, ptr [[TMP9]], align 4 +// CHECK11-NEXT: [[TMP10:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP2]], i32 0, i32 9 +// CHECK11-NEXT: call void @llvm.memset.p0.i32(ptr align 4 [[TMP10]], i8 0, i32 4, i1 false) +// CHECK11-NEXT: [[TMP11:%.*]] = load i64, ptr [[TMP9]], align 4 +// CHECK11-NEXT: call void @__kmpc_taskloop(ptr @[[GLOB1]], i32 [[TMP0]], ptr [[TMP1]], i32 1, ptr [[TMP7]], ptr [[TMP8]], i64 [[TMP11]], i32 1, i32 0, i64 0, ptr @.omp_task_dup.) +// CHECK11-NEXT: call void @__kmpc_end_taskgroup(ptr @[[GLOB1]], i32 [[TMP0]]) +// CHECK11-NEXT: call void @__kmpc_taskgroup(ptr @[[GLOB1]], i32 [[TMP0]]) +// CHECK11-NEXT: [[TMP12:%.*]] = call ptr @__kmpc_omp_task_alloc(ptr @[[GLOB1]], i32 [[TMP0]], i32 1, i32 52, i32 1, ptr @.omp_task_entry..2) +// CHECK11-NEXT: [[TMP13:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T_WITH_PRIVATES_1:%.*]], ptr [[TMP12]], i32 0, i32 0 +// CHECK11-NEXT: [[TMP14:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP13]], i32 0, i32 5 +// CHECK11-NEXT: store i64 0, ptr [[TMP14]], align 4 +// CHECK11-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP13]], i32 0, i32 6 +// CHECK11-NEXT: store i64 1, ptr [[TMP15]], align 4 +// CHECK11-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP13]], i32 0, i32 7 +// CHECK11-NEXT: store i64 1, ptr [[TMP16]], align 4 +// CHECK11-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP13]], i32 0, i32 9 +// CHECK11-NEXT: call void @llvm.memset.p0.i32(ptr align 4 [[TMP17]], i8 0, i32 4, i1 false) +// CHECK11-NEXT: [[TMP18:%.*]] = load i64, ptr [[TMP16]], align 4 +// CHECK11-NEXT: call void @__kmpc_taskloop(ptr @[[GLOB1]], i32 [[TMP0]], ptr [[TMP12]], i32 1, ptr [[TMP14]], ptr [[TMP15]], i64 [[TMP18]], i32 1, i32 0, i64 0, ptr null) +// CHECK11-NEXT: call void @__kmpc_end_taskgroup(ptr @[[GLOB1]], i32 [[TMP0]]) +// CHECK11-NEXT: [[CALL:%.*]] = call noundef i32 @_Z5tmainIiET_v() +// CHECK11-NEXT: store i32 [[CALL]], ptr [[RETVAL]], align 4 +// CHECK11-NEXT: [[ARRAY_BEGIN4:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[S_ARR]], i32 0, i32 0 +// CHECK11-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAY_BEGIN4]], i32 2 +// CHECK11-NEXT: br label [[ARRAYDESTROY_BODY:%.*]] +// CHECK11: arraydestroy.body: +// CHECK11-NEXT: [[ARRAYDESTROY_ELEMENTPAST:%.*]] = phi ptr [ [[TMP19]], [[ARRAYCTOR_CONT]] ], [ [[ARRAYDESTROY_ELEMENT:%.*]], [[ARRAYDESTROY_BODY]] ] +// CHECK11-NEXT: [[ARRAYDESTROY_ELEMENT]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAYDESTROY_ELEMENTPAST]], i32 -1 +// CHECK11-NEXT: call void @_ZN1SIfED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYDESTROY_ELEMENT]]) #[[ATTR3:[0-9]+]] +// CHECK11-NEXT: [[ARRAYDESTROY_DONE:%.*]] = icmp eq ptr [[ARRAYDESTROY_ELEMENT]], [[ARRAY_BEGIN4]] +// CHECK11-NEXT: br i1 [[ARRAYDESTROY_DONE]], label [[ARRAYDESTROY_DONE5:%.*]], label [[ARRAYDESTROY_BODY]] +// CHECK11: arraydestroy.done5: +// CHECK11-NEXT: call void @_ZN1SIfED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[TEST]]) #[[ATTR3]] +// CHECK11-NEXT: [[TMP20:%.*]] = load i32, ptr [[RETVAL]], align 4 +// CHECK11-NEXT: ret i32 [[TMP20]] +// +// +// CHECK11-LABEL: define {{[^@]+}}@_ZN1SIfEC1Ev +// CHECK11-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]]) unnamed_addr #[[ATTR1:[0-9]+]] comdat align 2 { +// CHECK11-NEXT: entry: +// CHECK11-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4 +// CHECK11-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4 +// CHECK11-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4 +// CHECK11-NEXT: call void @_ZN1SIfEC2Ev(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]]) +// CHECK11-NEXT: ret void +// +// +// CHECK11-LABEL: define {{[^@]+}}@_ZN1SIfEC1Ef +// CHECK11-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]], float noundef [[A:%.*]]) unnamed_addr #[[ATTR1]] comdat align 2 { +// CHECK11-NEXT: entry: +// CHECK11-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4 +// CHECK11-NEXT: [[A_ADDR:%.*]] = alloca float, align 4 +// CHECK11-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4 +// CHECK11-NEXT: store float [[A]], ptr [[A_ADDR]], align 4 +// CHECK11-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4 +// CHECK11-NEXT: [[TMP0:%.*]] = load float, ptr [[A_ADDR]], align 4 +// CHECK11-NEXT: call void @_ZN1SIfEC2Ef(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]], float noundef [[TMP0]]) +// CHECK11-NEXT: ret void +// +// +// CHECK11-LABEL: define {{[^@]+}}@.omp_task_privates_map. +// CHECK11-SAME: (ptr noalias noundef [[TMP0:%.*]], ptr noalias noundef [[TMP1:%.*]], ptr noalias noundef [[TMP2:%.*]], ptr noalias noundef [[TMP3:%.*]], ptr noalias noundef [[TMP4:%.*]], ptr noalias noundef [[TMP5:%.*]]) #[[ATTR5:[0-9]+]] { +// CHECK11-NEXT: entry: +// CHECK11-NEXT: [[DOTADDR:%.*]] = alloca ptr, align 4 +// CHECK11-NEXT: [[DOTADDR1:%.*]] = alloca ptr, align 4 +// CHECK11-NEXT: [[DOTADDR2:%.*]] = alloca ptr, align 4 +// CHECK11-NEXT: [[DOTADDR3:%.*]] = alloca ptr, align 4 +// CHECK11-NEXT: [[DOTADDR4:%.*]] = alloca ptr, align 4 +// CHECK11-NEXT: [[DOTADDR5:%.*]] = alloca ptr, align 4 +// CHECK11-NEXT: store ptr [[TMP0]], ptr [[DOTADDR]], align 4 +// CHECK11-NEXT: store ptr [[TMP1]], ptr [[DOTADDR1]], align 4 +// CHECK11-NEXT: store ptr [[TMP2]], ptr [[DOTADDR2]], align 4 +// CHECK11-NEXT: store ptr [[TMP3]], ptr [[DOTADDR3]], align 4 +// CHECK11-NEXT: store ptr [[TMP4]], ptr [[DOTADDR4]], align 4 +// CHECK11-NEXT: store ptr [[TMP5]], ptr [[DOTADDR5]], align 4 +// CHECK11-NEXT: [[TMP6:%.*]] = load ptr, ptr [[DOTADDR]], align 4 +// CHECK11-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT__KMP_PRIVATES_T:%.*]], ptr [[TMP6]], i32 0, i32 0 +// CHECK11-NEXT: [[TMP8:%.*]] = load ptr, ptr [[DOTADDR1]], align 4 +// CHECK11-NEXT: store ptr [[TMP7]], ptr [[TMP8]], align 4 +// CHECK11-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT__KMP_PRIVATES_T]], ptr [[TMP6]], i32 0, i32 1 +// CHECK11-NEXT: [[TMP10:%.*]] = load ptr, ptr [[DOTADDR2]], align 4 +// CHECK11-NEXT: store ptr [[TMP9]], ptr [[TMP10]], align 4 +// CHECK11-NEXT: [[TMP11:%.*]] = getelementptr inbounds [[STRUCT__KMP_PRIVATES_T]], ptr [[TMP6]], i32 0, i32 2 +// CHECK11-NEXT: [[TMP12:%.*]] = load ptr, ptr [[DOTADDR3]], align 4 +// CHECK11-NEXT: store ptr [[TMP11]], ptr [[TMP12]], align 4 +// CHECK11-NEXT: [[TMP13:%.*]] = getelementptr inbounds [[STRUCT__KMP_PRIVATES_T]], ptr [[TMP6]], i32 0, i32 3 +// CHECK11-NEXT: [[TMP14:%.*]] = load ptr, ptr [[DOTADDR4]], align 4 +// CHECK11-NEXT: store ptr [[TMP13]], ptr [[TMP14]], align 4 +// CHECK11-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT__KMP_PRIVATES_T]], ptr [[TMP6]], i32 0, i32 4 +// CHECK11-NEXT: [[TMP16:%.*]] = load ptr, ptr [[DOTADDR5]], align 4 +// CHECK11-NEXT: store ptr [[TMP15]], ptr [[TMP16]], align 4 +// CHECK11-NEXT: ret void +// +// +// CHECK11-LABEL: define {{[^@]+}}@.omp_task_entry. +// CHECK11-SAME: (i32 noundef [[TMP0:%.*]], ptr noalias noundef [[TMP1:%.*]]) #[[ATTR6:[0-9]+]] { +// CHECK11-NEXT: entry: +// CHECK11-NEXT: [[DOTGLOBAL_TID__ADDR_I:%.*]] = alloca i32, align 4 +// CHECK11-NEXT: [[DOTPART_ID__ADDR_I:%.*]] = alloca ptr, align 4 +// CHECK11-NEXT: [[DOTPRIVATES__ADDR_I:%.*]] = alloca ptr, align 4 +// CHECK11-NEXT: [[DOTCOPY_FN__ADDR_I:%.*]] = alloca ptr, align 4 +// CHECK11-NEXT: [[DOTTASK_T__ADDR_I:%.*]] = alloca ptr, align 4 +// CHECK11-NEXT: [[DOTLB__ADDR_I:%.*]] = alloca i64, align 8 +// CHECK11-NEXT: [[DOTUB__ADDR_I:%.*]] = alloca i64, align 8 +// CHECK11-NEXT: [[DOTST__ADDR_I:%.*]] = alloca i64, align 8 +// CHECK11-NEXT: [[DOTLITER__ADDR_I:%.*]] = alloca i32, align 4 +// CHECK11-NEXT: [[DOTREDUCTIONS__ADDR_I:%.*]] = alloca ptr, align 4 +// CHECK11-NEXT: [[__CONTEXT_ADDR_I:%.*]] = alloca ptr, align 4 +// CHECK11-NEXT: [[DOTPRIV_PTR_ADDR_I:%.*]] = alloca ptr, align 4 +// CHECK11-NEXT: [[DOTPRIV_PTR_ADDR1_I:%.*]] = alloca ptr, align 4 +// CHECK11-NEXT: [[DOTPRIV_PTR_ADDR2_I:%.*]] = alloca ptr, align 4 +// CHECK11-NEXT: [[DOTPRIV_PTR_ADDR3_I:%.*]] = alloca ptr, align 4 +// CHECK11-NEXT: [[DOTPRIV_PTR_ADDR4_I:%.*]] = alloca ptr, align 4 +// CHECK11-NEXT: [[TMP_I:%.*]] = alloca ptr, align 4 +// CHECK11-NEXT: [[TMP6_I:%.*]] = alloca ptr, align 4 +// CHECK11-NEXT: [[I_I:%.*]] = alloca i32, align 4 +// CHECK11-NEXT: [[DOTOMP_IV_I:%.*]] = alloca i32, align 4 +// CHECK11-NEXT: [[DOTADDR:%.*]] = alloca i32, align 4 +// CHECK11-NEXT: [[DOTADDR1:%.*]] = alloca ptr, align 4 +// CHECK11-NEXT: store i32 [[TMP0]], ptr [[DOTADDR]], align 4 +// CHECK11-NEXT: store ptr [[TMP1]], ptr [[DOTADDR1]], align 4 +// CHECK11-NEXT: [[TMP2:%.*]] = load i32, ptr [[DOTADDR]], align 4 +// CHECK11-NEXT: [[TMP3:%.*]] = load ptr, ptr [[DOTADDR1]], align 4 +// CHECK11-NEXT: [[TMP4:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T_WITH_PRIVATES:%.*]], ptr [[TMP3]], i32 0, i32 0 +// CHECK11-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T:%.*]], ptr [[TMP4]], i32 0, i32 2 +// CHECK11-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP4]], i32 0, i32 0 +// CHECK11-NEXT: [[TMP7:%.*]] = load ptr, ptr [[TMP6]], align 4 +// CHECK11-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T_WITH_PRIVATES]], ptr [[TMP3]], i32 0, i32 1 +// CHECK11-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP4]], i32 0, i32 5 +// CHECK11-NEXT: [[TMP10:%.*]] = load i64, ptr [[TMP9]], align 4 +// CHECK11-NEXT: [[TMP11:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP4]], i32 0, i32 6 +// CHECK11-NEXT: [[TMP12:%.*]] = load i64, ptr [[TMP11]], align 4 +// CHECK11-NEXT: [[TMP13:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP4]], i32 0, i32 7 +// CHECK11-NEXT: [[TMP14:%.*]] = load i64, ptr [[TMP13]], align 4 +// CHECK11-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP4]], i32 0, i32 8 +// CHECK11-NEXT: [[TMP16:%.*]] = load i32, ptr [[TMP15]], align 4 +// CHECK11-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP4]], i32 0, i32 9 +// CHECK11-NEXT: [[TMP18:%.*]] = load ptr, ptr [[TMP17]], align 4 +// CHECK11-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META4:![0-9]+]]) +// CHECK11-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META7:![0-9]+]]) +// CHECK11-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META9:![0-9]+]]) +// CHECK11-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META11:![0-9]+]]) +// CHECK11-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META13:![0-9]+]]) +// CHECK11-NEXT: store i32 [[TMP2]], ptr [[DOTGLOBAL_TID__ADDR_I]], align 4, !noalias [[META15:![0-9]+]] +// CHECK11-NEXT: store ptr [[TMP5]], ptr [[DOTPART_ID__ADDR_I]], align 4, !noalias [[META15]] +// CHECK11-NEXT: store ptr [[TMP8]], ptr [[DOTPRIVATES__ADDR_I]], align 4, !noalias [[META15]] +// CHECK11-NEXT: store ptr @.omp_task_privates_map., ptr [[DOTCOPY_FN__ADDR_I]], align 4, !noalias [[META15]] +// CHECK11-NEXT: store ptr [[TMP3]], ptr [[DOTTASK_T__ADDR_I]], align 4, !noalias [[META15]] +// CHECK11-NEXT: store i64 [[TMP10]], ptr [[DOTLB__ADDR_I]], align 8, !noalias [[META15]] +// CHECK11-NEXT: store i64 [[TMP12]], ptr [[DOTUB__ADDR_I]], align 8, !noalias [[META15]] +// CHECK11-NEXT: store i64 [[TMP14]], ptr [[DOTST__ADDR_I]], align 8, !noalias [[META15]] +// CHECK11-NEXT: store i32 [[TMP16]], ptr [[DOTLITER__ADDR_I]], align 4, !noalias [[META15]] +// CHECK11-NEXT: store ptr [[TMP18]], ptr [[DOTREDUCTIONS__ADDR_I]], align 4, !noalias [[META15]] +// CHECK11-NEXT: store ptr [[TMP7]], ptr [[__CONTEXT_ADDR_I]], align 4, !noalias [[META15]] +// CHECK11-NEXT: [[TMP19:%.*]] = load ptr, ptr [[__CONTEXT_ADDR_I]], align 4, !noalias [[META15]] +// CHECK11-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTCOPY_FN__ADDR_I]], align 4, !noalias [[META15]] +// CHECK11-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTPRIVATES__ADDR_I]], align 4, !noalias [[META15]] +// CHECK11-NEXT: call void [[TMP20]](ptr [[TMP21]], ptr [[DOTPRIV_PTR_ADDR_I]], ptr [[DOTPRIV_PTR_ADDR1_I]], ptr [[DOTPRIV_PTR_ADDR2_I]], ptr [[DOTPRIV_PTR_ADDR3_I]], ptr [[DOTPRIV_PTR_ADDR4_I]]) #[[ATTR3]] +// CHECK11-NEXT: [[TMP22:%.*]] = load ptr, ptr [[DOTPRIV_PTR_ADDR_I]], align 4, !noalias [[META15]] +// CHECK11-NEXT: [[TMP23:%.*]] = load ptr, ptr [[DOTPRIV_PTR_ADDR1_I]], align 4, !noalias [[META15]] +// CHECK11-NEXT: [[TMP24:%.*]] = load ptr, ptr [[DOTPRIV_PTR_ADDR2_I]], align 4, !noalias [[META15]] +// CHECK11-NEXT: [[TMP25:%.*]] = load ptr, ptr [[DOTPRIV_PTR_ADDR3_I]], align 4, !noalias [[META15]] +// CHECK11-NEXT: store ptr [[TMP25]], ptr [[TMP_I]], align 4, !noalias [[META15]] +// CHECK11-NEXT: [[TMP26:%.*]] = load ptr, ptr [[DOTPRIV_PTR_ADDR4_I]], align 4, !noalias [[META15]] +// CHECK11-NEXT: store ptr undef, ptr [[TMP6_I]], align 4, !noalias [[META15]] +// CHECK11-NEXT: [[TMP27:%.*]] = load i64, ptr [[DOTLB__ADDR_I]], align 8, !noalias [[META15]] +// CHECK11-NEXT: [[CONV_I:%.*]] = trunc i64 [[TMP27]] to i32 +// CHECK11-NEXT: store i32 [[CONV_I]], ptr [[DOTOMP_IV_I]], align 4, !noalias [[META15]] +// CHECK11-NEXT: br label [[OMP_INNER_FOR_COND_I:%.*]] +// CHECK11: omp.inner.for.cond.i: +// CHECK11-NEXT: [[TMP28:%.*]] = load i32, ptr [[DOTOMP_IV_I]], align 4, !noalias [[META15]], !llvm.access.group [[ACC_GRP16:![0-9]+]] +// CHECK11-NEXT: [[CONV7_I:%.*]] = sext i32 [[TMP28]] to i64 +// CHECK11-NEXT: [[TMP29:%.*]] = load i64, ptr [[DOTUB__ADDR_I]], align 8, !noalias [[META15]], !llvm.access.group [[ACC_GRP16]] +// CHECK11-NEXT: [[CMP_I:%.*]] = icmp ule i64 [[CONV7_I]], [[TMP29]] +// CHECK11-NEXT: br i1 [[CMP_I]], label [[OMP_INNER_FOR_BODY_I:%.*]], label [[DOTOMP_OUTLINED__EXIT:%.*]] +// CHECK11: omp.inner.for.body.i: +// CHECK11-NEXT: [[TMP30:%.*]] = load i32, ptr [[DOTOMP_IV_I]], align 4, !noalias [[META15]], !llvm.access.group [[ACC_GRP16]] +// CHECK11-NEXT: store i32 [[TMP30]], ptr [[I_I]], align 4, !noalias [[META15]], !llvm.access.group [[ACC_GRP16]] +// CHECK11-NEXT: [[TMP31:%.*]] = load i32, ptr [[TMP22]], align 4, !llvm.access.group [[ACC_GRP16]] +// CHECK11-NEXT: [[TMP32:%.*]] = load i32, ptr [[I_I]], align 4, !noalias [[META15]], !llvm.access.group [[ACC_GRP16]] +// CHECK11-NEXT: [[ARRAYIDX_I:%.*]] = getelementptr inbounds [2 x i32], ptr [[TMP23]], i32 0, i32 [[TMP32]] +// CHECK11-NEXT: store i32 [[TMP31]], ptr [[ARRAYIDX_I]], align 4, !llvm.access.group [[ACC_GRP16]] +// CHECK11-NEXT: [[TMP33:%.*]] = load ptr, ptr [[TMP_I]], align 4, !noalias [[META15]], !llvm.access.group [[ACC_GRP16]] +// CHECK11-NEXT: [[TMP34:%.*]] = load i32, ptr [[I_I]], align 4, !noalias [[META15]], !llvm.access.group [[ACC_GRP16]] +// CHECK11-NEXT: [[ARRAYIDX8_I:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[TMP24]], i32 0, i32 [[TMP34]] +// CHECK11-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[ARRAYIDX8_I]], ptr align 4 [[TMP33]], i32 4, i1 false), !llvm.access.group [[ACC_GRP16]] +// CHECK11-NEXT: [[TMP35:%.*]] = load i32, ptr [[DOTOMP_IV_I]], align 4, !noalias [[META15]], !llvm.access.group [[ACC_GRP16]] +// CHECK11-NEXT: [[ADD9_I:%.*]] = add nsw i32 [[TMP35]], 1 +// CHECK11-NEXT: store i32 [[ADD9_I]], ptr [[DOTOMP_IV_I]], align 4, !noalias [[META15]], !llvm.access.group [[ACC_GRP16]] +// CHECK11-NEXT: br label [[OMP_INNER_FOR_COND_I]], !llvm.loop [[LOOP17:![0-9]+]] +// CHECK11: .omp_outlined..exit: +// CHECK11-NEXT: ret i32 0 +// +// +// CHECK11-LABEL: define {{[^@]+}}@.omp_task_dup. +// CHECK11-SAME: (ptr noundef [[TMP0:%.*]], ptr noundef [[TMP1:%.*]], i32 noundef [[TMP2:%.*]]) #[[ATTR6]] { +// CHECK11-NEXT: entry: +// CHECK11-NEXT: [[DOTADDR:%.*]] = alloca ptr, align 4 +// CHECK11-NEXT: [[DOTADDR1:%.*]] = alloca ptr, align 4 +// CHECK11-NEXT: [[DOTADDR2:%.*]] = alloca i32, align 4 +// CHECK11-NEXT: store ptr [[TMP0]], ptr [[DOTADDR]], align 4 +// CHECK11-NEXT: store ptr [[TMP1]], ptr [[DOTADDR1]], align 4 +// CHECK11-NEXT: store i32 [[TMP2]], ptr [[DOTADDR2]], align 4 +// CHECK11-NEXT: [[TMP3:%.*]] = load ptr, ptr [[DOTADDR]], align 4 +// CHECK11-NEXT: [[TMP4:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T_WITH_PRIVATES:%.*]], ptr [[TMP3]], i32 0, i32 1 +// CHECK11-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT__KMP_PRIVATES_T:%.*]], ptr [[TMP4]], i32 0, i32 2 +// CHECK11-NEXT: [[ARRAY_BEGIN:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[TMP5]], i32 0, i32 0 +// CHECK11-NEXT: [[ARRAYCTOR_END:%.*]] = getelementptr inbounds [[STRUCT_S:%.*]], ptr [[ARRAY_BEGIN]], i32 2 +// CHECK11-NEXT: br label [[ARRAYCTOR_LOOP:%.*]] +// CHECK11: arrayctor.loop: +// CHECK11-NEXT: [[ARRAYCTOR_CUR:%.*]] = phi ptr [ [[ARRAY_BEGIN]], [[ENTRY:%.*]] ], [ [[ARRAYCTOR_NEXT:%.*]], [[ARRAYCTOR_LOOP]] ] +// CHECK11-NEXT: call void @_ZN1SIfEC1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYCTOR_CUR]]) +// CHECK11-NEXT: [[ARRAYCTOR_NEXT]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAYCTOR_CUR]], i32 1 +// CHECK11-NEXT: [[ARRAYCTOR_DONE:%.*]] = icmp eq ptr [[ARRAYCTOR_NEXT]], [[ARRAYCTOR_END]] +// CHECK11-NEXT: br i1 [[ARRAYCTOR_DONE]], label [[ARRAYCTOR_CONT:%.*]], label [[ARRAYCTOR_LOOP]] +// CHECK11: arrayctor.cont: +// CHECK11-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT__KMP_PRIVATES_T]], ptr [[TMP4]], i32 0, i32 3 +// CHECK11-NEXT: call void @_ZN1SIfEC1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[TMP6]]) +// CHECK11-NEXT: ret void +// +// +// CHECK11-LABEL: define {{[^@]+}}@.omp_task_destructor. +// CHECK11-SAME: (i32 noundef [[TMP0:%.*]], ptr noalias noundef [[TMP1:%.*]]) #[[ATTR6]] { +// CHECK11-NEXT: entry: +// CHECK11-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 +// CHECK11-NEXT: [[DOTADDR:%.*]] = alloca i32, align 4 +// CHECK11-NEXT: [[DOTADDR1:%.*]] = alloca ptr, align 4 +// CHECK11-NEXT: store i32 [[TMP0]], ptr [[DOTADDR]], align 4 +// CHECK11-NEXT: store ptr [[TMP1]], ptr [[DOTADDR1]], align 4 +// CHECK11-NEXT: [[TMP2:%.*]] = load ptr, ptr [[DOTADDR1]], align 4 +// CHECK11-NEXT: [[TMP3:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T_WITH_PRIVATES:%.*]], ptr [[TMP2]], i32 0, i32 1 +// CHECK11-NEXT: [[TMP4:%.*]] = getelementptr inbounds [[STRUCT__KMP_PRIVATES_T:%.*]], ptr [[TMP3]], i32 0, i32 2 +// CHECK11-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT__KMP_PRIVATES_T]], ptr [[TMP3]], i32 0, i32 3 +// CHECK11-NEXT: call void @_ZN1SIfED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[TMP5]]) #[[ATTR3]] +// CHECK11-NEXT: [[ARRAY_BEGIN:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[TMP4]], i32 0, i32 0 +// CHECK11-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT_S:%.*]], ptr [[ARRAY_BEGIN]], i32 2 +// CHECK11-NEXT: br label [[ARRAYDESTROY_BODY:%.*]] +// CHECK11: arraydestroy.body: +// CHECK11-NEXT: [[ARRAYDESTROY_ELEMENTPAST:%.*]] = phi ptr [ [[TMP6]], [[ENTRY:%.*]] ], [ [[ARRAYDESTROY_ELEMENT:%.*]], [[ARRAYDESTROY_BODY]] ] +// CHECK11-NEXT: [[ARRAYDESTROY_ELEMENT]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAYDESTROY_ELEMENTPAST]], i32 -1 +// CHECK11-NEXT: call void @_ZN1SIfED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYDESTROY_ELEMENT]]) #[[ATTR3]] +// CHECK11-NEXT: [[ARRAYDESTROY_DONE:%.*]] = icmp eq ptr [[ARRAYDESTROY_ELEMENT]], [[ARRAY_BEGIN]] +// CHECK11-NEXT: br i1 [[ARRAYDESTROY_DONE]], label [[ARRAYDESTROY_DONE2:%.*]], label [[ARRAYDESTROY_BODY]] +// CHECK11: arraydestroy.done2: +// CHECK11-NEXT: [[TMP7:%.*]] = load i32, ptr [[RETVAL]], align 4 +// CHECK11-NEXT: ret i32 [[TMP7]] +// +// +// CHECK11-LABEL: define {{[^@]+}}@_ZN1SIfED1Ev +// CHECK11-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]]) unnamed_addr #[[ATTR1]] comdat align 2 { +// CHECK11-NEXT: entry: +// CHECK11-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4 +// CHECK11-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4 +// CHECK11-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4 +// CHECK11-NEXT: call void @_ZN1SIfED2Ev(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]]) #[[ATTR3]] +// CHECK11-NEXT: ret void +// +// +// CHECK11-LABEL: define {{[^@]+}}@.omp_task_entry..2 +// CHECK11-SAME: (i32 noundef [[TMP0:%.*]], ptr noalias noundef [[TMP1:%.*]]) #[[ATTR6]] { +// CHECK11-NEXT: entry: +// CHECK11-NEXT: [[DOTGLOBAL_TID__ADDR_I:%.*]] = alloca i32, align 4 +// CHECK11-NEXT: [[DOTPART_ID__ADDR_I:%.*]] = alloca ptr, align 4 +// CHECK11-NEXT: [[DOTPRIVATES__ADDR_I:%.*]] = alloca ptr, align 4 +// CHECK11-NEXT: [[DOTCOPY_FN__ADDR_I:%.*]] = alloca ptr, align 4 +// CHECK11-NEXT: [[DOTTASK_T__ADDR_I:%.*]] = alloca ptr, align 4 +// CHECK11-NEXT: [[DOTLB__ADDR_I:%.*]] = alloca i64, align 8 +// CHECK11-NEXT: [[DOTUB__ADDR_I:%.*]] = alloca i64, align 8 +// CHECK11-NEXT: [[DOTST__ADDR_I:%.*]] = alloca i64, align 8 +// CHECK11-NEXT: [[DOTLITER__ADDR_I:%.*]] = alloca i32, align 4 +// CHECK11-NEXT: [[DOTREDUCTIONS__ADDR_I:%.*]] = alloca ptr, align 4 +// CHECK11-NEXT: [[__CONTEXT_ADDR_I:%.*]] = alloca ptr, align 4 +// CHECK11-NEXT: [[I_I:%.*]] = alloca i32, align 4 +// CHECK11-NEXT: [[DOTOMP_IV_I:%.*]] = alloca i32, align 4 +// CHECK11-NEXT: [[DOTADDR:%.*]] = alloca i32, align 4 +// CHECK11-NEXT: [[DOTADDR1:%.*]] = alloca ptr, align 4 +// CHECK11-NEXT: store i32 [[TMP0]], ptr [[DOTADDR]], align 4 +// CHECK11-NEXT: store ptr [[TMP1]], ptr [[DOTADDR1]], align 4 +// CHECK11-NEXT: [[TMP2:%.*]] = load i32, ptr [[DOTADDR]], align 4 +// CHECK11-NEXT: [[TMP3:%.*]] = load ptr, ptr [[DOTADDR1]], align 4 +// CHECK11-NEXT: [[TMP4:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T_WITH_PRIVATES_1:%.*]], ptr [[TMP3]], i32 0, i32 0 +// CHECK11-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T:%.*]], ptr [[TMP4]], i32 0, i32 2 +// CHECK11-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP4]], i32 0, i32 0 +// CHECK11-NEXT: [[TMP7:%.*]] = load ptr, ptr [[TMP6]], align 4 +// CHECK11-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP4]], i32 0, i32 5 +// CHECK11-NEXT: [[TMP9:%.*]] = load i64, ptr [[TMP8]], align 4 +// CHECK11-NEXT: [[TMP10:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP4]], i32 0, i32 6 +// CHECK11-NEXT: [[TMP11:%.*]] = load i64, ptr [[TMP10]], align 4 +// CHECK11-NEXT: [[TMP12:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP4]], i32 0, i32 7 +// CHECK11-NEXT: [[TMP13:%.*]] = load i64, ptr [[TMP12]], align 4 +// CHECK11-NEXT: [[TMP14:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP4]], i32 0, i32 8 +// CHECK11-NEXT: [[TMP15:%.*]] = load i32, ptr [[TMP14]], align 4 +// CHECK11-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP4]], i32 0, i32 9 +// CHECK11-NEXT: [[TMP17:%.*]] = load ptr, ptr [[TMP16]], align 4 +// CHECK11-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META20:![0-9]+]]) +// CHECK11-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META23:![0-9]+]]) +// CHECK11-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META25:![0-9]+]]) +// CHECK11-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META27:![0-9]+]]) +// CHECK11-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META29:![0-9]+]]) +// CHECK11-NEXT: store i32 [[TMP2]], ptr [[DOTGLOBAL_TID__ADDR_I]], align 4, !noalias [[META31:![0-9]+]] +// CHECK11-NEXT: store ptr [[TMP5]], ptr [[DOTPART_ID__ADDR_I]], align 4, !noalias [[META31]] +// CHECK11-NEXT: store ptr null, ptr [[DOTPRIVATES__ADDR_I]], align 4, !noalias [[META31]] +// CHECK11-NEXT: store ptr null, ptr [[DOTCOPY_FN__ADDR_I]], align 4, !noalias [[META31]] +// CHECK11-NEXT: store ptr [[TMP3]], ptr [[DOTTASK_T__ADDR_I]], align 4, !noalias [[META31]] +// CHECK11-NEXT: store i64 [[TMP9]], ptr [[DOTLB__ADDR_I]], align 8, !noalias [[META31]] +// CHECK11-NEXT: store i64 [[TMP11]], ptr [[DOTUB__ADDR_I]], align 8, !noalias [[META31]] +// CHECK11-NEXT: store i64 [[TMP13]], ptr [[DOTST__ADDR_I]], align 8, !noalias [[META31]] +// CHECK11-NEXT: store i32 [[TMP15]], ptr [[DOTLITER__ADDR_I]], align 4, !noalias [[META31]] +// CHECK11-NEXT: store ptr [[TMP17]], ptr [[DOTREDUCTIONS__ADDR_I]], align 4, !noalias [[META31]] +// CHECK11-NEXT: store ptr [[TMP7]], ptr [[__CONTEXT_ADDR_I]], align 4, !noalias [[META31]] +// CHECK11-NEXT: [[TMP18:%.*]] = load ptr, ptr [[__CONTEXT_ADDR_I]], align 4, !noalias [[META31]] +// CHECK11-NEXT: [[TMP19:%.*]] = load i64, ptr [[DOTLB__ADDR_I]], align 8, !noalias [[META31]] +// CHECK11-NEXT: [[CONV_I:%.*]] = trunc i64 [[TMP19]] to i32 +// CHECK11-NEXT: store i32 [[CONV_I]], ptr [[DOTOMP_IV_I]], align 4, !noalias [[META31]] +// CHECK11-NEXT: br label [[OMP_INNER_FOR_COND_I:%.*]] +// CHECK11: omp.inner.for.cond.i: +// CHECK11-NEXT: [[TMP20:%.*]] = load i32, ptr [[DOTOMP_IV_I]], align 4, !noalias [[META31]], !llvm.access.group [[ACC_GRP32:![0-9]+]] +// CHECK11-NEXT: [[CONV1_I:%.*]] = sext i32 [[TMP20]] to i64 +// CHECK11-NEXT: [[TMP21:%.*]] = load i64, ptr [[DOTUB__ADDR_I]], align 8, !noalias [[META31]], !llvm.access.group [[ACC_GRP32]] +// CHECK11-NEXT: [[CMP_I:%.*]] = icmp ule i64 [[CONV1_I]], [[TMP21]] +// CHECK11-NEXT: br i1 [[CMP_I]], label [[OMP_INNER_FOR_BODY_I:%.*]], label [[DOTOMP_OUTLINED__1_EXIT:%.*]] +// CHECK11: omp.inner.for.body.i: +// CHECK11-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IV_I]], align 4, !noalias [[META31]], !llvm.access.group [[ACC_GRP32]] +// CHECK11-NEXT: store i32 [[TMP22]], ptr [[I_I]], align 4, !noalias [[META31]], !llvm.access.group [[ACC_GRP32]] +// CHECK11-NEXT: [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IV_I]], align 4, !noalias [[META31]], !llvm.access.group [[ACC_GRP32]] +// CHECK11-NEXT: [[ADD2_I:%.*]] = add nsw i32 [[TMP23]], 1 +// CHECK11-NEXT: store i32 [[ADD2_I]], ptr [[DOTOMP_IV_I]], align 4, !noalias [[META31]], !llvm.access.group [[ACC_GRP32]] +// CHECK11-NEXT: br label [[OMP_INNER_FOR_COND_I]], !llvm.loop [[LOOP33:![0-9]+]] +// CHECK11: .omp_outlined..1.exit: +// CHECK11-NEXT: ret i32 0 +// +// +// CHECK11-LABEL: define {{[^@]+}}@_Z5tmainIiET_v +// CHECK11-SAME: () #[[ATTR1]] comdat { +// CHECK11-NEXT: entry: +// CHECK11-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 +// CHECK11-NEXT: [[TEST:%.*]] = alloca [[STRUCT_S_2:%.*]], align 4 +// CHECK11-NEXT: [[T_VAR:%.*]] = alloca i32, align 4 +// CHECK11-NEXT: [[VEC:%.*]] = alloca [2 x i32], align 4 +// CHECK11-NEXT: [[S_ARR:%.*]] = alloca [2 x %struct.S.2], align 4 +// CHECK11-NEXT: [[VAR:%.*]] = alloca ptr, align 4 +// CHECK11-NEXT: [[AGG_CAPTURED:%.*]] = alloca [[STRUCT_ANON_3:%.*]], align 1 +// CHECK11-NEXT: [[TMP:%.*]] = alloca i32, align 4 +// CHECK11-NEXT: [[_TMP1:%.*]] = alloca ptr, align 4 +// CHECK11-NEXT: [[TMP0:%.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GLOB1]]) +// CHECK11-NEXT: call void @_ZN1SIiEC1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[TEST]]) +// CHECK11-NEXT: store i32 0, ptr [[T_VAR]], align 4 +// CHECK11-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[VEC]], ptr align 4 @__const._Z5tmainIiET_v.vec, i32 8, i1 false) +// CHECK11-NEXT: [[ARRAYINIT_BEGIN:%.*]] = getelementptr inbounds [2 x %struct.S.2], ptr [[S_ARR]], i32 0, i32 0 +// CHECK11-NEXT: call void @_ZN1SIiEC1Ei(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYINIT_BEGIN]], i32 noundef 1) +// CHECK11-NEXT: [[ARRAYINIT_ELEMENT:%.*]] = getelementptr inbounds [[STRUCT_S_2]], ptr [[ARRAYINIT_BEGIN]], i32 1 +// CHECK11-NEXT: call void @_ZN1SIiEC1Ei(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYINIT_ELEMENT]], i32 noundef 2) +// CHECK11-NEXT: store ptr [[TEST]], ptr [[VAR]], align 4 +// CHECK11-NEXT: call void @__kmpc_taskgroup(ptr @[[GLOB1]], i32 [[TMP0]]) +// CHECK11-NEXT: store ptr undef, ptr [[_TMP1]], align 4 +// CHECK11-NEXT: [[TMP1:%.*]] = call ptr @__kmpc_omp_task_alloc(ptr @[[GLOB1]], i32 [[TMP0]], i32 9, i32 76, i32 1, ptr @.omp_task_entry..5) +// CHECK11-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T_WITH_PRIVATES_4:%.*]], ptr [[TMP1]], i32 0, i32 0 +// CHECK11-NEXT: [[TMP3:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T_WITH_PRIVATES_4]], ptr [[TMP1]], i32 0, i32 1 +// CHECK11-NEXT: [[TMP4:%.*]] = getelementptr inbounds [[STRUCT__KMP_PRIVATES_T_5:%.*]], ptr [[TMP3]], i32 0, i32 2 +// CHECK11-NEXT: [[ARRAY_BEGIN:%.*]] = getelementptr inbounds [2 x %struct.S.2], ptr [[TMP4]], i32 0, i32 0 +// CHECK11-NEXT: [[ARRAYCTOR_END:%.*]] = getelementptr inbounds [[STRUCT_S_2]], ptr [[ARRAY_BEGIN]], i32 2 +// CHECK11-NEXT: br label [[ARRAYCTOR_LOOP:%.*]] +// CHECK11: arrayctor.loop: +// CHECK11-NEXT: [[ARRAYCTOR_CUR:%.*]] = phi ptr [ [[ARRAY_BEGIN]], [[ENTRY:%.*]] ], [ [[ARRAYCTOR_NEXT:%.*]], [[ARRAYCTOR_LOOP]] ] +// CHECK11-NEXT: call void @_ZN1SIiEC1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYCTOR_CUR]]) +// CHECK11-NEXT: [[ARRAYCTOR_NEXT]] = getelementptr inbounds [[STRUCT_S_2]], ptr [[ARRAYCTOR_CUR]], i32 1 +// CHECK11-NEXT: [[ARRAYCTOR_DONE:%.*]] = icmp eq ptr [[ARRAYCTOR_NEXT]], [[ARRAYCTOR_END]] +// CHECK11-NEXT: br i1 [[ARRAYCTOR_DONE]], label [[ARRAYCTOR_CONT:%.*]], label [[ARRAYCTOR_LOOP]] +// CHECK11: arrayctor.cont: +// CHECK11-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT__KMP_PRIVATES_T_5]], ptr [[TMP3]], i32 0, i32 3 +// CHECK11-NEXT: call void @_ZN1SIiEC1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[TMP5]]) +// CHECK11-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T:%.*]], ptr [[TMP2]], i32 0, i32 3 +// CHECK11-NEXT: store ptr @.omp_task_destructor..7, ptr [[TMP6]], align 4 +// CHECK11-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP2]], i32 0, i32 5 +// CHECK11-NEXT: store i64 0, ptr [[TMP7]], align 4 +// CHECK11-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP2]], i32 0, i32 6 +// CHECK11-NEXT: store i64 1, ptr [[TMP8]], align 4 +// CHECK11-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP2]], i32 0, i32 7 +// CHECK11-NEXT: store i64 1, ptr [[TMP9]], align 4 +// CHECK11-NEXT: [[TMP10:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP2]], i32 0, i32 9 +// CHECK11-NEXT: call void @llvm.memset.p0.i32(ptr align 4 [[TMP10]], i8 0, i32 4, i1 false) +// CHECK11-NEXT: [[TMP11:%.*]] = load i64, ptr [[TMP9]], align 4 +// CHECK11-NEXT: call void @__kmpc_taskloop(ptr @[[GLOB1]], i32 [[TMP0]], ptr [[TMP1]], i32 1, ptr [[TMP7]], ptr [[TMP8]], i64 [[TMP11]], i32 1, i32 0, i64 0, ptr @.omp_task_dup..6) +// CHECK11-NEXT: call void @__kmpc_end_taskgroup(ptr @[[GLOB1]], i32 [[TMP0]]) +// CHECK11-NEXT: store i32 0, ptr [[RETVAL]], align 4 +// CHECK11-NEXT: [[ARRAY_BEGIN2:%.*]] = getelementptr inbounds [2 x %struct.S.2], ptr [[S_ARR]], i32 0, i32 0 +// CHECK11-NEXT: [[TMP12:%.*]] = getelementptr inbounds [[STRUCT_S_2]], ptr [[ARRAY_BEGIN2]], i32 2 +// CHECK11-NEXT: br label [[ARRAYDESTROY_BODY:%.*]] +// CHECK11: arraydestroy.body: +// CHECK11-NEXT: [[ARRAYDESTROY_ELEMENTPAST:%.*]] = phi ptr [ [[TMP12]], [[ARRAYCTOR_CONT]] ], [ [[ARRAYDESTROY_ELEMENT:%.*]], [[ARRAYDESTROY_BODY]] ] +// CHECK11-NEXT: [[ARRAYDESTROY_ELEMENT]] = getelementptr inbounds [[STRUCT_S_2]], ptr [[ARRAYDESTROY_ELEMENTPAST]], i32 -1 +// CHECK11-NEXT: call void @_ZN1SIiED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYDESTROY_ELEMENT]]) #[[ATTR3]] +// CHECK11-NEXT: [[ARRAYDESTROY_DONE:%.*]] = icmp eq ptr [[ARRAYDESTROY_ELEMENT]], [[ARRAY_BEGIN2]] +// CHECK11-NEXT: br i1 [[ARRAYDESTROY_DONE]], label [[ARRAYDESTROY_DONE3:%.*]], label [[ARRAYDESTROY_BODY]] +// CHECK11: arraydestroy.done3: +// CHECK11-NEXT: call void @_ZN1SIiED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[TEST]]) #[[ATTR3]] +// CHECK11-NEXT: [[TMP13:%.*]] = load i32, ptr [[RETVAL]], align 4 +// CHECK11-NEXT: ret i32 [[TMP13]] +// +// +// CHECK11-LABEL: define {{[^@]+}}@_ZN1SIfEC2Ev +// CHECK11-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]]) unnamed_addr #[[ATTR1]] comdat align 2 { +// CHECK11-NEXT: entry: +// CHECK11-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4 +// CHECK11-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4 +// CHECK11-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4 +// CHECK11-NEXT: [[F:%.*]] = getelementptr inbounds [[STRUCT_S:%.*]], ptr [[THIS1]], i32 0, i32 0 +// CHECK11-NEXT: store float 0.000000e+00, ptr [[F]], align 4 +// CHECK11-NEXT: ret void +// +// +// CHECK11-LABEL: define {{[^@]+}}@_ZN1SIfEC2Ef +// CHECK11-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]], float noundef [[A:%.*]]) unnamed_addr #[[ATTR1]] comdat align 2 { +// CHECK11-NEXT: entry: +// CHECK11-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4 +// CHECK11-NEXT: [[A_ADDR:%.*]] = alloca float, align 4 +// CHECK11-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4 +// CHECK11-NEXT: store float [[A]], ptr [[A_ADDR]], align 4 +// CHECK11-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4 +// CHECK11-NEXT: [[F:%.*]] = getelementptr inbounds [[STRUCT_S:%.*]], ptr [[THIS1]], i32 0, i32 0 +// CHECK11-NEXT: [[TMP0:%.*]] = load float, ptr [[A_ADDR]], align 4 +// CHECK11-NEXT: store float [[TMP0]], ptr [[F]], align 4 +// CHECK11-NEXT: ret void +// +// +// CHECK11-LABEL: define {{[^@]+}}@_ZN1SIfED2Ev +// CHECK11-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]]) unnamed_addr #[[ATTR1]] comdat align 2 { +// CHECK11-NEXT: entry: +// CHECK11-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4 +// CHECK11-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4 +// CHECK11-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4 +// CHECK11-NEXT: ret void +// +// +// CHECK11-LABEL: define {{[^@]+}}@_ZN1SIiEC1Ev +// CHECK11-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]]) unnamed_addr #[[ATTR1]] comdat align 2 { +// CHECK11-NEXT: entry: +// CHECK11-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4 +// CHECK11-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4 +// CHECK11-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4 +// CHECK11-NEXT: call void @_ZN1SIiEC2Ev(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]]) +// CHECK11-NEXT: ret void +// +// +// CHECK11-LABEL: define {{[^@]+}}@_ZN1SIiEC1Ei +// CHECK11-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]], i32 noundef [[A:%.*]]) unnamed_addr #[[ATTR1]] comdat align 2 { +// CHECK11-NEXT: entry: +// CHECK11-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4 +// CHECK11-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 +// CHECK11-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4 +// CHECK11-NEXT: store i32 [[A]], ptr [[A_ADDR]], align 4 +// CHECK11-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4 +// CHECK11-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4 +// CHECK11-NEXT: call void @_ZN1SIiEC2Ei(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]], i32 noundef [[TMP0]]) +// CHECK11-NEXT: ret void +// +// +// CHECK11-LABEL: define {{[^@]+}}@.omp_task_privates_map..4 +// CHECK11-SAME: (ptr noalias noundef [[TMP0:%.*]], ptr noalias noundef [[TMP1:%.*]], ptr noalias noundef [[TMP2:%.*]], ptr noalias noundef [[TMP3:%.*]], ptr noalias noundef [[TMP4:%.*]]) #[[ATTR5]] { +// CHECK11-NEXT: entry: +// CHECK11-NEXT: [[DOTADDR:%.*]] = alloca ptr, align 4 +// CHECK11-NEXT: [[DOTADDR1:%.*]] = alloca ptr, align 4 +// CHECK11-NEXT: [[DOTADDR2:%.*]] = alloca ptr, align 4 +// CHECK11-NEXT: [[DOTADDR3:%.*]] = alloca ptr, align 4 +// CHECK11-NEXT: [[DOTADDR4:%.*]] = alloca ptr, align 4 +// CHECK11-NEXT: store ptr [[TMP0]], ptr [[DOTADDR]], align 4 +// CHECK11-NEXT: store ptr [[TMP1]], ptr [[DOTADDR1]], align 4 +// CHECK11-NEXT: store ptr [[TMP2]], ptr [[DOTADDR2]], align 4 +// CHECK11-NEXT: store ptr [[TMP3]], ptr [[DOTADDR3]], align 4 +// CHECK11-NEXT: store ptr [[TMP4]], ptr [[DOTADDR4]], align 4 +// CHECK11-NEXT: [[TMP5:%.*]] = load ptr, ptr [[DOTADDR]], align 4 +// CHECK11-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT__KMP_PRIVATES_T_5:%.*]], ptr [[TMP5]], i32 0, i32 0 +// CHECK11-NEXT: [[TMP7:%.*]] = load ptr, ptr [[DOTADDR1]], align 4 +// CHECK11-NEXT: store ptr [[TMP6]], ptr [[TMP7]], align 4 +// CHECK11-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT__KMP_PRIVATES_T_5]], ptr [[TMP5]], i32 0, i32 1 +// CHECK11-NEXT: [[TMP9:%.*]] = load ptr, ptr [[DOTADDR2]], align 4 +// CHECK11-NEXT: store ptr [[TMP8]], ptr [[TMP9]], align 4 +// CHECK11-NEXT: [[TMP10:%.*]] = getelementptr inbounds [[STRUCT__KMP_PRIVATES_T_5]], ptr [[TMP5]], i32 0, i32 2 +// CHECK11-NEXT: [[TMP11:%.*]] = load ptr, ptr [[DOTADDR3]], align 4 +// CHECK11-NEXT: store ptr [[TMP10]], ptr [[TMP11]], align 4 +// CHECK11-NEXT: [[TMP12:%.*]] = getelementptr inbounds [[STRUCT__KMP_PRIVATES_T_5]], ptr [[TMP5]], i32 0, i32 3 +// CHECK11-NEXT: [[TMP13:%.*]] = load ptr, ptr [[DOTADDR4]], align 4 +// CHECK11-NEXT: store ptr [[TMP12]], ptr [[TMP13]], align 4 +// CHECK11-NEXT: ret void +// +// +// CHECK11-LABEL: define {{[^@]+}}@.omp_task_entry..5 +// CHECK11-SAME: (i32 noundef [[TMP0:%.*]], ptr noalias noundef [[TMP1:%.*]]) #[[ATTR6]] { +// CHECK11-NEXT: entry: +// CHECK11-NEXT: [[DOTGLOBAL_TID__ADDR_I:%.*]] = alloca i32, align 4 +// CHECK11-NEXT: [[DOTPART_ID__ADDR_I:%.*]] = alloca ptr, align 4 +// CHECK11-NEXT: [[DOTPRIVATES__ADDR_I:%.*]] = alloca ptr, align 4 +// CHECK11-NEXT: [[DOTCOPY_FN__ADDR_I:%.*]] = alloca ptr, align 4 +// CHECK11-NEXT: [[DOTTASK_T__ADDR_I:%.*]] = alloca ptr, align 4 +// CHECK11-NEXT: [[DOTLB__ADDR_I:%.*]] = alloca i64, align 8 +// CHECK11-NEXT: [[DOTUB__ADDR_I:%.*]] = alloca i64, align 8 +// CHECK11-NEXT: [[DOTST__ADDR_I:%.*]] = alloca i64, align 8 +// CHECK11-NEXT: [[DOTLITER__ADDR_I:%.*]] = alloca i32, align 4 +// CHECK11-NEXT: [[DOTREDUCTIONS__ADDR_I:%.*]] = alloca ptr, align 4 +// CHECK11-NEXT: [[__CONTEXT_ADDR_I:%.*]] = alloca ptr, align 4 +// CHECK11-NEXT: [[DOTPRIV_PTR_ADDR_I:%.*]] = alloca ptr, align 4 +// CHECK11-NEXT: [[DOTPRIV_PTR_ADDR1_I:%.*]] = alloca ptr, align 4 +// CHECK11-NEXT: [[DOTPRIV_PTR_ADDR2_I:%.*]] = alloca ptr, align 4 +// CHECK11-NEXT: [[DOTPRIV_PTR_ADDR3_I:%.*]] = alloca ptr, align 4 +// CHECK11-NEXT: [[TMP_I:%.*]] = alloca ptr, align 4 +// CHECK11-NEXT: [[TMP5_I:%.*]] = alloca ptr, align 4 +// CHECK11-NEXT: [[I_I:%.*]] = alloca i32, align 4 +// CHECK11-NEXT: [[DOTOMP_IV_I:%.*]] = alloca i32, align 4 +// CHECK11-NEXT: [[DOTADDR:%.*]] = alloca i32, align 4 +// CHECK11-NEXT: [[DOTADDR1:%.*]] = alloca ptr, align 4 +// CHECK11-NEXT: store i32 [[TMP0]], ptr [[DOTADDR]], align 4 +// CHECK11-NEXT: store ptr [[TMP1]], ptr [[DOTADDR1]], align 4 +// CHECK11-NEXT: [[TMP2:%.*]] = load i32, ptr [[DOTADDR]], align 4 +// CHECK11-NEXT: [[TMP3:%.*]] = load ptr, ptr [[DOTADDR1]], align 4 +// CHECK11-NEXT: [[TMP4:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T_WITH_PRIVATES_4:%.*]], ptr [[TMP3]], i32 0, i32 0 +// CHECK11-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T:%.*]], ptr [[TMP4]], i32 0, i32 2 +// CHECK11-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP4]], i32 0, i32 0 +// CHECK11-NEXT: [[TMP7:%.*]] = load ptr, ptr [[TMP6]], align 4 +// CHECK11-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T_WITH_PRIVATES_4]], ptr [[TMP3]], i32 0, i32 1 +// CHECK11-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP4]], i32 0, i32 5 +// CHECK11-NEXT: [[TMP10:%.*]] = load i64, ptr [[TMP9]], align 4 +// CHECK11-NEXT: [[TMP11:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP4]], i32 0, i32 6 +// CHECK11-NEXT: [[TMP12:%.*]] = load i64, ptr [[TMP11]], align 4 +// CHECK11-NEXT: [[TMP13:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP4]], i32 0, i32 7 +// CHECK11-NEXT: [[TMP14:%.*]] = load i64, ptr [[TMP13]], align 4 +// CHECK11-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP4]], i32 0, i32 8 +// CHECK11-NEXT: [[TMP16:%.*]] = load i32, ptr [[TMP15]], align 4 +// CHECK11-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP4]], i32 0, i32 9 +// CHECK11-NEXT: [[TMP18:%.*]] = load ptr, ptr [[TMP17]], align 4 +// CHECK11-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META35:![0-9]+]]) +// CHECK11-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META38:![0-9]+]]) +// CHECK11-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META40:![0-9]+]]) +// CHECK11-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META42:![0-9]+]]) +// CHECK11-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META44:![0-9]+]]) +// CHECK11-NEXT: store i32 [[TMP2]], ptr [[DOTGLOBAL_TID__ADDR_I]], align 4, !noalias [[META46:![0-9]+]] +// CHECK11-NEXT: store ptr [[TMP5]], ptr [[DOTPART_ID__ADDR_I]], align 4, !noalias [[META46]] +// CHECK11-NEXT: store ptr [[TMP8]], ptr [[DOTPRIVATES__ADDR_I]], align 4, !noalias [[META46]] +// CHECK11-NEXT: store ptr @.omp_task_privates_map..4, ptr [[DOTCOPY_FN__ADDR_I]], align 4, !noalias [[META46]] +// CHECK11-NEXT: store ptr [[TMP3]], ptr [[DOTTASK_T__ADDR_I]], align 4, !noalias [[META46]] +// CHECK11-NEXT: store i64 [[TMP10]], ptr [[DOTLB__ADDR_I]], align 8, !noalias [[META46]] +// CHECK11-NEXT: store i64 [[TMP12]], ptr [[DOTUB__ADDR_I]], align 8, !noalias [[META46]] +// CHECK11-NEXT: store i64 [[TMP14]], ptr [[DOTST__ADDR_I]], align 8, !noalias [[META46]] +// CHECK11-NEXT: store i32 [[TMP16]], ptr [[DOTLITER__ADDR_I]], align 4, !noalias [[META46]] +// CHECK11-NEXT: store ptr [[TMP18]], ptr [[DOTREDUCTIONS__ADDR_I]], align 4, !noalias [[META46]] +// CHECK11-NEXT: store ptr [[TMP7]], ptr [[__CONTEXT_ADDR_I]], align 4, !noalias [[META46]] +// CHECK11-NEXT: [[TMP19:%.*]] = load ptr, ptr [[__CONTEXT_ADDR_I]], align 4, !noalias [[META46]] +// CHECK11-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTCOPY_FN__ADDR_I]], align 4, !noalias [[META46]] +// CHECK11-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTPRIVATES__ADDR_I]], align 4, !noalias [[META46]] +// CHECK11-NEXT: call void [[TMP20]](ptr [[TMP21]], ptr [[DOTPRIV_PTR_ADDR_I]], ptr [[DOTPRIV_PTR_ADDR1_I]], ptr [[DOTPRIV_PTR_ADDR2_I]], ptr [[DOTPRIV_PTR_ADDR3_I]]) #[[ATTR3]] +// CHECK11-NEXT: [[TMP22:%.*]] = load ptr, ptr [[DOTPRIV_PTR_ADDR_I]], align 4, !noalias [[META46]] +// CHECK11-NEXT: [[TMP23:%.*]] = load ptr, ptr [[DOTPRIV_PTR_ADDR1_I]], align 4, !noalias [[META46]] +// CHECK11-NEXT: [[TMP24:%.*]] = load ptr, ptr [[DOTPRIV_PTR_ADDR2_I]], align 4, !noalias [[META46]] +// CHECK11-NEXT: [[TMP25:%.*]] = load ptr, ptr [[DOTPRIV_PTR_ADDR3_I]], align 4, !noalias [[META46]] +// CHECK11-NEXT: store ptr [[TMP25]], ptr [[TMP_I]], align 4, !noalias [[META46]] +// CHECK11-NEXT: store ptr undef, ptr [[TMP5_I]], align 4, !noalias [[META46]] +// CHECK11-NEXT: [[TMP26:%.*]] = load i64, ptr [[DOTLB__ADDR_I]], align 8, !noalias [[META46]] +// CHECK11-NEXT: [[CONV_I:%.*]] = trunc i64 [[TMP26]] to i32 +// CHECK11-NEXT: store i32 [[CONV_I]], ptr [[DOTOMP_IV_I]], align 4, !noalias [[META46]] +// CHECK11-NEXT: br label [[OMP_INNER_FOR_COND_I:%.*]] +// CHECK11: omp.inner.for.cond.i: +// CHECK11-NEXT: [[TMP27:%.*]] = load i32, ptr [[DOTOMP_IV_I]], align 4, !noalias [[META46]], !llvm.access.group [[ACC_GRP47:![0-9]+]] +// CHECK11-NEXT: [[CONV6_I:%.*]] = sext i32 [[TMP27]] to i64 +// CHECK11-NEXT: [[TMP28:%.*]] = load i64, ptr [[DOTUB__ADDR_I]], align 8, !noalias [[META46]], !llvm.access.group [[ACC_GRP47]] +// CHECK11-NEXT: [[CMP_I:%.*]] = icmp ule i64 [[CONV6_I]], [[TMP28]] +// CHECK11-NEXT: br i1 [[CMP_I]], label [[OMP_INNER_FOR_BODY_I:%.*]], label [[DOTOMP_OUTLINED__3_EXIT:%.*]] +// CHECK11: omp.inner.for.body.i: +// CHECK11-NEXT: [[TMP29:%.*]] = load i32, ptr [[DOTOMP_IV_I]], align 4, !noalias [[META46]], !llvm.access.group [[ACC_GRP47]] +// CHECK11-NEXT: store i32 [[TMP29]], ptr [[I_I]], align 4, !noalias [[META46]], !llvm.access.group [[ACC_GRP47]] +// CHECK11-NEXT: [[TMP30:%.*]] = load i32, ptr [[TMP22]], align 4, !llvm.access.group [[ACC_GRP47]] +// CHECK11-NEXT: [[TMP31:%.*]] = load i32, ptr [[I_I]], align 4, !noalias [[META46]], !llvm.access.group [[ACC_GRP47]] +// CHECK11-NEXT: [[ARRAYIDX_I:%.*]] = getelementptr inbounds [2 x i32], ptr [[TMP23]], i32 0, i32 [[TMP31]] +// CHECK11-NEXT: store i32 [[TMP30]], ptr [[ARRAYIDX_I]], align 4, !llvm.access.group [[ACC_GRP47]] +// CHECK11-NEXT: [[TMP32:%.*]] = load ptr, ptr [[TMP_I]], align 4, !noalias [[META46]], !llvm.access.group [[ACC_GRP47]] +// CHECK11-NEXT: [[TMP33:%.*]] = load i32, ptr [[I_I]], align 4, !noalias [[META46]], !llvm.access.group [[ACC_GRP47]] +// CHECK11-NEXT: [[ARRAYIDX7_I:%.*]] = getelementptr inbounds [2 x %struct.S.2], ptr [[TMP24]], i32 0, i32 [[TMP33]] +// CHECK11-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[ARRAYIDX7_I]], ptr align 4 [[TMP32]], i32 4, i1 false), !llvm.access.group [[ACC_GRP47]] +// CHECK11-NEXT: [[TMP34:%.*]] = load i32, ptr [[DOTOMP_IV_I]], align 4, !noalias [[META46]], !llvm.access.group [[ACC_GRP47]] +// CHECK11-NEXT: [[ADD8_I:%.*]] = add nsw i32 [[TMP34]], 1 +// CHECK11-NEXT: store i32 [[ADD8_I]], ptr [[DOTOMP_IV_I]], align 4, !noalias [[META46]], !llvm.access.group [[ACC_GRP47]] +// CHECK11-NEXT: br label [[OMP_INNER_FOR_COND_I]], !llvm.loop [[LOOP48:![0-9]+]] +// CHECK11: .omp_outlined..3.exit: +// CHECK11-NEXT: ret i32 0 +// +// +// CHECK11-LABEL: define {{[^@]+}}@.omp_task_dup..6 +// CHECK11-SAME: (ptr noundef [[TMP0:%.*]], ptr noundef [[TMP1:%.*]], i32 noundef [[TMP2:%.*]]) #[[ATTR6]] { +// CHECK11-NEXT: entry: +// CHECK11-NEXT: [[DOTADDR:%.*]] = alloca ptr, align 4 +// CHECK11-NEXT: [[DOTADDR1:%.*]] = alloca ptr, align 4 +// CHECK11-NEXT: [[DOTADDR2:%.*]] = alloca i32, align 4 +// CHECK11-NEXT: store ptr [[TMP0]], ptr [[DOTADDR]], align 4 +// CHECK11-NEXT: store ptr [[TMP1]], ptr [[DOTADDR1]], align 4 +// CHECK11-NEXT: store i32 [[TMP2]], ptr [[DOTADDR2]], align 4 +// CHECK11-NEXT: [[TMP3:%.*]] = load ptr, ptr [[DOTADDR]], align 4 +// CHECK11-NEXT: [[TMP4:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T_WITH_PRIVATES_4:%.*]], ptr [[TMP3]], i32 0, i32 1 +// CHECK11-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT__KMP_PRIVATES_T_5:%.*]], ptr [[TMP4]], i32 0, i32 2 +// CHECK11-NEXT: [[ARRAY_BEGIN:%.*]] = getelementptr inbounds [2 x %struct.S.2], ptr [[TMP5]], i32 0, i32 0 +// CHECK11-NEXT: [[ARRAYCTOR_END:%.*]] = getelementptr inbounds [[STRUCT_S_2:%.*]], ptr [[ARRAY_BEGIN]], i32 2 +// CHECK11-NEXT: br label [[ARRAYCTOR_LOOP:%.*]] +// CHECK11: arrayctor.loop: +// CHECK11-NEXT: [[ARRAYCTOR_CUR:%.*]] = phi ptr [ [[ARRAY_BEGIN]], [[ENTRY:%.*]] ], [ [[ARRAYCTOR_NEXT:%.*]], [[ARRAYCTOR_LOOP]] ] +// CHECK11-NEXT: call void @_ZN1SIiEC1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYCTOR_CUR]]) +// CHECK11-NEXT: [[ARRAYCTOR_NEXT]] = getelementptr inbounds [[STRUCT_S_2]], ptr [[ARRAYCTOR_CUR]], i32 1 +// CHECK11-NEXT: [[ARRAYCTOR_DONE:%.*]] = icmp eq ptr [[ARRAYCTOR_NEXT]], [[ARRAYCTOR_END]] +// CHECK11-NEXT: br i1 [[ARRAYCTOR_DONE]], label [[ARRAYCTOR_CONT:%.*]], label [[ARRAYCTOR_LOOP]] +// CHECK11: arrayctor.cont: +// CHECK11-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT__KMP_PRIVATES_T_5]], ptr [[TMP4]], i32 0, i32 3 +// CHECK11-NEXT: call void @_ZN1SIiEC1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[TMP6]]) +// CHECK11-NEXT: ret void +// +// +// CHECK11-LABEL: define {{[^@]+}}@.omp_task_destructor..7 +// CHECK11-SAME: (i32 noundef [[TMP0:%.*]], ptr noalias noundef [[TMP1:%.*]]) #[[ATTR6]] { +// CHECK11-NEXT: entry: +// CHECK11-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 +// CHECK11-NEXT: [[DOTADDR:%.*]] = alloca i32, align 4 +// CHECK11-NEXT: [[DOTADDR1:%.*]] = alloca ptr, align 4 +// CHECK11-NEXT: store i32 [[TMP0]], ptr [[DOTADDR]], align 4 +// CHECK11-NEXT: store ptr [[TMP1]], ptr [[DOTADDR1]], align 4 +// CHECK11-NEXT: [[TMP2:%.*]] = load ptr, ptr [[DOTADDR1]], align 4 +// CHECK11-NEXT: [[TMP3:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T_WITH_PRIVATES_4:%.*]], ptr [[TMP2]], i32 0, i32 1 +// CHECK11-NEXT: [[TMP4:%.*]] = getelementptr inbounds [[STRUCT__KMP_PRIVATES_T_5:%.*]], ptr [[TMP3]], i32 0, i32 2 +// CHECK11-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT__KMP_PRIVATES_T_5]], ptr [[TMP3]], i32 0, i32 3 +// CHECK11-NEXT: call void @_ZN1SIiED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[TMP5]]) #[[ATTR3]] +// CHECK11-NEXT: [[ARRAY_BEGIN:%.*]] = getelementptr inbounds [2 x %struct.S.2], ptr [[TMP4]], i32 0, i32 0 +// CHECK11-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT_S_2:%.*]], ptr [[ARRAY_BEGIN]], i32 2 +// CHECK11-NEXT: br label [[ARRAYDESTROY_BODY:%.*]] +// CHECK11: arraydestroy.body: +// CHECK11-NEXT: [[ARRAYDESTROY_ELEMENTPAST:%.*]] = phi ptr [ [[TMP6]], [[ENTRY:%.*]] ], [ [[ARRAYDESTROY_ELEMENT:%.*]], [[ARRAYDESTROY_BODY]] ] +// CHECK11-NEXT: [[ARRAYDESTROY_ELEMENT]] = getelementptr inbounds [[STRUCT_S_2]], ptr [[ARRAYDESTROY_ELEMENTPAST]], i32 -1 +// CHECK11-NEXT: call void @_ZN1SIiED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYDESTROY_ELEMENT]]) #[[ATTR3]] +// CHECK11-NEXT: [[ARRAYDESTROY_DONE:%.*]] = icmp eq ptr [[ARRAYDESTROY_ELEMENT]], [[ARRAY_BEGIN]] +// CHECK11-NEXT: br i1 [[ARRAYDESTROY_DONE]], label [[ARRAYDESTROY_DONE2:%.*]], label [[ARRAYDESTROY_BODY]] +// CHECK11: arraydestroy.done2: +// CHECK11-NEXT: [[TMP7:%.*]] = load i32, ptr [[RETVAL]], align 4 +// CHECK11-NEXT: ret i32 [[TMP7]] +// +// +// CHECK11-LABEL: define {{[^@]+}}@_ZN1SIiED1Ev +// CHECK11-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]]) unnamed_addr #[[ATTR1]] comdat align 2 { +// CHECK11-NEXT: entry: +// CHECK11-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4 +// CHECK11-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4 +// CHECK11-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4 +// CHECK11-NEXT: call void @_ZN1SIiED2Ev(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]]) #[[ATTR3]] +// CHECK11-NEXT: ret void +// +// +// CHECK11-LABEL: define {{[^@]+}}@_ZN1SIiEC2Ev +// CHECK11-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]]) unnamed_addr #[[ATTR1]] comdat align 2 { +// CHECK11-NEXT: entry: +// CHECK11-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4 +// CHECK11-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4 +// CHECK11-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4 +// CHECK11-NEXT: [[F:%.*]] = getelementptr inbounds [[STRUCT_S_2:%.*]], ptr [[THIS1]], i32 0, i32 0 +// CHECK11-NEXT: store i32 0, ptr [[F]], align 4 +// CHECK11-NEXT: ret void +// +// +// CHECK11-LABEL: define {{[^@]+}}@_ZN1SIiEC2Ei +// CHECK11-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]], i32 noundef [[A:%.*]]) unnamed_addr #[[ATTR1]] comdat align 2 { +// CHECK11-NEXT: entry: +// CHECK11-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4 +// CHECK11-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 +// CHECK11-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4 +// CHECK11-NEXT: store i32 [[A]], ptr [[A_ADDR]], align 4 +// CHECK11-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4 +// CHECK11-NEXT: [[F:%.*]] = getelementptr inbounds [[STRUCT_S_2:%.*]], ptr [[THIS1]], i32 0, i32 0 +// CHECK11-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4 +// CHECK11-NEXT: store i32 [[TMP0]], ptr [[F]], align 4 +// CHECK11-NEXT: ret void +// +// +// CHECK11-LABEL: define {{[^@]+}}@_ZN1SIiED2Ev +// CHECK11-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]]) unnamed_addr #[[ATTR1]] comdat align 2 { +// CHECK11-NEXT: entry: +// CHECK11-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4 +// CHECK11-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4 +// CHECK11-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4 +// CHECK11-NEXT: ret void +// +// +// CHECK13-LABEL: define {{[^@]+}}@main +// CHECK13-SAME: () #[[ATTR0:[0-9]+]] { +// CHECK13-NEXT: entry: +// CHECK13-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 +// CHECK13-NEXT: [[G:%.*]] = alloca double, align 8 +// CHECK13-NEXT: [[G1:%.*]] = alloca ptr, align 8 +// CHECK13-NEXT: [[TEST:%.*]] = alloca [[STRUCT_S:%.*]], align 4 +// CHECK13-NEXT: [[T_VAR:%.*]] = alloca i32, align 4 +// CHECK13-NEXT: [[VEC:%.*]] = alloca [2 x i32], align 4 +// CHECK13-NEXT: [[S_ARR:%.*]] = alloca [2 x %struct.S], align 4 +// CHECK13-NEXT: [[VAR:%.*]] = alloca ptr, align 8 +// CHECK13-NEXT: [[TMP:%.*]] = alloca i32, align 4 +// CHECK13-NEXT: [[_TMP1:%.*]] = alloca ptr, align 8 +// CHECK13-NEXT: [[DOTOMP_LB:%.*]] = alloca i64, align 8 +// CHECK13-NEXT: [[DOTOMP_UB:%.*]] = alloca i64, align 8 +// CHECK13-NEXT: [[DOTOMP_IV:%.*]] = alloca i32, align 4 +// CHECK13-NEXT: [[T_VAR2:%.*]] = alloca i32, align 4 +// CHECK13-NEXT: [[VEC3:%.*]] = alloca [2 x i32], align 4 +// CHECK13-NEXT: [[S_ARR4:%.*]] = alloca [2 x %struct.S], align 4 +// CHECK13-NEXT: [[VAR5:%.*]] = alloca [[STRUCT_S]], align 4 +// CHECK13-NEXT: [[_TMP6:%.*]] = alloca ptr, align 8 +// CHECK13-NEXT: [[SVAR:%.*]] = alloca i32, align 4 +// CHECK13-NEXT: [[I:%.*]] = alloca i32, align 4 +// CHECK13-NEXT: [[I13:%.*]] = alloca i32, align 4 +// CHECK13-NEXT: [[_TMP14:%.*]] = alloca i32, align 4 +// CHECK13-NEXT: [[DOTOMP_LB15:%.*]] = alloca i64, align 8 +// CHECK13-NEXT: [[DOTOMP_UB16:%.*]] = alloca i64, align 8 +// CHECK13-NEXT: [[DOTOMP_IV17:%.*]] = alloca i32, align 4 +// CHECK13-NEXT: [[I19:%.*]] = alloca i32, align 4 +// CHECK13-NEXT: store i32 0, ptr [[RETVAL]], align 4 +// CHECK13-NEXT: store ptr [[G]], ptr [[G1]], align 8 +// CHECK13-NEXT: call void @_ZN1SIfEC1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[TEST]]) +// CHECK13-NEXT: store i32 0, ptr [[T_VAR]], align 4 +// CHECK13-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[VEC]], ptr align 4 @__const.main.vec, i64 8, i1 false) +// CHECK13-NEXT: [[ARRAYINIT_BEGIN:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[S_ARR]], i64 0, i64 0 +// CHECK13-NEXT: call void @_ZN1SIfEC1Ef(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYINIT_BEGIN]], float noundef 1.000000e+00) +// CHECK13-NEXT: [[ARRAYINIT_ELEMENT:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAYINIT_BEGIN]], i64 1 +// CHECK13-NEXT: call void @_ZN1SIfEC1Ef(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYINIT_ELEMENT]], float noundef 2.000000e+00) +// CHECK13-NEXT: store ptr [[TEST]], ptr [[VAR]], align 8 +// CHECK13-NEXT: store ptr undef, ptr [[_TMP1]], align 8 +// CHECK13-NEXT: store i64 0, ptr [[DOTOMP_LB]], align 8 +// CHECK13-NEXT: store i64 1, ptr [[DOTOMP_UB]], align 8 +// CHECK13-NEXT: [[TMP0:%.*]] = load i64, ptr [[DOTOMP_LB]], align 8 +// CHECK13-NEXT: [[CONV:%.*]] = trunc i64 [[TMP0]] to i32 +// CHECK13-NEXT: store i32 [[CONV]], ptr [[DOTOMP_IV]], align 4 +// CHECK13-NEXT: [[ARRAY_BEGIN:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[S_ARR4]], i32 0, i32 0 +// CHECK13-NEXT: [[ARRAYCTOR_END:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAY_BEGIN]], i64 2 +// CHECK13-NEXT: br label [[ARRAYCTOR_LOOP:%.*]] +// CHECK13: arrayctor.loop: +// CHECK13-NEXT: [[ARRAYCTOR_CUR:%.*]] = phi ptr [ [[ARRAY_BEGIN]], [[ENTRY:%.*]] ], [ [[ARRAYCTOR_NEXT:%.*]], [[ARRAYCTOR_LOOP]] ] +// CHECK13-NEXT: call void @_ZN1SIfEC1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYCTOR_CUR]]) +// CHECK13-NEXT: [[ARRAYCTOR_NEXT]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAYCTOR_CUR]], i64 1 +// CHECK13-NEXT: [[ARRAYCTOR_DONE:%.*]] = icmp eq ptr [[ARRAYCTOR_NEXT]], [[ARRAYCTOR_END]] +// CHECK13-NEXT: br i1 [[ARRAYCTOR_DONE]], label [[ARRAYCTOR_CONT:%.*]], label [[ARRAYCTOR_LOOP]] +// CHECK13: arrayctor.cont: +// CHECK13-NEXT: call void @_ZN1SIfEC1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR5]]) +// CHECK13-NEXT: store ptr [[VAR5]], ptr [[_TMP6]], align 8 +// CHECK13-NEXT: br label [[OMP_INNER_FOR_COND:%.*]] +// CHECK13: omp.inner.for.cond: +// CHECK13-NEXT: [[TMP1:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4, !llvm.access.group [[ACC_GRP2:![0-9]+]] +// CHECK13-NEXT: [[CONV7:%.*]] = sext i32 [[TMP1]] to i64 +// CHECK13-NEXT: [[TMP2:%.*]] = load i64, ptr [[DOTOMP_UB]], align 8, !llvm.access.group [[ACC_GRP2]] +// CHECK13-NEXT: [[CMP:%.*]] = icmp ule i64 [[CONV7]], [[TMP2]] +// CHECK13-NEXT: br i1 [[CMP]], label [[OMP_INNER_FOR_BODY:%.*]], label [[OMP_INNER_FOR_COND_CLEANUP:%.*]] +// CHECK13: omp.inner.for.cond.cleanup: +// CHECK13-NEXT: br label [[OMP_INNER_FOR_END:%.*]] +// CHECK13: omp.inner.for.body: +// CHECK13-NEXT: [[TMP3:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4, !llvm.access.group [[ACC_GRP2]] +// CHECK13-NEXT: [[MUL:%.*]] = mul nsw i32 [[TMP3]], 1 +// CHECK13-NEXT: [[ADD:%.*]] = add nsw i32 0, [[MUL]] +// CHECK13-NEXT: store i32 [[ADD]], ptr [[I]], align 4, !llvm.access.group [[ACC_GRP2]] +// CHECK13-NEXT: [[TMP4:%.*]] = load i32, ptr [[T_VAR2]], align 4, !llvm.access.group [[ACC_GRP2]] +// CHECK13-NEXT: [[TMP5:%.*]] = load i32, ptr [[I]], align 4, !llvm.access.group [[ACC_GRP2]] +// CHECK13-NEXT: [[IDXPROM:%.*]] = sext i32 [[TMP5]] to i64 +// CHECK13-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x i32], ptr [[VEC3]], i64 0, i64 [[IDXPROM]] +// CHECK13-NEXT: store i32 [[TMP4]], ptr [[ARRAYIDX]], align 4, !llvm.access.group [[ACC_GRP2]] +// CHECK13-NEXT: [[TMP6:%.*]] = load ptr, ptr [[_TMP6]], align 8, !llvm.access.group [[ACC_GRP2]] +// CHECK13-NEXT: [[TMP7:%.*]] = load i32, ptr [[I]], align 4, !llvm.access.group [[ACC_GRP2]] +// CHECK13-NEXT: [[IDXPROM8:%.*]] = sext i32 [[TMP7]] to i64 +// CHECK13-NEXT: [[ARRAYIDX9:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[S_ARR4]], i64 0, i64 [[IDXPROM8]] +// CHECK13-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[ARRAYIDX9]], ptr align 4 [[TMP6]], i64 4, i1 false), !llvm.access.group [[ACC_GRP2]] +// CHECK13-NEXT: br label [[OMP_BODY_CONTINUE:%.*]] +// CHECK13: omp.body.continue: +// CHECK13-NEXT: br label [[OMP_INNER_FOR_INC:%.*]] +// CHECK13: omp.inner.for.inc: +// CHECK13-NEXT: [[TMP8:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4, !llvm.access.group [[ACC_GRP2]] +// CHECK13-NEXT: [[ADD10:%.*]] = add nsw i32 [[TMP8]], 1 +// CHECK13-NEXT: store i32 [[ADD10]], ptr [[DOTOMP_IV]], align 4, !llvm.access.group [[ACC_GRP2]] +// CHECK13-NEXT: br label [[OMP_INNER_FOR_COND]], !llvm.loop [[LOOP3:![0-9]+]] +// CHECK13: omp.inner.for.end: +// CHECK13-NEXT: store i32 2, ptr [[I]], align 4 +// CHECK13-NEXT: call void @_ZN1SIfED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR5]]) #[[ATTR3:[0-9]+]] +// CHECK13-NEXT: [[ARRAY_BEGIN11:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[S_ARR4]], i32 0, i32 0 +// CHECK13-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAY_BEGIN11]], i64 2 +// CHECK13-NEXT: br label [[ARRAYDESTROY_BODY:%.*]] +// CHECK13: arraydestroy.body: +// CHECK13-NEXT: [[ARRAYDESTROY_ELEMENTPAST:%.*]] = phi ptr [ [[TMP9]], [[OMP_INNER_FOR_END]] ], [ [[ARRAYDESTROY_ELEMENT:%.*]], [[ARRAYDESTROY_BODY]] ] +// CHECK13-NEXT: [[ARRAYDESTROY_ELEMENT]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAYDESTROY_ELEMENTPAST]], i64 -1 +// CHECK13-NEXT: call void @_ZN1SIfED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYDESTROY_ELEMENT]]) #[[ATTR3]] +// CHECK13-NEXT: [[ARRAYDESTROY_DONE:%.*]] = icmp eq ptr [[ARRAYDESTROY_ELEMENT]], [[ARRAY_BEGIN11]] +// CHECK13-NEXT: br i1 [[ARRAYDESTROY_DONE]], label [[ARRAYDESTROY_DONE12:%.*]], label [[ARRAYDESTROY_BODY]] +// CHECK13: arraydestroy.done12: +// CHECK13-NEXT: store i64 0, ptr [[DOTOMP_LB15]], align 8 +// CHECK13-NEXT: store i64 1, ptr [[DOTOMP_UB16]], align 8 +// CHECK13-NEXT: [[TMP10:%.*]] = load i64, ptr [[DOTOMP_LB15]], align 8 +// CHECK13-NEXT: [[CONV18:%.*]] = trunc i64 [[TMP10]] to i32 +// CHECK13-NEXT: store i32 [[CONV18]], ptr [[DOTOMP_IV17]], align 4 +// CHECK13-NEXT: br label [[OMP_INNER_FOR_COND20:%.*]] +// CHECK13: omp.inner.for.cond20: +// CHECK13-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IV17]], align 4, !llvm.access.group [[ACC_GRP6:![0-9]+]] +// CHECK13-NEXT: [[CONV21:%.*]] = sext i32 [[TMP11]] to i64 +// CHECK13-NEXT: [[TMP12:%.*]] = load i64, ptr [[DOTOMP_UB16]], align 8, !llvm.access.group [[ACC_GRP6]] +// CHECK13-NEXT: [[CMP22:%.*]] = icmp ule i64 [[CONV21]], [[TMP12]] +// CHECK13-NEXT: br i1 [[CMP22]], label [[OMP_INNER_FOR_BODY23:%.*]], label [[OMP_INNER_FOR_END29:%.*]] +// CHECK13: omp.inner.for.body23: +// CHECK13-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IV17]], align 4, !llvm.access.group [[ACC_GRP6]] +// CHECK13-NEXT: [[MUL24:%.*]] = mul nsw i32 [[TMP13]], 1 +// CHECK13-NEXT: [[ADD25:%.*]] = add nsw i32 0, [[MUL24]] +// CHECK13-NEXT: store i32 [[ADD25]], ptr [[I19]], align 4, !llvm.access.group [[ACC_GRP6]] +// CHECK13-NEXT: br label [[OMP_BODY_CONTINUE26:%.*]] +// CHECK13: omp.body.continue26: +// CHECK13-NEXT: br label [[OMP_INNER_FOR_INC27:%.*]] +// CHECK13: omp.inner.for.inc27: +// CHECK13-NEXT: [[TMP14:%.*]] = load i32, ptr [[DOTOMP_IV17]], align 4, !llvm.access.group [[ACC_GRP6]] +// CHECK13-NEXT: [[ADD28:%.*]] = add nsw i32 [[TMP14]], 1 +// CHECK13-NEXT: store i32 [[ADD28]], ptr [[DOTOMP_IV17]], align 4, !llvm.access.group [[ACC_GRP6]] +// CHECK13-NEXT: br label [[OMP_INNER_FOR_COND20]], !llvm.loop [[LOOP7:![0-9]+]] +// CHECK13: omp.inner.for.end29: +// CHECK13-NEXT: store i32 2, ptr [[I13]], align 4 +// CHECK13-NEXT: [[CALL:%.*]] = call noundef signext i32 @_Z5tmainIiET_v() +// CHECK13-NEXT: store i32 [[CALL]], ptr [[RETVAL]], align 4 +// CHECK13-NEXT: [[ARRAY_BEGIN30:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[S_ARR]], i32 0, i32 0 +// CHECK13-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAY_BEGIN30]], i64 2 +// CHECK13-NEXT: br label [[ARRAYDESTROY_BODY31:%.*]] +// CHECK13: arraydestroy.body31: +// CHECK13-NEXT: [[ARRAYDESTROY_ELEMENTPAST32:%.*]] = phi ptr [ [[TMP15]], [[OMP_INNER_FOR_END29]] ], [ [[ARRAYDESTROY_ELEMENT33:%.*]], [[ARRAYDESTROY_BODY31]] ] +// CHECK13-NEXT: [[ARRAYDESTROY_ELEMENT33]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAYDESTROY_ELEMENTPAST32]], i64 -1 +// CHECK13-NEXT: call void @_ZN1SIfED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYDESTROY_ELEMENT33]]) #[[ATTR3]] +// CHECK13-NEXT: [[ARRAYDESTROY_DONE34:%.*]] = icmp eq ptr [[ARRAYDESTROY_ELEMENT33]], [[ARRAY_BEGIN30]] +// CHECK13-NEXT: br i1 [[ARRAYDESTROY_DONE34]], label [[ARRAYDESTROY_DONE35:%.*]], label [[ARRAYDESTROY_BODY31]] +// CHECK13: arraydestroy.done35: +// CHECK13-NEXT: call void @_ZN1SIfED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[TEST]]) #[[ATTR3]] +// CHECK13-NEXT: [[TMP16:%.*]] = load i32, ptr [[RETVAL]], align 4 +// CHECK13-NEXT: ret i32 [[TMP16]] +// +// +// CHECK13-LABEL: define {{[^@]+}}@_ZN1SIfEC1Ev +// CHECK13-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]]) unnamed_addr #[[ATTR1:[0-9]+]] comdat { +// CHECK13-NEXT: entry: +// CHECK13-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK13-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 +// CHECK13-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK13-NEXT: call void @_ZN1SIfEC2Ev(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]]) +// CHECK13-NEXT: ret void +// +// +// CHECK13-LABEL: define {{[^@]+}}@_ZN1SIfEC1Ef +// CHECK13-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]], float noundef [[A:%.*]]) unnamed_addr #[[ATTR1]] comdat { +// CHECK13-NEXT: entry: +// CHECK13-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK13-NEXT: [[A_ADDR:%.*]] = alloca float, align 4 +// CHECK13-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 +// CHECK13-NEXT: store float [[A]], ptr [[A_ADDR]], align 4 +// CHECK13-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK13-NEXT: [[TMP0:%.*]] = load float, ptr [[A_ADDR]], align 4 +// CHECK13-NEXT: call void @_ZN1SIfEC2Ef(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]], float noundef [[TMP0]]) +// CHECK13-NEXT: ret void +// +// +// CHECK13-LABEL: define {{[^@]+}}@_ZN1SIfED1Ev +// CHECK13-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]]) unnamed_addr #[[ATTR1]] comdat { +// CHECK13-NEXT: entry: +// CHECK13-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK13-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 +// CHECK13-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK13-NEXT: call void @_ZN1SIfED2Ev(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]]) #[[ATTR3]] +// CHECK13-NEXT: ret void +// +// +// CHECK13-LABEL: define {{[^@]+}}@_Z5tmainIiET_v +// CHECK13-SAME: () #[[ATTR1]] comdat { +// CHECK13-NEXT: entry: +// CHECK13-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 +// CHECK13-NEXT: [[TEST:%.*]] = alloca [[STRUCT_S_0:%.*]], align 4 +// CHECK13-NEXT: [[T_VAR:%.*]] = alloca i32, align 4 +// CHECK13-NEXT: [[VEC:%.*]] = alloca [2 x i32], align 4 +// CHECK13-NEXT: [[S_ARR:%.*]] = alloca [2 x %struct.S.0], align 4 +// CHECK13-NEXT: [[VAR:%.*]] = alloca ptr, align 8 +// CHECK13-NEXT: [[TMP:%.*]] = alloca i32, align 4 +// CHECK13-NEXT: [[_TMP1:%.*]] = alloca ptr, align 8 +// CHECK13-NEXT: [[DOTOMP_LB:%.*]] = alloca i64, align 8 +// CHECK13-NEXT: [[DOTOMP_UB:%.*]] = alloca i64, align 8 +// CHECK13-NEXT: [[DOTOMP_IV:%.*]] = alloca i32, align 4 +// CHECK13-NEXT: [[T_VAR2:%.*]] = alloca i32, align 4 +// CHECK13-NEXT: [[VEC3:%.*]] = alloca [2 x i32], align 4 +// CHECK13-NEXT: [[S_ARR4:%.*]] = alloca [2 x %struct.S.0], align 4 +// CHECK13-NEXT: [[VAR5:%.*]] = alloca [[STRUCT_S_0]], align 4 +// CHECK13-NEXT: [[_TMP6:%.*]] = alloca ptr, align 8 +// CHECK13-NEXT: [[I:%.*]] = alloca i32, align 4 +// CHECK13-NEXT: call void @_ZN1SIiEC1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[TEST]]) +// CHECK13-NEXT: store i32 0, ptr [[T_VAR]], align 4 +// CHECK13-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[VEC]], ptr align 4 @__const._Z5tmainIiET_v.vec, i64 8, i1 false) +// CHECK13-NEXT: [[ARRAYINIT_BEGIN:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR]], i64 0, i64 0 +// CHECK13-NEXT: call void @_ZN1SIiEC1Ei(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYINIT_BEGIN]], i32 noundef signext 1) +// CHECK13-NEXT: [[ARRAYINIT_ELEMENT:%.*]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[ARRAYINIT_BEGIN]], i64 1 +// CHECK13-NEXT: call void @_ZN1SIiEC1Ei(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYINIT_ELEMENT]], i32 noundef signext 2) +// CHECK13-NEXT: store ptr [[TEST]], ptr [[VAR]], align 8 +// CHECK13-NEXT: store ptr undef, ptr [[_TMP1]], align 8 +// CHECK13-NEXT: store i64 0, ptr [[DOTOMP_LB]], align 8 +// CHECK13-NEXT: store i64 1, ptr [[DOTOMP_UB]], align 8 +// CHECK13-NEXT: [[TMP0:%.*]] = load i64, ptr [[DOTOMP_LB]], align 8 +// CHECK13-NEXT: [[CONV:%.*]] = trunc i64 [[TMP0]] to i32 +// CHECK13-NEXT: store i32 [[CONV]], ptr [[DOTOMP_IV]], align 4 +// CHECK13-NEXT: [[ARRAY_BEGIN:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR4]], i32 0, i32 0 +// CHECK13-NEXT: [[ARRAYCTOR_END:%.*]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[ARRAY_BEGIN]], i64 2 +// CHECK13-NEXT: br label [[ARRAYCTOR_LOOP:%.*]] +// CHECK13: arrayctor.loop: +// CHECK13-NEXT: [[ARRAYCTOR_CUR:%.*]] = phi ptr [ [[ARRAY_BEGIN]], [[ENTRY:%.*]] ], [ [[ARRAYCTOR_NEXT:%.*]], [[ARRAYCTOR_LOOP]] ] +// CHECK13-NEXT: call void @_ZN1SIiEC1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYCTOR_CUR]]) +// CHECK13-NEXT: [[ARRAYCTOR_NEXT]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[ARRAYCTOR_CUR]], i64 1 +// CHECK13-NEXT: [[ARRAYCTOR_DONE:%.*]] = icmp eq ptr [[ARRAYCTOR_NEXT]], [[ARRAYCTOR_END]] +// CHECK13-NEXT: br i1 [[ARRAYCTOR_DONE]], label [[ARRAYCTOR_CONT:%.*]], label [[ARRAYCTOR_LOOP]] +// CHECK13: arrayctor.cont: +// CHECK13-NEXT: call void @_ZN1SIiEC1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR5]]) +// CHECK13-NEXT: store ptr [[VAR5]], ptr [[_TMP6]], align 8 +// CHECK13-NEXT: br label [[OMP_INNER_FOR_COND:%.*]] +// CHECK13: omp.inner.for.cond: +// CHECK13-NEXT: [[TMP1:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4, !llvm.access.group [[ACC_GRP9:![0-9]+]] +// CHECK13-NEXT: [[CONV7:%.*]] = sext i32 [[TMP1]] to i64 +// CHECK13-NEXT: [[TMP2:%.*]] = load i64, ptr [[DOTOMP_UB]], align 8, !llvm.access.group [[ACC_GRP9]] +// CHECK13-NEXT: [[CMP:%.*]] = icmp ule i64 [[CONV7]], [[TMP2]] +// CHECK13-NEXT: br i1 [[CMP]], label [[OMP_INNER_FOR_BODY:%.*]], label [[OMP_INNER_FOR_COND_CLEANUP:%.*]] +// CHECK13: omp.inner.for.cond.cleanup: +// CHECK13-NEXT: br label [[OMP_INNER_FOR_END:%.*]] +// CHECK13: omp.inner.for.body: +// CHECK13-NEXT: [[TMP3:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4, !llvm.access.group [[ACC_GRP9]] +// CHECK13-NEXT: [[MUL:%.*]] = mul nsw i32 [[TMP3]], 1 +// CHECK13-NEXT: [[ADD:%.*]] = add nsw i32 0, [[MUL]] +// CHECK13-NEXT: store i32 [[ADD]], ptr [[I]], align 4, !llvm.access.group [[ACC_GRP9]] +// CHECK13-NEXT: [[TMP4:%.*]] = load i32, ptr [[T_VAR2]], align 4, !llvm.access.group [[ACC_GRP9]] +// CHECK13-NEXT: [[TMP5:%.*]] = load i32, ptr [[I]], align 4, !llvm.access.group [[ACC_GRP9]] +// CHECK13-NEXT: [[IDXPROM:%.*]] = sext i32 [[TMP5]] to i64 +// CHECK13-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x i32], ptr [[VEC3]], i64 0, i64 [[IDXPROM]] +// CHECK13-NEXT: store i32 [[TMP4]], ptr [[ARRAYIDX]], align 4, !llvm.access.group [[ACC_GRP9]] +// CHECK13-NEXT: [[TMP6:%.*]] = load ptr, ptr [[_TMP6]], align 8, !llvm.access.group [[ACC_GRP9]] +// CHECK13-NEXT: [[TMP7:%.*]] = load i32, ptr [[I]], align 4, !llvm.access.group [[ACC_GRP9]] +// CHECK13-NEXT: [[IDXPROM8:%.*]] = sext i32 [[TMP7]] to i64 +// CHECK13-NEXT: [[ARRAYIDX9:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR4]], i64 0, i64 [[IDXPROM8]] +// CHECK13-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[ARRAYIDX9]], ptr align 4 [[TMP6]], i64 4, i1 false), !llvm.access.group [[ACC_GRP9]] +// CHECK13-NEXT: br label [[OMP_BODY_CONTINUE:%.*]] +// CHECK13: omp.body.continue: +// CHECK13-NEXT: br label [[OMP_INNER_FOR_INC:%.*]] +// CHECK13: omp.inner.for.inc: +// CHECK13-NEXT: [[TMP8:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4, !llvm.access.group [[ACC_GRP9]] +// CHECK13-NEXT: [[ADD10:%.*]] = add nsw i32 [[TMP8]], 1 +// CHECK13-NEXT: store i32 [[ADD10]], ptr [[DOTOMP_IV]], align 4, !llvm.access.group [[ACC_GRP9]] +// CHECK13-NEXT: br label [[OMP_INNER_FOR_COND]], !llvm.loop [[LOOP10:![0-9]+]] +// CHECK13: omp.inner.for.end: +// CHECK13-NEXT: store i32 2, ptr [[I]], align 4 +// CHECK13-NEXT: call void @_ZN1SIiED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR5]]) #[[ATTR3]] +// CHECK13-NEXT: [[ARRAY_BEGIN11:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR4]], i32 0, i32 0 +// CHECK13-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[ARRAY_BEGIN11]], i64 2 +// CHECK13-NEXT: br label [[ARRAYDESTROY_BODY:%.*]] +// CHECK13: arraydestroy.body: +// CHECK13-NEXT: [[ARRAYDESTROY_ELEMENTPAST:%.*]] = phi ptr [ [[TMP9]], [[OMP_INNER_FOR_END]] ], [ [[ARRAYDESTROY_ELEMENT:%.*]], [[ARRAYDESTROY_BODY]] ] +// CHECK13-NEXT: [[ARRAYDESTROY_ELEMENT]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[ARRAYDESTROY_ELEMENTPAST]], i64 -1 +// CHECK13-NEXT: call void @_ZN1SIiED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYDESTROY_ELEMENT]]) #[[ATTR3]] +// CHECK13-NEXT: [[ARRAYDESTROY_DONE:%.*]] = icmp eq ptr [[ARRAYDESTROY_ELEMENT]], [[ARRAY_BEGIN11]] +// CHECK13-NEXT: br i1 [[ARRAYDESTROY_DONE]], label [[ARRAYDESTROY_DONE12:%.*]], label [[ARRAYDESTROY_BODY]] +// CHECK13: arraydestroy.done12: +// CHECK13-NEXT: store i32 0, ptr [[RETVAL]], align 4 +// CHECK13-NEXT: [[ARRAY_BEGIN13:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR]], i32 0, i32 0 +// CHECK13-NEXT: [[TMP10:%.*]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[ARRAY_BEGIN13]], i64 2 +// CHECK13-NEXT: br label [[ARRAYDESTROY_BODY14:%.*]] +// CHECK13: arraydestroy.body14: +// CHECK13-NEXT: [[ARRAYDESTROY_ELEMENTPAST15:%.*]] = phi ptr [ [[TMP10]], [[ARRAYDESTROY_DONE12]] ], [ [[ARRAYDESTROY_ELEMENT16:%.*]], [[ARRAYDESTROY_BODY14]] ] +// CHECK13-NEXT: [[ARRAYDESTROY_ELEMENT16]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[ARRAYDESTROY_ELEMENTPAST15]], i64 -1 +// CHECK13-NEXT: call void @_ZN1SIiED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYDESTROY_ELEMENT16]]) #[[ATTR3]] +// CHECK13-NEXT: [[ARRAYDESTROY_DONE17:%.*]] = icmp eq ptr [[ARRAYDESTROY_ELEMENT16]], [[ARRAY_BEGIN13]] +// CHECK13-NEXT: br i1 [[ARRAYDESTROY_DONE17]], label [[ARRAYDESTROY_DONE18:%.*]], label [[ARRAYDESTROY_BODY14]] +// CHECK13: arraydestroy.done18: +// CHECK13-NEXT: call void @_ZN1SIiED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[TEST]]) #[[ATTR3]] +// CHECK13-NEXT: [[TMP11:%.*]] = load i32, ptr [[RETVAL]], align 4 +// CHECK13-NEXT: ret i32 [[TMP11]] +// +// +// CHECK13-LABEL: define {{[^@]+}}@_ZN1SIfEC2Ev +// CHECK13-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]]) unnamed_addr #[[ATTR1]] comdat { +// CHECK13-NEXT: entry: +// CHECK13-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK13-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 +// CHECK13-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK13-NEXT: [[F:%.*]] = getelementptr inbounds [[STRUCT_S:%.*]], ptr [[THIS1]], i32 0, i32 0 +// CHECK13-NEXT: store float 0.000000e+00, ptr [[F]], align 4 +// CHECK13-NEXT: ret void +// +// +// CHECK13-LABEL: define {{[^@]+}}@_ZN1SIfED2Ev +// CHECK13-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]]) unnamed_addr #[[ATTR1]] comdat { +// CHECK13-NEXT: entry: +// CHECK13-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK13-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 +// CHECK13-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK13-NEXT: ret void +// +// +// CHECK13-LABEL: define {{[^@]+}}@_ZN1SIfEC2Ef +// CHECK13-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]], float noundef [[A:%.*]]) unnamed_addr #[[ATTR1]] comdat { +// CHECK13-NEXT: entry: +// CHECK13-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK13-NEXT: [[A_ADDR:%.*]] = alloca float, align 4 +// CHECK13-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 +// CHECK13-NEXT: store float [[A]], ptr [[A_ADDR]], align 4 +// CHECK13-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK13-NEXT: [[F:%.*]] = getelementptr inbounds [[STRUCT_S:%.*]], ptr [[THIS1]], i32 0, i32 0 +// CHECK13-NEXT: [[TMP0:%.*]] = load float, ptr [[A_ADDR]], align 4 +// CHECK13-NEXT: store float [[TMP0]], ptr [[F]], align 4 +// CHECK13-NEXT: ret void +// +// +// CHECK13-LABEL: define {{[^@]+}}@_ZN1SIiEC1Ev +// CHECK13-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]]) unnamed_addr #[[ATTR1]] comdat { +// CHECK13-NEXT: entry: +// CHECK13-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK13-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 +// CHECK13-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK13-NEXT: call void @_ZN1SIiEC2Ev(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]]) +// CHECK13-NEXT: ret void +// +// +// CHECK13-LABEL: define {{[^@]+}}@_ZN1SIiEC1Ei +// CHECK13-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]], i32 noundef signext [[A:%.*]]) unnamed_addr #[[ATTR1]] comdat { +// CHECK13-NEXT: entry: +// CHECK13-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK13-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 +// CHECK13-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 +// CHECK13-NEXT: store i32 [[A]], ptr [[A_ADDR]], align 4 +// CHECK13-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK13-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4 +// CHECK13-NEXT: call void @_ZN1SIiEC2Ei(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]], i32 noundef signext [[TMP0]]) +// CHECK13-NEXT: ret void +// +// +// CHECK13-LABEL: define {{[^@]+}}@_ZN1SIiED1Ev +// CHECK13-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]]) unnamed_addr #[[ATTR1]] comdat { +// CHECK13-NEXT: entry: +// CHECK13-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK13-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 +// CHECK13-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK13-NEXT: call void @_ZN1SIiED2Ev(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]]) #[[ATTR3]] +// CHECK13-NEXT: ret void +// +// +// CHECK13-LABEL: define {{[^@]+}}@_ZN1SIiEC2Ev +// CHECK13-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]]) unnamed_addr #[[ATTR1]] comdat { +// CHECK13-NEXT: entry: +// CHECK13-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK13-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 +// CHECK13-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK13-NEXT: [[F:%.*]] = getelementptr inbounds [[STRUCT_S_0:%.*]], ptr [[THIS1]], i32 0, i32 0 +// CHECK13-NEXT: store i32 0, ptr [[F]], align 4 +// CHECK13-NEXT: ret void +// +// +// CHECK13-LABEL: define {{[^@]+}}@_ZN1SIiEC2Ei +// CHECK13-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]], i32 noundef signext [[A:%.*]]) unnamed_addr #[[ATTR1]] comdat { +// CHECK13-NEXT: entry: +// CHECK13-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK13-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 +// CHECK13-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 +// CHECK13-NEXT: store i32 [[A]], ptr [[A_ADDR]], align 4 +// CHECK13-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK13-NEXT: [[F:%.*]] = getelementptr inbounds [[STRUCT_S_0:%.*]], ptr [[THIS1]], i32 0, i32 0 +// CHECK13-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4 +// CHECK13-NEXT: store i32 [[TMP0]], ptr [[F]], align 4 +// CHECK13-NEXT: ret void +// +// +// CHECK13-LABEL: define {{[^@]+}}@_ZN1SIiED2Ev +// CHECK13-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]]) unnamed_addr #[[ATTR1]] comdat { +// CHECK13-NEXT: entry: +// CHECK13-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK13-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 +// CHECK13-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK13-NEXT: ret void +// +// +// CHECK15-LABEL: define {{[^@]+}}@main +// CHECK15-SAME: () #[[ATTR0:[0-9]+]] { +// CHECK15-NEXT: entry: +// CHECK15-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 +// CHECK15-NEXT: [[G:%.*]] = alloca double, align 8 +// CHECK15-NEXT: [[G1:%.*]] = alloca ptr, align 4 +// CHECK15-NEXT: [[TEST:%.*]] = alloca [[STRUCT_S:%.*]], align 4 +// CHECK15-NEXT: [[T_VAR:%.*]] = alloca i32, align 4 +// CHECK15-NEXT: [[VEC:%.*]] = alloca [2 x i32], align 4 +// CHECK15-NEXT: [[S_ARR:%.*]] = alloca [2 x %struct.S], align 4 +// CHECK15-NEXT: [[VAR:%.*]] = alloca ptr, align 4 +// CHECK15-NEXT: [[TMP:%.*]] = alloca i32, align 4 +// CHECK15-NEXT: [[_TMP1:%.*]] = alloca ptr, align 4 +// CHECK15-NEXT: [[DOTOMP_LB:%.*]] = alloca i64, align 8 +// CHECK15-NEXT: [[DOTOMP_UB:%.*]] = alloca i64, align 8 +// CHECK15-NEXT: [[DOTOMP_IV:%.*]] = alloca i32, align 4 +// CHECK15-NEXT: [[T_VAR2:%.*]] = alloca i32, align 4 +// CHECK15-NEXT: [[VEC3:%.*]] = alloca [2 x i32], align 4 +// CHECK15-NEXT: [[S_ARR4:%.*]] = alloca [2 x %struct.S], align 4 +// CHECK15-NEXT: [[VAR5:%.*]] = alloca [[STRUCT_S]], align 4 +// CHECK15-NEXT: [[_TMP6:%.*]] = alloca ptr, align 4 +// CHECK15-NEXT: [[SVAR:%.*]] = alloca i32, align 4 +// CHECK15-NEXT: [[I:%.*]] = alloca i32, align 4 +// CHECK15-NEXT: [[I12:%.*]] = alloca i32, align 4 +// CHECK15-NEXT: [[_TMP13:%.*]] = alloca i32, align 4 +// CHECK15-NEXT: [[DOTOMP_LB14:%.*]] = alloca i64, align 8 +// CHECK15-NEXT: [[DOTOMP_UB15:%.*]] = alloca i64, align 8 +// CHECK15-NEXT: [[DOTOMP_IV16:%.*]] = alloca i32, align 4 +// CHECK15-NEXT: [[I18:%.*]] = alloca i32, align 4 +// CHECK15-NEXT: store i32 0, ptr [[RETVAL]], align 4 +// CHECK15-NEXT: store ptr [[G]], ptr [[G1]], align 4 +// CHECK15-NEXT: call void @_ZN1SIfEC1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[TEST]]) +// CHECK15-NEXT: store i32 0, ptr [[T_VAR]], align 4 +// CHECK15-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[VEC]], ptr align 4 @__const.main.vec, i32 8, i1 false) +// CHECK15-NEXT: [[ARRAYINIT_BEGIN:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[S_ARR]], i32 0, i32 0 +// CHECK15-NEXT: call void @_ZN1SIfEC1Ef(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYINIT_BEGIN]], float noundef 1.000000e+00) +// CHECK15-NEXT: [[ARRAYINIT_ELEMENT:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAYINIT_BEGIN]], i32 1 +// CHECK15-NEXT: call void @_ZN1SIfEC1Ef(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYINIT_ELEMENT]], float noundef 2.000000e+00) +// CHECK15-NEXT: store ptr [[TEST]], ptr [[VAR]], align 4 +// CHECK15-NEXT: store ptr undef, ptr [[_TMP1]], align 4 +// CHECK15-NEXT: store i64 0, ptr [[DOTOMP_LB]], align 8 +// CHECK15-NEXT: store i64 1, ptr [[DOTOMP_UB]], align 8 +// CHECK15-NEXT: [[TMP0:%.*]] = load i64, ptr [[DOTOMP_LB]], align 8 +// CHECK15-NEXT: [[CONV:%.*]] = trunc i64 [[TMP0]] to i32 +// CHECK15-NEXT: store i32 [[CONV]], ptr [[DOTOMP_IV]], align 4 +// CHECK15-NEXT: [[ARRAY_BEGIN:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[S_ARR4]], i32 0, i32 0 +// CHECK15-NEXT: [[ARRAYCTOR_END:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAY_BEGIN]], i32 2 +// CHECK15-NEXT: br label [[ARRAYCTOR_LOOP:%.*]] +// CHECK15: arrayctor.loop: +// CHECK15-NEXT: [[ARRAYCTOR_CUR:%.*]] = phi ptr [ [[ARRAY_BEGIN]], [[ENTRY:%.*]] ], [ [[ARRAYCTOR_NEXT:%.*]], [[ARRAYCTOR_LOOP]] ] +// CHECK15-NEXT: call void @_ZN1SIfEC1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYCTOR_CUR]]) +// CHECK15-NEXT: [[ARRAYCTOR_NEXT]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAYCTOR_CUR]], i32 1 +// CHECK15-NEXT: [[ARRAYCTOR_DONE:%.*]] = icmp eq ptr [[ARRAYCTOR_NEXT]], [[ARRAYCTOR_END]] +// CHECK15-NEXT: br i1 [[ARRAYCTOR_DONE]], label [[ARRAYCTOR_CONT:%.*]], label [[ARRAYCTOR_LOOP]] +// CHECK15: arrayctor.cont: +// CHECK15-NEXT: call void @_ZN1SIfEC1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR5]]) +// CHECK15-NEXT: store ptr [[VAR5]], ptr [[_TMP6]], align 4 +// CHECK15-NEXT: br label [[OMP_INNER_FOR_COND:%.*]] +// CHECK15: omp.inner.for.cond: +// CHECK15-NEXT: [[TMP1:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4, !llvm.access.group [[ACC_GRP3:![0-9]+]] +// CHECK15-NEXT: [[CONV7:%.*]] = sext i32 [[TMP1]] to i64 +// CHECK15-NEXT: [[TMP2:%.*]] = load i64, ptr [[DOTOMP_UB]], align 8, !llvm.access.group [[ACC_GRP3]] +// CHECK15-NEXT: [[CMP:%.*]] = icmp ule i64 [[CONV7]], [[TMP2]] +// CHECK15-NEXT: br i1 [[CMP]], label [[OMP_INNER_FOR_BODY:%.*]], label [[OMP_INNER_FOR_COND_CLEANUP:%.*]] +// CHECK15: omp.inner.for.cond.cleanup: +// CHECK15-NEXT: br label [[OMP_INNER_FOR_END:%.*]] +// CHECK15: omp.inner.for.body: +// CHECK15-NEXT: [[TMP3:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4, !llvm.access.group [[ACC_GRP3]] +// CHECK15-NEXT: [[MUL:%.*]] = mul nsw i32 [[TMP3]], 1 +// CHECK15-NEXT: [[ADD:%.*]] = add nsw i32 0, [[MUL]] +// CHECK15-NEXT: store i32 [[ADD]], ptr [[I]], align 4, !llvm.access.group [[ACC_GRP3]] +// CHECK15-NEXT: [[TMP4:%.*]] = load i32, ptr [[T_VAR2]], align 4, !llvm.access.group [[ACC_GRP3]] +// CHECK15-NEXT: [[TMP5:%.*]] = load i32, ptr [[I]], align 4, !llvm.access.group [[ACC_GRP3]] +// CHECK15-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x i32], ptr [[VEC3]], i32 0, i32 [[TMP5]] +// CHECK15-NEXT: store i32 [[TMP4]], ptr [[ARRAYIDX]], align 4, !llvm.access.group [[ACC_GRP3]] +// CHECK15-NEXT: [[TMP6:%.*]] = load ptr, ptr [[_TMP6]], align 4, !llvm.access.group [[ACC_GRP3]] +// CHECK15-NEXT: [[TMP7:%.*]] = load i32, ptr [[I]], align 4, !llvm.access.group [[ACC_GRP3]] +// CHECK15-NEXT: [[ARRAYIDX8:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[S_ARR4]], i32 0, i32 [[TMP7]] +// CHECK15-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[ARRAYIDX8]], ptr align 4 [[TMP6]], i32 4, i1 false), !llvm.access.group [[ACC_GRP3]] +// CHECK15-NEXT: br label [[OMP_BODY_CONTINUE:%.*]] +// CHECK15: omp.body.continue: +// CHECK15-NEXT: br label [[OMP_INNER_FOR_INC:%.*]] +// CHECK15: omp.inner.for.inc: +// CHECK15-NEXT: [[TMP8:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4, !llvm.access.group [[ACC_GRP3]] +// CHECK15-NEXT: [[ADD9:%.*]] = add nsw i32 [[TMP8]], 1 +// CHECK15-NEXT: store i32 [[ADD9]], ptr [[DOTOMP_IV]], align 4, !llvm.access.group [[ACC_GRP3]] +// CHECK15-NEXT: br label [[OMP_INNER_FOR_COND]], !llvm.loop [[LOOP4:![0-9]+]] +// CHECK15: omp.inner.for.end: +// CHECK15-NEXT: store i32 2, ptr [[I]], align 4 +// CHECK15-NEXT: call void @_ZN1SIfED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR5]]) #[[ATTR3:[0-9]+]] +// CHECK15-NEXT: [[ARRAY_BEGIN10:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[S_ARR4]], i32 0, i32 0 +// CHECK15-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAY_BEGIN10]], i32 2 +// CHECK15-NEXT: br label [[ARRAYDESTROY_BODY:%.*]] +// CHECK15: arraydestroy.body: +// CHECK15-NEXT: [[ARRAYDESTROY_ELEMENTPAST:%.*]] = phi ptr [ [[TMP9]], [[OMP_INNER_FOR_END]] ], [ [[ARRAYDESTROY_ELEMENT:%.*]], [[ARRAYDESTROY_BODY]] ] +// CHECK15-NEXT: [[ARRAYDESTROY_ELEMENT]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAYDESTROY_ELEMENTPAST]], i32 -1 +// CHECK15-NEXT: call void @_ZN1SIfED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYDESTROY_ELEMENT]]) #[[ATTR3]] +// CHECK15-NEXT: [[ARRAYDESTROY_DONE:%.*]] = icmp eq ptr [[ARRAYDESTROY_ELEMENT]], [[ARRAY_BEGIN10]] +// CHECK15-NEXT: br i1 [[ARRAYDESTROY_DONE]], label [[ARRAYDESTROY_DONE11:%.*]], label [[ARRAYDESTROY_BODY]] +// CHECK15: arraydestroy.done11: +// CHECK15-NEXT: store i64 0, ptr [[DOTOMP_LB14]], align 8 +// CHECK15-NEXT: store i64 1, ptr [[DOTOMP_UB15]], align 8 +// CHECK15-NEXT: [[TMP10:%.*]] = load i64, ptr [[DOTOMP_LB14]], align 8 +// CHECK15-NEXT: [[CONV17:%.*]] = trunc i64 [[TMP10]] to i32 +// CHECK15-NEXT: store i32 [[CONV17]], ptr [[DOTOMP_IV16]], align 4 +// CHECK15-NEXT: br label [[OMP_INNER_FOR_COND19:%.*]] +// CHECK15: omp.inner.for.cond19: +// CHECK15-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IV16]], align 4, !llvm.access.group [[ACC_GRP7:![0-9]+]] +// CHECK15-NEXT: [[CONV20:%.*]] = sext i32 [[TMP11]] to i64 +// CHECK15-NEXT: [[TMP12:%.*]] = load i64, ptr [[DOTOMP_UB15]], align 8, !llvm.access.group [[ACC_GRP7]] +// CHECK15-NEXT: [[CMP21:%.*]] = icmp ule i64 [[CONV20]], [[TMP12]] +// CHECK15-NEXT: br i1 [[CMP21]], label [[OMP_INNER_FOR_BODY22:%.*]], label [[OMP_INNER_FOR_END28:%.*]] +// CHECK15: omp.inner.for.body22: +// CHECK15-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IV16]], align 4, !llvm.access.group [[ACC_GRP7]] +// CHECK15-NEXT: [[MUL23:%.*]] = mul nsw i32 [[TMP13]], 1 +// CHECK15-NEXT: [[ADD24:%.*]] = add nsw i32 0, [[MUL23]] +// CHECK15-NEXT: store i32 [[ADD24]], ptr [[I18]], align 4, !llvm.access.group [[ACC_GRP7]] +// CHECK15-NEXT: br label [[OMP_BODY_CONTINUE25:%.*]] +// CHECK15: omp.body.continue25: +// CHECK15-NEXT: br label [[OMP_INNER_FOR_INC26:%.*]] +// CHECK15: omp.inner.for.inc26: +// CHECK15-NEXT: [[TMP14:%.*]] = load i32, ptr [[DOTOMP_IV16]], align 4, !llvm.access.group [[ACC_GRP7]] +// CHECK15-NEXT: [[ADD27:%.*]] = add nsw i32 [[TMP14]], 1 +// CHECK15-NEXT: store i32 [[ADD27]], ptr [[DOTOMP_IV16]], align 4, !llvm.access.group [[ACC_GRP7]] +// CHECK15-NEXT: br label [[OMP_INNER_FOR_COND19]], !llvm.loop [[LOOP8:![0-9]+]] +// CHECK15: omp.inner.for.end28: +// CHECK15-NEXT: store i32 2, ptr [[I12]], align 4 +// CHECK15-NEXT: [[CALL:%.*]] = call noundef i32 @_Z5tmainIiET_v() +// CHECK15-NEXT: store i32 [[CALL]], ptr [[RETVAL]], align 4 +// CHECK15-NEXT: [[ARRAY_BEGIN29:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[S_ARR]], i32 0, i32 0 +// CHECK15-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAY_BEGIN29]], i32 2 +// CHECK15-NEXT: br label [[ARRAYDESTROY_BODY30:%.*]] +// CHECK15: arraydestroy.body30: +// CHECK15-NEXT: [[ARRAYDESTROY_ELEMENTPAST31:%.*]] = phi ptr [ [[TMP15]], [[OMP_INNER_FOR_END28]] ], [ [[ARRAYDESTROY_ELEMENT32:%.*]], [[ARRAYDESTROY_BODY30]] ] +// CHECK15-NEXT: [[ARRAYDESTROY_ELEMENT32]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAYDESTROY_ELEMENTPAST31]], i32 -1 +// CHECK15-NEXT: call void @_ZN1SIfED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYDESTROY_ELEMENT32]]) #[[ATTR3]] +// CHECK15-NEXT: [[ARRAYDESTROY_DONE33:%.*]] = icmp eq ptr [[ARRAYDESTROY_ELEMENT32]], [[ARRAY_BEGIN29]] +// CHECK15-NEXT: br i1 [[ARRAYDESTROY_DONE33]], label [[ARRAYDESTROY_DONE34:%.*]], label [[ARRAYDESTROY_BODY30]] +// CHECK15: arraydestroy.done34: +// CHECK15-NEXT: call void @_ZN1SIfED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[TEST]]) #[[ATTR3]] +// CHECK15-NEXT: [[TMP16:%.*]] = load i32, ptr [[RETVAL]], align 4 +// CHECK15-NEXT: ret i32 [[TMP16]] +// +// +// CHECK15-LABEL: define {{[^@]+}}@_ZN1SIfEC1Ev +// CHECK15-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]]) unnamed_addr #[[ATTR1:[0-9]+]] comdat align 2 { +// CHECK15-NEXT: entry: +// CHECK15-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4 +// CHECK15-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4 +// CHECK15-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4 +// CHECK15-NEXT: call void @_ZN1SIfEC2Ev(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]]) +// CHECK15-NEXT: ret void +// +// +// CHECK15-LABEL: define {{[^@]+}}@_ZN1SIfEC1Ef +// CHECK15-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]], float noundef [[A:%.*]]) unnamed_addr #[[ATTR1]] comdat align 2 { +// CHECK15-NEXT: entry: +// CHECK15-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4 +// CHECK15-NEXT: [[A_ADDR:%.*]] = alloca float, align 4 +// CHECK15-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4 +// CHECK15-NEXT: store float [[A]], ptr [[A_ADDR]], align 4 +// CHECK15-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4 +// CHECK15-NEXT: [[TMP0:%.*]] = load float, ptr [[A_ADDR]], align 4 +// CHECK15-NEXT: call void @_ZN1SIfEC2Ef(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]], float noundef [[TMP0]]) +// CHECK15-NEXT: ret void +// +// +// CHECK15-LABEL: define {{[^@]+}}@_ZN1SIfED1Ev +// CHECK15-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]]) unnamed_addr #[[ATTR1]] comdat align 2 { +// CHECK15-NEXT: entry: +// CHECK15-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4 +// CHECK15-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4 +// CHECK15-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4 +// CHECK15-NEXT: call void @_ZN1SIfED2Ev(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]]) #[[ATTR3]] +// CHECK15-NEXT: ret void +// +// +// CHECK15-LABEL: define {{[^@]+}}@_Z5tmainIiET_v +// CHECK15-SAME: () #[[ATTR1]] comdat { +// CHECK15-NEXT: entry: +// CHECK15-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 +// CHECK15-NEXT: [[TEST:%.*]] = alloca [[STRUCT_S_0:%.*]], align 4 +// CHECK15-NEXT: [[T_VAR:%.*]] = alloca i32, align 4 +// CHECK15-NEXT: [[VEC:%.*]] = alloca [2 x i32], align 4 +// CHECK15-NEXT: [[S_ARR:%.*]] = alloca [2 x %struct.S.0], align 4 +// CHECK15-NEXT: [[VAR:%.*]] = alloca ptr, align 4 +// CHECK15-NEXT: [[TMP:%.*]] = alloca i32, align 4 +// CHECK15-NEXT: [[_TMP1:%.*]] = alloca ptr, align 4 +// CHECK15-NEXT: [[DOTOMP_LB:%.*]] = alloca i64, align 8 +// CHECK15-NEXT: [[DOTOMP_UB:%.*]] = alloca i64, align 8 +// CHECK15-NEXT: [[DOTOMP_IV:%.*]] = alloca i32, align 4 +// CHECK15-NEXT: [[T_VAR2:%.*]] = alloca i32, align 4 +// CHECK15-NEXT: [[VEC3:%.*]] = alloca [2 x i32], align 4 +// CHECK15-NEXT: [[S_ARR4:%.*]] = alloca [2 x %struct.S.0], align 4 +// CHECK15-NEXT: [[VAR5:%.*]] = alloca [[STRUCT_S_0]], align 4 +// CHECK15-NEXT: [[_TMP6:%.*]] = alloca ptr, align 4 +// CHECK15-NEXT: [[I:%.*]] = alloca i32, align 4 +// CHECK15-NEXT: call void @_ZN1SIiEC1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[TEST]]) +// CHECK15-NEXT: store i32 0, ptr [[T_VAR]], align 4 +// CHECK15-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[VEC]], ptr align 4 @__const._Z5tmainIiET_v.vec, i32 8, i1 false) +// CHECK15-NEXT: [[ARRAYINIT_BEGIN:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR]], i32 0, i32 0 +// CHECK15-NEXT: call void @_ZN1SIiEC1Ei(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYINIT_BEGIN]], i32 noundef 1) +// CHECK15-NEXT: [[ARRAYINIT_ELEMENT:%.*]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[ARRAYINIT_BEGIN]], i32 1 +// CHECK15-NEXT: call void @_ZN1SIiEC1Ei(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYINIT_ELEMENT]], i32 noundef 2) +// CHECK15-NEXT: store ptr [[TEST]], ptr [[VAR]], align 4 +// CHECK15-NEXT: store ptr undef, ptr [[_TMP1]], align 4 +// CHECK15-NEXT: store i64 0, ptr [[DOTOMP_LB]], align 8 +// CHECK15-NEXT: store i64 1, ptr [[DOTOMP_UB]], align 8 +// CHECK15-NEXT: [[TMP0:%.*]] = load i64, ptr [[DOTOMP_LB]], align 8 +// CHECK15-NEXT: [[CONV:%.*]] = trunc i64 [[TMP0]] to i32 +// CHECK15-NEXT: store i32 [[CONV]], ptr [[DOTOMP_IV]], align 4 +// CHECK15-NEXT: [[ARRAY_BEGIN:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR4]], i32 0, i32 0 +// CHECK15-NEXT: [[ARRAYCTOR_END:%.*]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[ARRAY_BEGIN]], i32 2 +// CHECK15-NEXT: br label [[ARRAYCTOR_LOOP:%.*]] +// CHECK15: arrayctor.loop: +// CHECK15-NEXT: [[ARRAYCTOR_CUR:%.*]] = phi ptr [ [[ARRAY_BEGIN]], [[ENTRY:%.*]] ], [ [[ARRAYCTOR_NEXT:%.*]], [[ARRAYCTOR_LOOP]] ] +// CHECK15-NEXT: call void @_ZN1SIiEC1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYCTOR_CUR]]) +// CHECK15-NEXT: [[ARRAYCTOR_NEXT]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[ARRAYCTOR_CUR]], i32 1 +// CHECK15-NEXT: [[ARRAYCTOR_DONE:%.*]] = icmp eq ptr [[ARRAYCTOR_NEXT]], [[ARRAYCTOR_END]] +// CHECK15-NEXT: br i1 [[ARRAYCTOR_DONE]], label [[ARRAYCTOR_CONT:%.*]], label [[ARRAYCTOR_LOOP]] +// CHECK15: arrayctor.cont: +// CHECK15-NEXT: call void @_ZN1SIiEC1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR5]]) +// CHECK15-NEXT: store ptr [[VAR5]], ptr [[_TMP6]], align 4 +// CHECK15-NEXT: br label [[OMP_INNER_FOR_COND:%.*]] +// CHECK15: omp.inner.for.cond: +// CHECK15-NEXT: [[TMP1:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4, !llvm.access.group [[ACC_GRP10:![0-9]+]] +// CHECK15-NEXT: [[CONV7:%.*]] = sext i32 [[TMP1]] to i64 +// CHECK15-NEXT: [[TMP2:%.*]] = load i64, ptr [[DOTOMP_UB]], align 8, !llvm.access.group [[ACC_GRP10]] +// CHECK15-NEXT: [[CMP:%.*]] = icmp ule i64 [[CONV7]], [[TMP2]] +// CHECK15-NEXT: br i1 [[CMP]], label [[OMP_INNER_FOR_BODY:%.*]], label [[OMP_INNER_FOR_COND_CLEANUP:%.*]] +// CHECK15: omp.inner.for.cond.cleanup: +// CHECK15-NEXT: br label [[OMP_INNER_FOR_END:%.*]] +// CHECK15: omp.inner.for.body: +// CHECK15-NEXT: [[TMP3:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4, !llvm.access.group [[ACC_GRP10]] +// CHECK15-NEXT: [[MUL:%.*]] = mul nsw i32 [[TMP3]], 1 +// CHECK15-NEXT: [[ADD:%.*]] = add nsw i32 0, [[MUL]] +// CHECK15-NEXT: store i32 [[ADD]], ptr [[I]], align 4, !llvm.access.group [[ACC_GRP10]] +// CHECK15-NEXT: [[TMP4:%.*]] = load i32, ptr [[T_VAR2]], align 4, !llvm.access.group [[ACC_GRP10]] +// CHECK15-NEXT: [[TMP5:%.*]] = load i32, ptr [[I]], align 4, !llvm.access.group [[ACC_GRP10]] +// CHECK15-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x i32], ptr [[VEC3]], i32 0, i32 [[TMP5]] +// CHECK15-NEXT: store i32 [[TMP4]], ptr [[ARRAYIDX]], align 4, !llvm.access.group [[ACC_GRP10]] +// CHECK15-NEXT: [[TMP6:%.*]] = load ptr, ptr [[_TMP6]], align 4, !llvm.access.group [[ACC_GRP10]] +// CHECK15-NEXT: [[TMP7:%.*]] = load i32, ptr [[I]], align 4, !llvm.access.group [[ACC_GRP10]] +// CHECK15-NEXT: [[ARRAYIDX8:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR4]], i32 0, i32 [[TMP7]] +// CHECK15-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[ARRAYIDX8]], ptr align 4 [[TMP6]], i32 4, i1 false), !llvm.access.group [[ACC_GRP10]] +// CHECK15-NEXT: br label [[OMP_BODY_CONTINUE:%.*]] +// CHECK15: omp.body.continue: +// CHECK15-NEXT: br label [[OMP_INNER_FOR_INC:%.*]] +// CHECK15: omp.inner.for.inc: +// CHECK15-NEXT: [[TMP8:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4, !llvm.access.group [[ACC_GRP10]] +// CHECK15-NEXT: [[ADD9:%.*]] = add nsw i32 [[TMP8]], 1 +// CHECK15-NEXT: store i32 [[ADD9]], ptr [[DOTOMP_IV]], align 4, !llvm.access.group [[ACC_GRP10]] +// CHECK15-NEXT: br label [[OMP_INNER_FOR_COND]], !llvm.loop [[LOOP11:![0-9]+]] +// CHECK15: omp.inner.for.end: +// CHECK15-NEXT: store i32 2, ptr [[I]], align 4 +// CHECK15-NEXT: call void @_ZN1SIiED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR5]]) #[[ATTR3]] +// CHECK15-NEXT: [[ARRAY_BEGIN10:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR4]], i32 0, i32 0 +// CHECK15-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[ARRAY_BEGIN10]], i32 2 +// CHECK15-NEXT: br label [[ARRAYDESTROY_BODY:%.*]] +// CHECK15: arraydestroy.body: +// CHECK15-NEXT: [[ARRAYDESTROY_ELEMENTPAST:%.*]] = phi ptr [ [[TMP9]], [[OMP_INNER_FOR_END]] ], [ [[ARRAYDESTROY_ELEMENT:%.*]], [[ARRAYDESTROY_BODY]] ] +// CHECK15-NEXT: [[ARRAYDESTROY_ELEMENT]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[ARRAYDESTROY_ELEMENTPAST]], i32 -1 +// CHECK15-NEXT: call void @_ZN1SIiED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYDESTROY_ELEMENT]]) #[[ATTR3]] +// CHECK15-NEXT: [[ARRAYDESTROY_DONE:%.*]] = icmp eq ptr [[ARRAYDESTROY_ELEMENT]], [[ARRAY_BEGIN10]] +// CHECK15-NEXT: br i1 [[ARRAYDESTROY_DONE]], label [[ARRAYDESTROY_DONE11:%.*]], label [[ARRAYDESTROY_BODY]] +// CHECK15: arraydestroy.done11: +// CHECK15-NEXT: store i32 0, ptr [[RETVAL]], align 4 +// CHECK15-NEXT: [[ARRAY_BEGIN12:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR]], i32 0, i32 0 +// CHECK15-NEXT: [[TMP10:%.*]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[ARRAY_BEGIN12]], i32 2 +// CHECK15-NEXT: br label [[ARRAYDESTROY_BODY13:%.*]] +// CHECK15: arraydestroy.body13: +// CHECK15-NEXT: [[ARRAYDESTROY_ELEMENTPAST14:%.*]] = phi ptr [ [[TMP10]], [[ARRAYDESTROY_DONE11]] ], [ [[ARRAYDESTROY_ELEMENT15:%.*]], [[ARRAYDESTROY_BODY13]] ] +// CHECK15-NEXT: [[ARRAYDESTROY_ELEMENT15]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[ARRAYDESTROY_ELEMENTPAST14]], i32 -1 +// CHECK15-NEXT: call void @_ZN1SIiED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYDESTROY_ELEMENT15]]) #[[ATTR3]] +// CHECK15-NEXT: [[ARRAYDESTROY_DONE16:%.*]] = icmp eq ptr [[ARRAYDESTROY_ELEMENT15]], [[ARRAY_BEGIN12]] +// CHECK15-NEXT: br i1 [[ARRAYDESTROY_DONE16]], label [[ARRAYDESTROY_DONE17:%.*]], label [[ARRAYDESTROY_BODY13]] +// CHECK15: arraydestroy.done17: +// CHECK15-NEXT: call void @_ZN1SIiED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[TEST]]) #[[ATTR3]] +// CHECK15-NEXT: [[TMP11:%.*]] = load i32, ptr [[RETVAL]], align 4 +// CHECK15-NEXT: ret i32 [[TMP11]] +// +// +// CHECK15-LABEL: define {{[^@]+}}@_ZN1SIfEC2Ev +// CHECK15-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]]) unnamed_addr #[[ATTR1]] comdat align 2 { +// CHECK15-NEXT: entry: +// CHECK15-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4 +// CHECK15-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4 +// CHECK15-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4 +// CHECK15-NEXT: [[F:%.*]] = getelementptr inbounds [[STRUCT_S:%.*]], ptr [[THIS1]], i32 0, i32 0 +// CHECK15-NEXT: store float 0.000000e+00, ptr [[F]], align 4 +// CHECK15-NEXT: ret void +// +// +// CHECK15-LABEL: define {{[^@]+}}@_ZN1SIfED2Ev +// CHECK15-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]]) unnamed_addr #[[ATTR1]] comdat align 2 { +// CHECK15-NEXT: entry: +// CHECK15-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4 +// CHECK15-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4 +// CHECK15-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4 +// CHECK15-NEXT: ret void +// +// +// CHECK15-LABEL: define {{[^@]+}}@_ZN1SIfEC2Ef +// CHECK15-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]], float noundef [[A:%.*]]) unnamed_addr #[[ATTR1]] comdat align 2 { +// CHECK15-NEXT: entry: +// CHECK15-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4 +// CHECK15-NEXT: [[A_ADDR:%.*]] = alloca float, align 4 +// CHECK15-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4 +// CHECK15-NEXT: store float [[A]], ptr [[A_ADDR]], align 4 +// CHECK15-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4 +// CHECK15-NEXT: [[F:%.*]] = getelementptr inbounds [[STRUCT_S:%.*]], ptr [[THIS1]], i32 0, i32 0 +// CHECK15-NEXT: [[TMP0:%.*]] = load float, ptr [[A_ADDR]], align 4 +// CHECK15-NEXT: store float [[TMP0]], ptr [[F]], align 4 +// CHECK15-NEXT: ret void +// +// +// CHECK15-LABEL: define {{[^@]+}}@_ZN1SIiEC1Ev +// CHECK15-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]]) unnamed_addr #[[ATTR1]] comdat align 2 { +// CHECK15-NEXT: entry: +// CHECK15-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4 +// CHECK15-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4 +// CHECK15-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4 +// CHECK15-NEXT: call void @_ZN1SIiEC2Ev(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]]) +// CHECK15-NEXT: ret void +// +// +// CHECK15-LABEL: define {{[^@]+}}@_ZN1SIiEC1Ei +// CHECK15-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]], i32 noundef [[A:%.*]]) unnamed_addr #[[ATTR1]] comdat align 2 { +// CHECK15-NEXT: entry: +// CHECK15-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4 +// CHECK15-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 +// CHECK15-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4 +// CHECK15-NEXT: store i32 [[A]], ptr [[A_ADDR]], align 4 +// CHECK15-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4 +// CHECK15-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4 +// CHECK15-NEXT: call void @_ZN1SIiEC2Ei(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]], i32 noundef [[TMP0]]) +// CHECK15-NEXT: ret void +// +// +// CHECK15-LABEL: define {{[^@]+}}@_ZN1SIiED1Ev +// CHECK15-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]]) unnamed_addr #[[ATTR1]] comdat align 2 { +// CHECK15-NEXT: entry: +// CHECK15-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4 +// CHECK15-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4 +// CHECK15-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4 +// CHECK15-NEXT: call void @_ZN1SIiED2Ev(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]]) #[[ATTR3]] +// CHECK15-NEXT: ret void +// +// +// CHECK15-LABEL: define {{[^@]+}}@_ZN1SIiEC2Ev +// CHECK15-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]]) unnamed_addr #[[ATTR1]] comdat align 2 { +// CHECK15-NEXT: entry: +// CHECK15-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4 +// CHECK15-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4 +// CHECK15-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4 +// CHECK15-NEXT: [[F:%.*]] = getelementptr inbounds [[STRUCT_S_0:%.*]], ptr [[THIS1]], i32 0, i32 0 +// CHECK15-NEXT: store i32 0, ptr [[F]], align 4 +// CHECK15-NEXT: ret void +// +// +// CHECK15-LABEL: define {{[^@]+}}@_ZN1SIiEC2Ei +// CHECK15-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]], i32 noundef [[A:%.*]]) unnamed_addr #[[ATTR1]] comdat align 2 { +// CHECK15-NEXT: entry: +// CHECK15-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4 +// CHECK15-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 +// CHECK15-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4 +// CHECK15-NEXT: store i32 [[A]], ptr [[A_ADDR]], align 4 +// CHECK15-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4 +// CHECK15-NEXT: [[F:%.*]] = getelementptr inbounds [[STRUCT_S_0:%.*]], ptr [[THIS1]], i32 0, i32 0 +// CHECK15-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4 +// CHECK15-NEXT: store i32 [[TMP0]], ptr [[F]], align 4 +// CHECK15-NEXT: ret void +// +// +// CHECK15-LABEL: define {{[^@]+}}@_ZN1SIiED2Ev +// CHECK15-SAME: (ptr noundef nonnull align 4 dereferenceable(4) [[THIS:%.*]]) unnamed_addr #[[ATTR1]] comdat align 2 { +// CHECK15-NEXT: entry: +// CHECK15-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4 +// CHECK15-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4 +// CHECK15-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4 +// CHECK15-NEXT: ret void +// diff --git a/clang/test/OpenMP/target_data_use_device_addr_codegen.cpp b/clang/test/OpenMP/target_data_use_device_addr_codegen.cpp index 7e70cdf74ad373614a33958df86d6a396d2722ce..ae0653d0585d46524c378fa99176cd4f2ff2c280 100644 --- a/clang/test/OpenMP/target_data_use_device_addr_codegen.cpp +++ b/clang/test/OpenMP/target_data_use_device_addr_codegen.cpp @@ -144,7 +144,13 @@ int main() { // CHECK: [[ARR_IDX6:%.+]] = getelementptr inbounds [4 x i32], ptr [[ARR_ADDR]], i64 0, i64 0 // CHECK: [[A_ADDR2:%.+]] = getelementptr inbounds %struct.S, ptr [[THIS]], i32 0, i32 0 // CHECK: [[P4:%.+]] = mul nuw i64 [[CONV:%.+]], 4 -// CHECK: [[ARR_END:%.+]] = getelementptr i32, ptr [[ARR_IDX6]], i32 1 +// CHECK: [[A_ADDR3:%.+]] = getelementptr inbounds %struct.S, ptr [[THIS]], i32 0, i32 0 +// CHECK: [[L5:%.+]] = load i32, ptr [[A_ADDR3]] +// CHECK: [[L6:%.+]] = sext i32 [[L5]] to i64 +// CHECK: [[LB_ADD_LEN:%lb_add_len]] = add nsw i64 -1, [[L6]] +// CHECK: [[ARR_ADDR9:%.+]] = getelementptr inbounds %struct.S, ptr [[THIS]], i32 0, i32 3 +// CHECK: [[ARR_IDX10:%arrayidx.+]] = getelementptr inbounds [4 x i32], ptr [[ARR_ADDR9]], i64 0, i64 %lb_add_len +// CHECK: [[ARR_END:%.+]] = getelementptr i32, ptr [[ARR_IDX10]], i32 1 // CHECK: [[E:%.+]] = ptrtoint ptr [[ARR_END]] to i64 // CHECK: [[B:%.+]] = ptrtoint ptr [[A_ADDR]] to i64 // CHECK: [[DIFF:%.+]] = sub i64 [[E]], [[B]] diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_private_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_private_codegen.cpp index 6fcbb8def798f32eac2fd58f9750a169e4b7832c..48ead1c3e43ce604128d042cf92f73a44c811f8d 100644 --- a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_private_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_private_codegen.cpp @@ -564,7 +564,7 @@ int main() { // // // CHECK1-LABEL: define {{[^@]+}}@_Z5tmainIiET_v -// CHECK1-SAME: () #[[ATTR6:[0-9]+]] comdat { +// CHECK1-SAME: () #[[ATTR1]] comdat { // CHECK1-NEXT: entry: // CHECK1-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 // CHECK1-NEXT: [[TEST:%.*]] = alloca [[STRUCT_S_0:%.*]], align 4 @@ -1326,7 +1326,7 @@ int main() { // // // CHECK3-LABEL: define {{[^@]+}}@_Z5tmainIiET_v -// CHECK3-SAME: () #[[ATTR6:[0-9]+]] comdat { +// CHECK3-SAME: () #[[ATTR1]] comdat { // CHECK3-NEXT: entry: // CHECK3-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 // CHECK3-NEXT: [[TEST:%.*]] = alloca [[STRUCT_S_0:%.*]], align 4 @@ -1828,14 +1828,14 @@ int main() { // // // CHECK5-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l104 -// CHECK5-SAME: () #[[ATTR5:[0-9]+]] { +// CHECK5-SAME: () #[[ATTR4:[0-9]+]] { // CHECK5-NEXT: entry: // CHECK5-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB3:[0-9]+]], i32 0, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l104.omp_outlined) // CHECK5-NEXT: ret void // // // CHECK5-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l104.omp_outlined -// CHECK5-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]]) #[[ATTR5]] { +// CHECK5-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]]) #[[ATTR4]] { // CHECK5-NEXT: entry: // CHECK5-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 8 // CHECK5-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca ptr, align 8 @@ -1909,7 +1909,7 @@ int main() { // // // CHECK5-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l104.omp_outlined.omp_outlined -// CHECK5-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], i64 noundef [[DOTPREVIOUS_LB_:%.*]], i64 noundef [[DOTPREVIOUS_UB_:%.*]]) #[[ATTR5]] { +// CHECK5-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], i64 noundef [[DOTPREVIOUS_LB_:%.*]], i64 noundef [[DOTPREVIOUS_UB_:%.*]]) #[[ATTR4]] { // CHECK5-NEXT: entry: // CHECK5-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 8 // CHECK5-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca ptr, align 8 @@ -2103,12 +2103,12 @@ int main() { // CHECK7-NEXT: [[DOTOMP_LB:%.*]] = alloca i32, align 4 // CHECK7-NEXT: [[DOTOMP_UB:%.*]] = alloca i32, align 4 // CHECK7-NEXT: [[DOTOMP_IV:%.*]] = alloca i32, align 4 -// CHECK7-NEXT: [[I:%.*]] = alloca i32, align 4 // CHECK7-NEXT: [[T_VAR:%.*]] = alloca i32, align 4 // CHECK7-NEXT: [[VEC:%.*]] = alloca [2 x i32], align 4 // CHECK7-NEXT: [[S_ARR:%.*]] = alloca [2 x %struct.S], align 4 // CHECK7-NEXT: [[VAR:%.*]] = alloca [[STRUCT_S:%.*]], align 4 // CHECK7-NEXT: [[SIVAR:%.*]] = alloca i32, align 4 +// CHECK7-NEXT: [[I:%.*]] = alloca i32, align 4 // CHECK7-NEXT: store i32 0, ptr [[RETVAL]], align 4 // CHECK7-NEXT: store i32 0, ptr [[DOTOMP_LB]], align 4 // CHECK7-NEXT: store i32 1, ptr [[DOTOMP_UB]], align 4 @@ -2177,7 +2177,7 @@ int main() { // // // CHECK7-LABEL: define {{[^@]+}}@_Z5tmainIiET_v -// CHECK7-SAME: () #[[ATTR5:[0-9]+]] comdat { +// CHECK7-SAME: () #[[ATTR1]] comdat { // CHECK7-NEXT: entry: // CHECK7-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 // CHECK7-NEXT: [[TEST:%.*]] = alloca [[STRUCT_S_0:%.*]], align 4 @@ -2190,12 +2190,12 @@ int main() { // CHECK7-NEXT: [[DOTOMP_LB:%.*]] = alloca i32, align 4 // CHECK7-NEXT: [[DOTOMP_UB:%.*]] = alloca i32, align 4 // CHECK7-NEXT: [[DOTOMP_IV:%.*]] = alloca i32, align 4 -// CHECK7-NEXT: [[I:%.*]] = alloca i32, align 4 // CHECK7-NEXT: [[T_VAR2:%.*]] = alloca i32, align 4 // CHECK7-NEXT: [[VEC3:%.*]] = alloca [2 x i32], align 4 // CHECK7-NEXT: [[S_ARR4:%.*]] = alloca [2 x %struct.S.0], align 4 // CHECK7-NEXT: [[VAR5:%.*]] = alloca [[STRUCT_S_0]], align 4 // CHECK7-NEXT: [[_TMP6:%.*]] = alloca ptr, align 8 +// CHECK7-NEXT: [[I:%.*]] = alloca i32, align 4 // CHECK7-NEXT: call void @_ZN1SIiEC1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[TEST]]) // CHECK7-NEXT: store i32 0, ptr [[T_VAR]], align 4 // CHECK7-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[VEC]], ptr align 4 @__const._Z5tmainIiET_v.vec, i64 8, i1 false) @@ -2481,12 +2481,12 @@ int main() { // CHECK9-NEXT: [[DOTOMP_LB:%.*]] = alloca i32, align 4 // CHECK9-NEXT: [[DOTOMP_UB:%.*]] = alloca i32, align 4 // CHECK9-NEXT: [[DOTOMP_IV:%.*]] = alloca i32, align 4 -// CHECK9-NEXT: [[I:%.*]] = alloca i32, align 4 // CHECK9-NEXT: [[T_VAR:%.*]] = alloca i32, align 4 // CHECK9-NEXT: [[VEC:%.*]] = alloca [2 x i32], align 4 // CHECK9-NEXT: [[S_ARR:%.*]] = alloca [2 x %struct.S], align 4 // CHECK9-NEXT: [[VAR:%.*]] = alloca [[STRUCT_S:%.*]], align 4 // CHECK9-NEXT: [[SIVAR:%.*]] = alloca i32, align 4 +// CHECK9-NEXT: [[I:%.*]] = alloca i32, align 4 // CHECK9-NEXT: store i32 0, ptr [[RETVAL]], align 4 // CHECK9-NEXT: store i32 0, ptr [[DOTOMP_LB]], align 4 // CHECK9-NEXT: store i32 1, ptr [[DOTOMP_UB]], align 4 @@ -2553,7 +2553,7 @@ int main() { // // // CHECK9-LABEL: define {{[^@]+}}@_Z5tmainIiET_v -// CHECK9-SAME: () #[[ATTR5:[0-9]+]] comdat { +// CHECK9-SAME: () #[[ATTR1]] comdat { // CHECK9-NEXT: entry: // CHECK9-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 // CHECK9-NEXT: [[TEST:%.*]] = alloca [[STRUCT_S_0:%.*]], align 4 @@ -2566,12 +2566,12 @@ int main() { // CHECK9-NEXT: [[DOTOMP_LB:%.*]] = alloca i32, align 4 // CHECK9-NEXT: [[DOTOMP_UB:%.*]] = alloca i32, align 4 // CHECK9-NEXT: [[DOTOMP_IV:%.*]] = alloca i32, align 4 -// CHECK9-NEXT: [[I:%.*]] = alloca i32, align 4 // CHECK9-NEXT: [[T_VAR2:%.*]] = alloca i32, align 4 // CHECK9-NEXT: [[VEC3:%.*]] = alloca [2 x i32], align 4 // CHECK9-NEXT: [[S_ARR4:%.*]] = alloca [2 x %struct.S.0], align 4 // CHECK9-NEXT: [[VAR5:%.*]] = alloca [[STRUCT_S_0]], align 4 // CHECK9-NEXT: [[_TMP6:%.*]] = alloca ptr, align 4 +// CHECK9-NEXT: [[I:%.*]] = alloca i32, align 4 // CHECK9-NEXT: call void @_ZN1SIiEC1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[TEST]]) // CHECK9-NEXT: store i32 0, ptr [[T_VAR]], align 4 // CHECK9-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[VEC]], ptr align 4 @__const._Z5tmainIiET_v.vec, i32 8, i1 false) diff --git a/clang/test/OpenMP/target_teams_distribute_simd_private_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_simd_private_codegen.cpp index d754a33dc8d0bc8175bfbb4eb8744594bec8fada..bf38e4bace5aa6906e45d7c7ad8f437136103a97 100644 --- a/clang/test/OpenMP/target_teams_distribute_simd_private_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_simd_private_codegen.cpp @@ -395,7 +395,7 @@ int main() { // // // CHECK1-LABEL: define {{[^@]+}}@_Z5tmainIiET_v -// CHECK1-SAME: () #[[ATTR6:[0-9]+]] comdat { +// CHECK1-SAME: () #[[ATTR1]] comdat { // CHECK1-NEXT: entry: // CHECK1-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 // CHECK1-NEXT: [[TEST:%.*]] = alloca [[STRUCT_S_0:%.*]], align 4 @@ -942,7 +942,7 @@ int main() { // // // CHECK3-LABEL: define {{[^@]+}}@_Z5tmainIiET_v -// CHECK3-SAME: () #[[ATTR6:[0-9]+]] comdat { +// CHECK3-SAME: () #[[ATTR1]] comdat { // CHECK3-NEXT: entry: // CHECK3-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 // CHECK3-NEXT: [[TEST:%.*]] = alloca [[STRUCT_S_0:%.*]], align 4 @@ -1295,12 +1295,12 @@ int main() { // CHECK5-NEXT: [[DOTOMP_LB:%.*]] = alloca i32, align 4 // CHECK5-NEXT: [[DOTOMP_UB:%.*]] = alloca i32, align 4 // CHECK5-NEXT: [[DOTOMP_IV:%.*]] = alloca i32, align 4 -// CHECK5-NEXT: [[I:%.*]] = alloca i32, align 4 // CHECK5-NEXT: [[T_VAR:%.*]] = alloca i32, align 4 // CHECK5-NEXT: [[VEC:%.*]] = alloca [2 x i32], align 4 // CHECK5-NEXT: [[S_ARR:%.*]] = alloca [2 x %struct.S], align 4 // CHECK5-NEXT: [[VAR:%.*]] = alloca [[STRUCT_S:%.*]], align 4 // CHECK5-NEXT: [[SIVAR:%.*]] = alloca i32, align 4 +// CHECK5-NEXT: [[I:%.*]] = alloca i32, align 4 // CHECK5-NEXT: store i32 0, ptr [[RETVAL]], align 4 // CHECK5-NEXT: store i32 0, ptr [[DOTOMP_LB]], align 4 // CHECK5-NEXT: store i32 1, ptr [[DOTOMP_UB]], align 4 @@ -1369,7 +1369,7 @@ int main() { // // // CHECK5-LABEL: define {{[^@]+}}@_Z5tmainIiET_v -// CHECK5-SAME: () #[[ATTR5:[0-9]+]] comdat { +// CHECK5-SAME: () #[[ATTR1]] comdat { // CHECK5-NEXT: entry: // CHECK5-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 // CHECK5-NEXT: [[TEST:%.*]] = alloca [[STRUCT_S_0:%.*]], align 4 @@ -1382,12 +1382,12 @@ int main() { // CHECK5-NEXT: [[DOTOMP_LB:%.*]] = alloca i32, align 4 // CHECK5-NEXT: [[DOTOMP_UB:%.*]] = alloca i32, align 4 // CHECK5-NEXT: [[DOTOMP_IV:%.*]] = alloca i32, align 4 -// CHECK5-NEXT: [[I:%.*]] = alloca i32, align 4 // CHECK5-NEXT: [[T_VAR2:%.*]] = alloca i32, align 4 // CHECK5-NEXT: [[VEC3:%.*]] = alloca [2 x i32], align 4 // CHECK5-NEXT: [[S_ARR4:%.*]] = alloca [2 x %struct.S.0], align 4 // CHECK5-NEXT: [[VAR5:%.*]] = alloca [[STRUCT_S_0]], align 4 // CHECK5-NEXT: [[_TMP6:%.*]] = alloca ptr, align 8 +// CHECK5-NEXT: [[I:%.*]] = alloca i32, align 4 // CHECK5-NEXT: call void @_ZN1SIiEC1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[TEST]]) // CHECK5-NEXT: store i32 0, ptr [[T_VAR]], align 4 // CHECK5-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[VEC]], ptr align 4 @__const._Z5tmainIiET_v.vec, i64 8, i1 false) @@ -1673,12 +1673,12 @@ int main() { // CHECK7-NEXT: [[DOTOMP_LB:%.*]] = alloca i32, align 4 // CHECK7-NEXT: [[DOTOMP_UB:%.*]] = alloca i32, align 4 // CHECK7-NEXT: [[DOTOMP_IV:%.*]] = alloca i32, align 4 -// CHECK7-NEXT: [[I:%.*]] = alloca i32, align 4 // CHECK7-NEXT: [[T_VAR:%.*]] = alloca i32, align 4 // CHECK7-NEXT: [[VEC:%.*]] = alloca [2 x i32], align 4 // CHECK7-NEXT: [[S_ARR:%.*]] = alloca [2 x %struct.S], align 4 // CHECK7-NEXT: [[VAR:%.*]] = alloca [[STRUCT_S:%.*]], align 4 // CHECK7-NEXT: [[SIVAR:%.*]] = alloca i32, align 4 +// CHECK7-NEXT: [[I:%.*]] = alloca i32, align 4 // CHECK7-NEXT: store i32 0, ptr [[RETVAL]], align 4 // CHECK7-NEXT: store i32 0, ptr [[DOTOMP_LB]], align 4 // CHECK7-NEXT: store i32 1, ptr [[DOTOMP_UB]], align 4 @@ -1745,7 +1745,7 @@ int main() { // // // CHECK7-LABEL: define {{[^@]+}}@_Z5tmainIiET_v -// CHECK7-SAME: () #[[ATTR5:[0-9]+]] comdat { +// CHECK7-SAME: () #[[ATTR1]] comdat { // CHECK7-NEXT: entry: // CHECK7-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 // CHECK7-NEXT: [[TEST:%.*]] = alloca [[STRUCT_S_0:%.*]], align 4 @@ -1758,12 +1758,12 @@ int main() { // CHECK7-NEXT: [[DOTOMP_LB:%.*]] = alloca i32, align 4 // CHECK7-NEXT: [[DOTOMP_UB:%.*]] = alloca i32, align 4 // CHECK7-NEXT: [[DOTOMP_IV:%.*]] = alloca i32, align 4 -// CHECK7-NEXT: [[I:%.*]] = alloca i32, align 4 // CHECK7-NEXT: [[T_VAR2:%.*]] = alloca i32, align 4 // CHECK7-NEXT: [[VEC3:%.*]] = alloca [2 x i32], align 4 // CHECK7-NEXT: [[S_ARR4:%.*]] = alloca [2 x %struct.S.0], align 4 // CHECK7-NEXT: [[VAR5:%.*]] = alloca [[STRUCT_S_0]], align 4 // CHECK7-NEXT: [[_TMP6:%.*]] = alloca ptr, align 4 +// CHECK7-NEXT: [[I:%.*]] = alloca i32, align 4 // CHECK7-NEXT: call void @_ZN1SIiEC1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[TEST]]) // CHECK7-NEXT: store i32 0, ptr [[T_VAR]], align 4 // CHECK7-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[VEC]], ptr align 4 @__const._Z5tmainIiET_v.vec, i32 8, i1 false) @@ -2089,14 +2089,14 @@ int main() { // // // CHECK9-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l74 -// CHECK9-SAME: () #[[ATTR5:[0-9]+]] { +// CHECK9-SAME: () #[[ATTR4:[0-9]+]] { // CHECK9-NEXT: entry: // CHECK9-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB2:[0-9]+]], i32 0, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l74.omp_outlined) // CHECK9-NEXT: ret void // // // CHECK9-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l74.omp_outlined -// CHECK9-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]]) #[[ATTR5]] { +// CHECK9-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]]) #[[ATTR4]] { // CHECK9-NEXT: entry: // CHECK9-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 8 // CHECK9-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca ptr, align 8 diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_simd_private_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_simd_private_codegen.cpp index 14c7f4f2365b5b79b0671d273e2bc4f58fcb33c5..8ad19077ed73c1bdfa7015fc2d86c979c02a991c 100644 --- a/clang/test/OpenMP/teams_distribute_parallel_for_simd_private_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_parallel_for_simd_private_codegen.cpp @@ -309,7 +309,7 @@ int main() { // // // CHECK1-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l98.omp_outlined -// CHECK1-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]]) #[[ATTR5:[0-9]+]] { +// CHECK1-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]]) #[[ATTR4]] { // CHECK1-NEXT: entry: // CHECK1-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 8 // CHECK1-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca ptr, align 8 @@ -407,7 +407,7 @@ int main() { // // // CHECK1-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l98.omp_outlined.omp_outlined -// CHECK1-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], i64 noundef [[DOTPREVIOUS_LB_:%.*]], i64 noundef [[DOTPREVIOUS_UB_:%.*]]) #[[ATTR5]] { +// CHECK1-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], i64 noundef [[DOTPREVIOUS_LB_:%.*]], i64 noundef [[DOTPREVIOUS_UB_:%.*]]) #[[ATTR4]] { // CHECK1-NEXT: entry: // CHECK1-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 8 // CHECK1-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca ptr, align 8 @@ -528,7 +528,7 @@ int main() { // // // CHECK1-LABEL: define {{[^@]+}}@_Z5tmainIiET_v -// CHECK1-SAME: () #[[ATTR7:[0-9]+]] comdat { +// CHECK1-SAME: () #[[ATTR1]] comdat { // CHECK1-NEXT: entry: // CHECK1-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 // CHECK1-NEXT: [[TEST:%.*]] = alloca [[STRUCT_S_0:%.*]], align 4 @@ -628,7 +628,7 @@ int main() { // // // CHECK1-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z5tmainIiET_v_l56.omp_outlined -// CHECK1-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]]) #[[ATTR5]] { +// CHECK1-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]]) #[[ATTR4]] { // CHECK1-NEXT: entry: // CHECK1-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 8 // CHECK1-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca ptr, align 8 @@ -729,7 +729,7 @@ int main() { // // // CHECK1-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z5tmainIiET_v_l56.omp_outlined.omp_outlined -// CHECK1-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], i64 noundef [[DOTPREVIOUS_LB_:%.*]], i64 noundef [[DOTPREVIOUS_UB_:%.*]]) #[[ATTR5]] { +// CHECK1-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], i64 noundef [[DOTPREVIOUS_LB_:%.*]], i64 noundef [[DOTPREVIOUS_UB_:%.*]]) #[[ATTR4]] { // CHECK1-NEXT: entry: // CHECK1-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 8 // CHECK1-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca ptr, align 8 @@ -1077,7 +1077,7 @@ int main() { // // // CHECK3-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l98.omp_outlined -// CHECK3-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]]) #[[ATTR5:[0-9]+]] { +// CHECK3-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]]) #[[ATTR4]] { // CHECK3-NEXT: entry: // CHECK3-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 4 // CHECK3-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca ptr, align 4 @@ -1173,7 +1173,7 @@ int main() { // // // CHECK3-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l98.omp_outlined.omp_outlined -// CHECK3-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], i32 noundef [[DOTPREVIOUS_LB_:%.*]], i32 noundef [[DOTPREVIOUS_UB_:%.*]]) #[[ATTR5]] { +// CHECK3-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], i32 noundef [[DOTPREVIOUS_LB_:%.*]], i32 noundef [[DOTPREVIOUS_UB_:%.*]]) #[[ATTR4]] { // CHECK3-NEXT: entry: // CHECK3-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 4 // CHECK3-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca ptr, align 4 @@ -1290,7 +1290,7 @@ int main() { // // // CHECK3-LABEL: define {{[^@]+}}@_Z5tmainIiET_v -// CHECK3-SAME: () #[[ATTR7:[0-9]+]] comdat { +// CHECK3-SAME: () #[[ATTR1]] comdat { // CHECK3-NEXT: entry: // CHECK3-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 // CHECK3-NEXT: [[TEST:%.*]] = alloca [[STRUCT_S_0:%.*]], align 4 @@ -1390,7 +1390,7 @@ int main() { // // // CHECK3-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z5tmainIiET_v_l56.omp_outlined -// CHECK3-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]]) #[[ATTR5]] { +// CHECK3-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]]) #[[ATTR4]] { // CHECK3-NEXT: entry: // CHECK3-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 4 // CHECK3-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca ptr, align 4 @@ -1489,7 +1489,7 @@ int main() { // // // CHECK3-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z5tmainIiET_v_l56.omp_outlined.omp_outlined -// CHECK3-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], i32 noundef [[DOTPREVIOUS_LB_:%.*]], i32 noundef [[DOTPREVIOUS_UB_:%.*]]) #[[ATTR5]] { +// CHECK3-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], i32 noundef [[DOTPREVIOUS_LB_:%.*]], i32 noundef [[DOTPREVIOUS_UB_:%.*]]) #[[ATTR4]] { // CHECK3-NEXT: entry: // CHECK3-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 4 // CHECK3-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca ptr, align 4 @@ -1750,12 +1750,12 @@ int main() { // CHECK5-NEXT: [[DOTOMP_LB:%.*]] = alloca i32, align 4 // CHECK5-NEXT: [[DOTOMP_UB:%.*]] = alloca i32, align 4 // CHECK5-NEXT: [[DOTOMP_IV:%.*]] = alloca i32, align 4 -// CHECK5-NEXT: [[I:%.*]] = alloca i32, align 4 // CHECK5-NEXT: [[T_VAR:%.*]] = alloca i32, align 4 // CHECK5-NEXT: [[VEC:%.*]] = alloca [2 x i32], align 4 // CHECK5-NEXT: [[S_ARR:%.*]] = alloca [2 x %struct.S], align 4 // CHECK5-NEXT: [[VAR:%.*]] = alloca [[STRUCT_S:%.*]], align 4 // CHECK5-NEXT: [[SIVAR:%.*]] = alloca i32, align 4 +// CHECK5-NEXT: [[I:%.*]] = alloca i32, align 4 // CHECK5-NEXT: store i32 0, ptr [[RETVAL]], align 4 // CHECK5-NEXT: store i32 0, ptr [[DOTOMP_LB]], align 4 // CHECK5-NEXT: store i32 1, ptr [[DOTOMP_UB]], align 4 @@ -1824,7 +1824,7 @@ int main() { // // // CHECK5-LABEL: define {{[^@]+}}@_Z5tmainIiET_v -// CHECK5-SAME: () #[[ATTR5:[0-9]+]] comdat { +// CHECK5-SAME: () #[[ATTR1]] comdat { // CHECK5-NEXT: entry: // CHECK5-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 // CHECK5-NEXT: [[TEST:%.*]] = alloca [[STRUCT_S_0:%.*]], align 4 @@ -1837,12 +1837,12 @@ int main() { // CHECK5-NEXT: [[DOTOMP_LB:%.*]] = alloca i32, align 4 // CHECK5-NEXT: [[DOTOMP_UB:%.*]] = alloca i32, align 4 // CHECK5-NEXT: [[DOTOMP_IV:%.*]] = alloca i32, align 4 -// CHECK5-NEXT: [[I:%.*]] = alloca i32, align 4 // CHECK5-NEXT: [[T_VAR2:%.*]] = alloca i32, align 4 // CHECK5-NEXT: [[VEC3:%.*]] = alloca [2 x i32], align 4 // CHECK5-NEXT: [[S_ARR4:%.*]] = alloca [2 x %struct.S.0], align 4 // CHECK5-NEXT: [[VAR5:%.*]] = alloca [[STRUCT_S_0]], align 4 // CHECK5-NEXT: [[_TMP6:%.*]] = alloca ptr, align 8 +// CHECK5-NEXT: [[I:%.*]] = alloca i32, align 4 // CHECK5-NEXT: call void @_ZN1SIiEC1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[TEST]]) // CHECK5-NEXT: store i32 0, ptr [[T_VAR]], align 4 // CHECK5-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[VEC]], ptr align 4 @__const._Z5tmainIiET_v.vec, i64 8, i1 false) @@ -2128,12 +2128,12 @@ int main() { // CHECK7-NEXT: [[DOTOMP_LB:%.*]] = alloca i32, align 4 // CHECK7-NEXT: [[DOTOMP_UB:%.*]] = alloca i32, align 4 // CHECK7-NEXT: [[DOTOMP_IV:%.*]] = alloca i32, align 4 -// CHECK7-NEXT: [[I:%.*]] = alloca i32, align 4 // CHECK7-NEXT: [[T_VAR:%.*]] = alloca i32, align 4 // CHECK7-NEXT: [[VEC:%.*]] = alloca [2 x i32], align 4 // CHECK7-NEXT: [[S_ARR:%.*]] = alloca [2 x %struct.S], align 4 // CHECK7-NEXT: [[VAR:%.*]] = alloca [[STRUCT_S:%.*]], align 4 // CHECK7-NEXT: [[SIVAR:%.*]] = alloca i32, align 4 +// CHECK7-NEXT: [[I:%.*]] = alloca i32, align 4 // CHECK7-NEXT: store i32 0, ptr [[RETVAL]], align 4 // CHECK7-NEXT: store i32 0, ptr [[DOTOMP_LB]], align 4 // CHECK7-NEXT: store i32 1, ptr [[DOTOMP_UB]], align 4 @@ -2200,7 +2200,7 @@ int main() { // // // CHECK7-LABEL: define {{[^@]+}}@_Z5tmainIiET_v -// CHECK7-SAME: () #[[ATTR5:[0-9]+]] comdat { +// CHECK7-SAME: () #[[ATTR1]] comdat { // CHECK7-NEXT: entry: // CHECK7-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 // CHECK7-NEXT: [[TEST:%.*]] = alloca [[STRUCT_S_0:%.*]], align 4 @@ -2213,12 +2213,12 @@ int main() { // CHECK7-NEXT: [[DOTOMP_LB:%.*]] = alloca i32, align 4 // CHECK7-NEXT: [[DOTOMP_UB:%.*]] = alloca i32, align 4 // CHECK7-NEXT: [[DOTOMP_IV:%.*]] = alloca i32, align 4 -// CHECK7-NEXT: [[I:%.*]] = alloca i32, align 4 // CHECK7-NEXT: [[T_VAR2:%.*]] = alloca i32, align 4 // CHECK7-NEXT: [[VEC3:%.*]] = alloca [2 x i32], align 4 // CHECK7-NEXT: [[S_ARR4:%.*]] = alloca [2 x %struct.S.0], align 4 // CHECK7-NEXT: [[VAR5:%.*]] = alloca [[STRUCT_S_0]], align 4 // CHECK7-NEXT: [[_TMP6:%.*]] = alloca ptr, align 4 +// CHECK7-NEXT: [[I:%.*]] = alloca i32, align 4 // CHECK7-NEXT: call void @_ZN1SIiEC1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[TEST]]) // CHECK7-NEXT: store i32 0, ptr [[T_VAR]], align 4 // CHECK7-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[VEC]], ptr align 4 @__const._Z5tmainIiET_v.vec, i32 8, i1 false) @@ -2544,7 +2544,7 @@ int main() { // // // CHECK9-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l75 -// CHECK9-SAME: (i64 noundef [[G1:%.*]]) #[[ATTR5:[0-9]+]] { +// CHECK9-SAME: (i64 noundef [[G1:%.*]]) #[[ATTR4:[0-9]+]] { // CHECK9-NEXT: entry: // CHECK9-NEXT: [[G1_ADDR:%.*]] = alloca i64, align 8 // CHECK9-NEXT: [[TMP:%.*]] = alloca ptr, align 8 @@ -2555,7 +2555,7 @@ int main() { // // // CHECK9-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l75.omp_outlined -// CHECK9-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]]) #[[ATTR6:[0-9]+]] { +// CHECK9-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]]) #[[ATTR4]] { // CHECK9-NEXT: entry: // CHECK9-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 8 // CHECK9-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca ptr, align 8 @@ -2629,7 +2629,7 @@ int main() { // // // CHECK9-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l75.omp_outlined.omp_outlined -// CHECK9-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], i64 noundef [[DOTPREVIOUS_LB_:%.*]], i64 noundef [[DOTPREVIOUS_UB_:%.*]]) #[[ATTR6]] { +// CHECK9-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], i64 noundef [[DOTPREVIOUS_LB_:%.*]], i64 noundef [[DOTPREVIOUS_UB_:%.*]]) #[[ATTR4]] { // CHECK9-NEXT: entry: // CHECK9-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 8 // CHECK9-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca ptr, align 8 diff --git a/clang/test/OpenMP/teams_distribute_simd_private_codegen.cpp b/clang/test/OpenMP/teams_distribute_simd_private_codegen.cpp index bfe5d360ed30acf15cd2fec691223e9eb962fcd2..1e629933d73989357dc7e65e2fda21d724d52d92 100644 --- a/clang/test/OpenMP/teams_distribute_simd_private_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_simd_private_codegen.cpp @@ -288,7 +288,7 @@ int main() { // // // CHECK1-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l94.omp_outlined -// CHECK1-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]]) #[[ATTR5:[0-9]+]] { +// CHECK1-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]]) #[[ATTR4]] { // CHECK1-NEXT: entry: // CHECK1-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 8 // CHECK1-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca ptr, align 8 @@ -399,7 +399,7 @@ int main() { // // // CHECK1-LABEL: define {{[^@]+}}@_Z5tmainIiET_v -// CHECK1-SAME: () #[[ATTR7:[0-9]+]] comdat { +// CHECK1-SAME: () #[[ATTR1]] comdat { // CHECK1-NEXT: entry: // CHECK1-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 // CHECK1-NEXT: [[TEST:%.*]] = alloca [[STRUCT_S_0:%.*]], align 4 @@ -499,7 +499,7 @@ int main() { // // // CHECK1-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z5tmainIiET_v_l56.omp_outlined -// CHECK1-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]]) #[[ATTR5]] { +// CHECK1-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]]) #[[ATTR4]] { // CHECK1-NEXT: entry: // CHECK1-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 8 // CHECK1-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca ptr, align 8 @@ -837,7 +837,7 @@ int main() { // // // CHECK3-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l94.omp_outlined -// CHECK3-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]]) #[[ATTR5:[0-9]+]] { +// CHECK3-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]]) #[[ATTR4]] { // CHECK3-NEXT: entry: // CHECK3-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 4 // CHECK3-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca ptr, align 4 @@ -946,7 +946,7 @@ int main() { // // // CHECK3-LABEL: define {{[^@]+}}@_Z5tmainIiET_v -// CHECK3-SAME: () #[[ATTR7:[0-9]+]] comdat { +// CHECK3-SAME: () #[[ATTR1]] comdat { // CHECK3-NEXT: entry: // CHECK3-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 // CHECK3-NEXT: [[TEST:%.*]] = alloca [[STRUCT_S_0:%.*]], align 4 @@ -1046,7 +1046,7 @@ int main() { // // // CHECK3-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z5tmainIiET_v_l56.omp_outlined -// CHECK3-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]]) #[[ATTR5]] { +// CHECK3-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]]) #[[ATTR4]] { // CHECK3-NEXT: entry: // CHECK3-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 4 // CHECK3-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca ptr, align 4 @@ -1299,12 +1299,12 @@ int main() { // CHECK5-NEXT: [[DOTOMP_LB:%.*]] = alloca i32, align 4 // CHECK5-NEXT: [[DOTOMP_UB:%.*]] = alloca i32, align 4 // CHECK5-NEXT: [[DOTOMP_IV:%.*]] = alloca i32, align 4 -// CHECK5-NEXT: [[I:%.*]] = alloca i32, align 4 // CHECK5-NEXT: [[T_VAR:%.*]] = alloca i32, align 4 // CHECK5-NEXT: [[VEC:%.*]] = alloca [2 x i32], align 4 // CHECK5-NEXT: [[S_ARR:%.*]] = alloca [2 x %struct.S], align 4 // CHECK5-NEXT: [[VAR:%.*]] = alloca [[STRUCT_S:%.*]], align 4 // CHECK5-NEXT: [[SIVAR:%.*]] = alloca i32, align 4 +// CHECK5-NEXT: [[I:%.*]] = alloca i32, align 4 // CHECK5-NEXT: store i32 0, ptr [[RETVAL]], align 4 // CHECK5-NEXT: store i32 0, ptr [[DOTOMP_LB]], align 4 // CHECK5-NEXT: store i32 1, ptr [[DOTOMP_UB]], align 4 @@ -1373,7 +1373,7 @@ int main() { // // // CHECK5-LABEL: define {{[^@]+}}@_Z5tmainIiET_v -// CHECK5-SAME: () #[[ATTR5:[0-9]+]] comdat { +// CHECK5-SAME: () #[[ATTR1]] comdat { // CHECK5-NEXT: entry: // CHECK5-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 // CHECK5-NEXT: [[TEST:%.*]] = alloca [[STRUCT_S_0:%.*]], align 4 @@ -1386,12 +1386,12 @@ int main() { // CHECK5-NEXT: [[DOTOMP_LB:%.*]] = alloca i32, align 4 // CHECK5-NEXT: [[DOTOMP_UB:%.*]] = alloca i32, align 4 // CHECK5-NEXT: [[DOTOMP_IV:%.*]] = alloca i32, align 4 -// CHECK5-NEXT: [[I:%.*]] = alloca i32, align 4 // CHECK5-NEXT: [[T_VAR2:%.*]] = alloca i32, align 4 // CHECK5-NEXT: [[VEC3:%.*]] = alloca [2 x i32], align 4 // CHECK5-NEXT: [[S_ARR4:%.*]] = alloca [2 x %struct.S.0], align 4 // CHECK5-NEXT: [[VAR5:%.*]] = alloca [[STRUCT_S_0]], align 4 // CHECK5-NEXT: [[_TMP6:%.*]] = alloca ptr, align 8 +// CHECK5-NEXT: [[I:%.*]] = alloca i32, align 4 // CHECK5-NEXT: call void @_ZN1SIiEC1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[TEST]]) // CHECK5-NEXT: store i32 0, ptr [[T_VAR]], align 4 // CHECK5-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[VEC]], ptr align 4 @__const._Z5tmainIiET_v.vec, i64 8, i1 false) @@ -1677,12 +1677,12 @@ int main() { // CHECK7-NEXT: [[DOTOMP_LB:%.*]] = alloca i32, align 4 // CHECK7-NEXT: [[DOTOMP_UB:%.*]] = alloca i32, align 4 // CHECK7-NEXT: [[DOTOMP_IV:%.*]] = alloca i32, align 4 -// CHECK7-NEXT: [[I:%.*]] = alloca i32, align 4 // CHECK7-NEXT: [[T_VAR:%.*]] = alloca i32, align 4 // CHECK7-NEXT: [[VEC:%.*]] = alloca [2 x i32], align 4 // CHECK7-NEXT: [[S_ARR:%.*]] = alloca [2 x %struct.S], align 4 // CHECK7-NEXT: [[VAR:%.*]] = alloca [[STRUCT_S:%.*]], align 4 // CHECK7-NEXT: [[SIVAR:%.*]] = alloca i32, align 4 +// CHECK7-NEXT: [[I:%.*]] = alloca i32, align 4 // CHECK7-NEXT: store i32 0, ptr [[RETVAL]], align 4 // CHECK7-NEXT: store i32 0, ptr [[DOTOMP_LB]], align 4 // CHECK7-NEXT: store i32 1, ptr [[DOTOMP_UB]], align 4 @@ -1749,7 +1749,7 @@ int main() { // // // CHECK7-LABEL: define {{[^@]+}}@_Z5tmainIiET_v -// CHECK7-SAME: () #[[ATTR5:[0-9]+]] comdat { +// CHECK7-SAME: () #[[ATTR1]] comdat { // CHECK7-NEXT: entry: // CHECK7-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 // CHECK7-NEXT: [[TEST:%.*]] = alloca [[STRUCT_S_0:%.*]], align 4 @@ -1762,12 +1762,12 @@ int main() { // CHECK7-NEXT: [[DOTOMP_LB:%.*]] = alloca i32, align 4 // CHECK7-NEXT: [[DOTOMP_UB:%.*]] = alloca i32, align 4 // CHECK7-NEXT: [[DOTOMP_IV:%.*]] = alloca i32, align 4 -// CHECK7-NEXT: [[I:%.*]] = alloca i32, align 4 // CHECK7-NEXT: [[T_VAR2:%.*]] = alloca i32, align 4 // CHECK7-NEXT: [[VEC3:%.*]] = alloca [2 x i32], align 4 // CHECK7-NEXT: [[S_ARR4:%.*]] = alloca [2 x %struct.S.0], align 4 // CHECK7-NEXT: [[VAR5:%.*]] = alloca [[STRUCT_S_0]], align 4 // CHECK7-NEXT: [[_TMP6:%.*]] = alloca ptr, align 4 +// CHECK7-NEXT: [[I:%.*]] = alloca i32, align 4 // CHECK7-NEXT: call void @_ZN1SIiEC1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[TEST]]) // CHECK7-NEXT: store i32 0, ptr [[T_VAR]], align 4 // CHECK7-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[VEC]], ptr align 4 @__const._Z5tmainIiET_v.vec, i32 8, i1 false) @@ -2093,7 +2093,7 @@ int main() { // // // CHECK9-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l75 -// CHECK9-SAME: (i64 noundef [[G1:%.*]]) #[[ATTR5:[0-9]+]] { +// CHECK9-SAME: (i64 noundef [[G1:%.*]]) #[[ATTR4:[0-9]+]] { // CHECK9-NEXT: entry: // CHECK9-NEXT: [[G1_ADDR:%.*]] = alloca i64, align 8 // CHECK9-NEXT: [[TMP:%.*]] = alloca ptr, align 8 @@ -2104,7 +2104,7 @@ int main() { // // // CHECK9-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l75.omp_outlined -// CHECK9-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]]) #[[ATTR6:[0-9]+]] { +// CHECK9-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]]) #[[ATTR4]] { // CHECK9-NEXT: entry: // CHECK9-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 8 // CHECK9-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca ptr, align 8 diff --git a/clang/test/Parser/cxx2b-lambdas.cpp b/clang/test/Parser/cxx2b-lambdas.cpp index bb9ed226afffafec150f74747478b7fcc473b888..ad975a17b6e476db538d234edb9dcc95f885a8f1 100644 --- a/clang/test/Parser/cxx2b-lambdas.cpp +++ b/clang/test/Parser/cxx2b-lambdas.cpp @@ -66,3 +66,15 @@ void static_captures() { } }; } + +constexpr auto static_capture_constexpr() { + char n = 'n'; + return [n] static { return n; }(); // expected-error {{a static lambda cannot have any captures}} +} +static_assert(static_capture_constexpr()); // expected-error {{static assertion expression is not an integral constant expression}} + +constexpr auto capture_constexpr() { + char n = 'n'; + return [n] { return n; }(); +} +static_assert(capture_constexpr()); diff --git a/clang/test/ParserOpenACC/parse-cache-construct.c b/clang/test/ParserOpenACC/parse-cache-construct.c new file mode 100644 index 0000000000000000000000000000000000000000..10976627ca95ce669b8f03b2a237d39d69f0e6ba --- /dev/null +++ b/clang/test/ParserOpenACC/parse-cache-construct.c @@ -0,0 +1,166 @@ +// RUN: %clang_cc1 %s -verify -fopenacc + +char *getArrayPtr(); +void func() { + char Array[10]; + char *ArrayPtr = getArrayPtr(); + int *readonly; + + for (int i = 0; i < 10; ++i) { + // expected-error@+2{{expected '('}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc cache + } + + for (int i = 0; i < 10; ++i) { + // expected-error@+3{{expected '('}} + // expected-warning@+2{{OpenACC clause parsing not yet implemented}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc cache clause list + } + + for (int i = 0; i < 10; ++i) { + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc cache() + } + + for (int i = 0; i < 10; ++i) { + // expected-warning@+2{{OpenACC clause parsing not yet implemented}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc cache() clause-list + } + + for (int i = 0; i < 10; ++i) { + // expected-error@+3{{expected ')'}} + // expected-note@+2{{to match this '('}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc cache( + } + + for (int i = 0; i < 10; ++i) { + // expected-error@+4{{use of undeclared identifier 'invalid'}} + // expected-error@+3{{expected ')'}} + // expected-note@+2{{to match this '('}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc cache(invalid + } + + for (int i = 0; i < 10; ++i) { + // expected-error@+4{{expected '['}} + // expected-error@+3{{expected ')'}} + // expected-note@+2{{to match this '('}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc cache(ArrayPtr + } + + for (int i = 0; i < 10; ++i) { + // expected-error@+2{{use of undeclared identifier 'invalid'}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc cache(invalid) + } + + for (int i = 0; i < 10; ++i) { + // expected-error@+2{{expected '['}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc cache(ArrayPtr) + } + + for (int i = 0; i < 10; ++i) { + // expected-error@+4{{expected expression}} + // expected-error@+3{{expected ')'}} + // expected-note@+2{{to match this '('}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc cache(ArrayPtr[ + } + + for (int i = 0; i < 10; ++i) { + // expected-error@+2{{expected expression}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc cache(ArrayPtr[, 5) + } + + for (int i = 0; i < 10; ++i) { + // expected-error@+2{{expected expression}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc cache(Array[) + } + + for (int i = 0; i < 10; ++i) { + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc cache(Array[*readonly]) + } + + for (int i = 0; i < 10; ++i) { + // expected-error@+4{{expected expression}} + // expected-error@+3{{expected ')'}} + // expected-note@+2{{to match this '('}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc cache(Array[*readonly: + } + + for (int i = 0; i < 10; ++i) { + // expected-error@+2{{expected '['}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc cache(readonly) + } + + for (int i = 0; i < 10; ++i) { + // expected-error@+2{{expected '['}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc cache(readonly:ArrayPtr) + } + + for (int i = 0; i < 10; ++i) { + // expected-error@+2{{expected expression}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc cache(readonly:ArrayPtr[5:]) + } + + for (int i = 0; i < 10; ++i) { + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc cache(readonly:ArrayPtr[5:*readonly]) + } + + for (int i = 0; i < 10; ++i) { + // expected-error@+2{{expected '['}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc cache(readonly:ArrayPtr[5:*readonly], Array) + } + + for (int i = 0; i < 10; ++i) { + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc cache(readonly:ArrayPtr[5:*readonly], Array[*readonly:3]) + } + + for (int i = 0; i < 10; ++i) { + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc cache(readonly:ArrayPtr[5 + i:*readonly], Array[*readonly + i:3]) + } + + for (int i = 0; i < 10; ++i) { + // expected-error@+4{{expected identifier}} + // expected-error@+3{{expected ')'}} + // expected-note@+2{{to match this '('}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc cache(readonly:ArrayPtr[5:*readonly], + } + + for (int i = 0; i < 10; ++i) { + // expected-error@+2{{expected identifier}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc cache(readonly:ArrayPtr[5:*readonly],) + } + + for (int i = 0; i < 10; ++i) { + // expected-warning@+2{{left operand of comma operator has no effect}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc cache(readonly:ArrayPtr[5,6:*readonly]) + } + + for (int i = 0; i < 10; ++i) { + // expected-warning@+2{{left operand of comma operator has no effect}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc cache(readonly:ArrayPtr[5:3, *readonly], ArrayPtr[0]) + } + +} diff --git a/clang/test/ParserOpenACC/parse-cache-construct.cpp b/clang/test/ParserOpenACC/parse-cache-construct.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3b2230cabae32fd0824708b53bcdfee4d87a2428 --- /dev/null +++ b/clang/test/ParserOpenACC/parse-cache-construct.cpp @@ -0,0 +1,51 @@ +// RUN: %clang_cc1 %s -verify -fopenacc + +namespace NS { + static char* NSArray;// expected-note{{declared here}} + static int NSInt;// expected-note 2{{declared here}} +} +char *getArrayPtr(); +template +void func() { + char *ArrayPtr = getArrayPtr(); + for (int i = 0; i < 10; ++i) { + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc cache(ArrayPtr[T::value + I:I + 5], T::array[(i + T::value, 5): 6]) + } + for (int i = 0; i < 10; ++i) { + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc cache(NS::NSArray[NS::NSInt]) + } + + for (int i = 0; i < 10; ++i) { + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc cache(NS::NSArray[NS::NSInt : NS::NSInt]) + } + + for (int i = 0; i < 10; ++i) { + // expected-error@+2{{use of undeclared identifier 'NSArray'; did you mean 'NS::NSArray'}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc cache(NSArray[NS::NSInt : NS::NSInt]) + } + + for (int i = 0; i < 10; ++i) { + // expected-error@+2{{use of undeclared identifier 'NSInt'; did you mean 'NS::NSInt'}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc cache(NS::NSArray[NSInt : NS::NSInt]) + } + + for (int i = 0; i < 10; ++i) { + // expected-error@+2{{use of undeclared identifier 'NSInt'; did you mean 'NS::NSInt'}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc cache(NS::NSArray[NS::NSInt : NSInt]) + } +} + +struct S { + static constexpr int value = 5; + static constexpr char array[] ={1,2,3,4,5}; +}; + +void use() { + func(); +} diff --git a/clang/test/ParserOpenACC/parse-constructs.c b/clang/test/ParserOpenACC/parse-constructs.c index f0f9d75ade1fb2ef1d310dd55080afc4832428b2..83d9bd6070d41db083a7846a7331bd45fac0a0f4 100644 --- a/clang/test/ParserOpenACC/parse-constructs.c +++ b/clang/test/ParserOpenACC/parse-constructs.c @@ -7,6 +7,17 @@ void func() { #pragma acc for(;;){} + // expected-error@+4{{expected OpenACC directive}} + // expected-error@+3{{expected clause-list or newline in OpenACC directive}} + // expected-warning@+2{{OpenACC clause parsing not yet implemented}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc(whatever) routine + + // expected-error@+3{{expected OpenACC directive}} + // expected-warning@+2{{OpenACC clause parsing not yet implemented}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc) routine + // expected-error@+2{{invalid OpenACC directive 'invalid'}} // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} #pragma acc invalid @@ -61,7 +72,7 @@ void func() { // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} #pragma acc enter for(;;){} - // expected-error@+3{{invalid OpenACC directive 'exit }'}} + // expected-error@+3{{expected identifier}} // expected-warning@+2{{OpenACC clause parsing not yet implemented}} // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} #pragma acc exit } diff --git a/clang/test/ParserOpenACC/parse-wait-construct.c b/clang/test/ParserOpenACC/parse-wait-construct.c new file mode 100644 index 0000000000000000000000000000000000000000..9b210bc7094210464ec2aefa154ebb5ec1dfe208 --- /dev/null +++ b/clang/test/ParserOpenACC/parse-wait-construct.c @@ -0,0 +1,157 @@ +// RUN: %clang_cc1 %s -verify -fopenacc + +void func() { + int i, j; + + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait + + // expected-warning@+2{{OpenACC clause parsing not yet implemented}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait clause-list + + // expected-error@+3{{expected ')'}} + // expected-note@+2{{to match this '('}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait ( + + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait () + + // expected-warning@+2{{OpenACC clause parsing not yet implemented}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait () clause-list + + // expected-error@+4{{expected expression}} + // expected-error@+3{{expected ')'}} + // expected-note@+2{{to match this '('}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait (devnum: + + // expected-error@+2{{expected expression}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait (devnum:) + + // expected-error@+3{{expected expression}} + // expected-warning@+2{{OpenACC clause parsing not yet implemented}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait (devnum:) clause-list + + // expected-error@+4{{expected ':'}} + // expected-error@+3{{expected ')'}} + // expected-note@+2{{to match this '('}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait (devnum: i + j + + // expected-error@+2{{expected ':'}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait (devnum: i + j) + + // expected-error@+3{{expected ':'}} + // expected-warning@+2{{OpenACC clause parsing not yet implemented}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait (devnum: i + j) clause-list + + // expected-error@+3{{expected ')'}} + // expected-note@+2{{to match this '('}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait (queues: + + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait (queues:) + + // expected-warning@+2{{OpenACC clause parsing not yet implemented}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait (queues:) clause-list + + // expected-error@+3{{expected ')'}} + // expected-note@+2{{to match this '('}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait (devnum: i + j:queues: + + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait (devnum: i + j:queues:) + + // expected-warning@+2{{OpenACC clause parsing not yet implemented}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait (devnum: i + j:queues:) clause-list + + // expected-error@+4{{use of undeclared identifier 'devnum'}} + // expected-error@+3{{expected ')'}} + // expected-note@+2{{to match this '('}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait (queues:devnum: i + j + + // expected-error@+2{{use of undeclared identifier 'devnum'}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait (queues:devnum: i + j) + + // expected-error@+3{{use of undeclared identifier 'devnum'}} + // expected-warning@+2{{OpenACC clause parsing not yet implemented}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait (queues:devnum: i + j) clause-list + + // expected-error@+3{{expected ')'}} + // expected-note@+2{{to match this '('}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait(i, j, 1+1, 3.3 + + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait(i, j, 1+1, 3.3) + // expected-warning@+2{{OpenACC clause parsing not yet implemented}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait(i, j, 1+1, 3.3) clause-list + + // expected-error@+4{{expected expression}} + // expected-error@+3{{expected ')'}} + // expected-note@+2{{to match this '('}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait(, + + // expected-error@+2{{expected expression}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait(,) + + // expected-error@+3{{expected expression}} + // expected-warning@+2{{OpenACC clause parsing not yet implemented}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait(,) clause-list + + // expected-error@+3{{expected ')'}} + // expected-note@+2{{to match this '('}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait(queues:i, j, 1+1, 3.3 + + // expected-error@+4{{expected expression}} + // expected-error@+3{{expected ')'}} + // expected-note@+2{{to match this '('}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait(queues:i, j, 1+1, 3.3, + + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait(queues:i, j, 1+1, 3.3) + + // expected-warning@+2{{OpenACC clause parsing not yet implemented}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait(queues:i, j, 1+1, 3.3) clause-list + + // expected-error@+3{{expected ')'}} + // expected-note@+2{{to match this '('}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait(devnum:3:i, j, 1+1, 3.3 + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait(devnum:3:i, j, 1+1, 3.3) + // expected-warning@+2{{OpenACC clause parsing not yet implemented}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait(devnum:3:i, j, 1+1, 3.3) clause-list + + // expected-error@+3{{expected ')'}} + // expected-note@+2{{to match this '('}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait(devnum:3:queues:i, j, 1+1, 3.3 + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait(devnum:3:queues:i, j, 1+1, 3.3) + // expected-warning@+2{{OpenACC clause parsing not yet implemented}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait(devnum:3:queues:i, j, 1+1, 3.3) clause-list +} diff --git a/clang/test/ParserOpenACC/unimplemented.c b/clang/test/ParserOpenACC/unimplemented.c index dd2e8bea74709180c6802c27273a8feba0770983..2927e685d30b563c312362398c2cf9c1857d2ae1 100644 --- a/clang/test/ParserOpenACC/unimplemented.c +++ b/clang/test/ParserOpenACC/unimplemented.c @@ -1,26 +1,26 @@ // RUN: %clang_cc1 %s -verify -fopenacc // Parser::ParseExternalDeclaration -// expected-error@+3{{invalid OpenACC directive 'not'}} +// expected-error@+3{{invalid OpenACC directive 'havent'}} // expected-warning@+2{{OpenACC clause parsing not yet implemented}} // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} -#pragma acc not yet implemented +#pragma acc havent implemented int foo; struct S { // Parser::ParseStructUnionBody -// expected-error@+3{{invalid OpenACC directive 'not'}} +// expected-error@+3{{invalid OpenACC directive 'havent'}} // expected-warning@+2{{OpenACC clause parsing not yet implemented}} // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} -#pragma acc not yet implemented +#pragma acc havent implemented int foo; }; void func() { // Parser::ParseStmtOrDeclarationAfterAttributes -// expected-error@+3{{invalid OpenACC directive 'not'}} +// expected-error@+3{{invalid OpenACC directive 'havent'}} // expected-warning@+2{{OpenACC clause parsing not yet implemented}} // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} -#pragma acc not yet implemented +#pragma acc havent implemented while(0) {} } diff --git a/clang/test/ParserOpenACC/unimplemented.cpp b/clang/test/ParserOpenACC/unimplemented.cpp index 4f6c5a649065ec96390c4f01beef2751e8f1343f..77619c9ae6551edc97d76268fe31cb3b9002060e 100644 --- a/clang/test/ParserOpenACC/unimplemented.cpp +++ b/clang/test/ParserOpenACC/unimplemented.cpp @@ -1,26 +1,26 @@ // RUN: %clang_cc1 %s -verify -fopenacc // Parser::ParseExternalDeclaration -// expected-error@+3{{invalid OpenACC directive 'not'}} +// expected-error@+3{{invalid OpenACC directive 'havent'}} // expected-warning@+2{{OpenACC clause parsing not yet implemented}} // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} -#pragma acc not yet implemented +#pragma acc havent implemented int foo; struct S { // Parser::ParseCXXClassMemberDeclarationWithPragmas -// expected-error@+3{{invalid OpenACC directive 'not'}} +// expected-error@+3{{invalid OpenACC directive 'havent'}} // expected-warning@+2{{OpenACC clause parsing not yet implemented}} // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} -#pragma acc not yet implemented +#pragma acc havent implemented int foo; }; void func() { // Parser::ParseStmtOrDeclarationAfterAttributes -// expected-error@+3{{invalid OpenACC directive 'not'}} +// expected-error@+3{{invalid OpenACC directive 'havent'}} // expected-warning@+2{{OpenACC clause parsing not yet implemented}} // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} -#pragma acc not yet implemented +#pragma acc havent implemented while(false) {} } diff --git a/clang/test/Preprocessor/init-aarch64.c b/clang/test/Preprocessor/init-aarch64.c index 2b7cc57f230333386feb3231a0eb4718aacf94f5..94c091a69e8444e963a5a72a11f19e8e1ec3cc9b 100644 --- a/clang/test/Preprocessor/init-aarch64.c +++ b/clang/test/Preprocessor/init-aarch64.c @@ -118,6 +118,7 @@ // AARCH64-NEXT: #define __FP_FAST_FMAF 1 // AARCH64-NEXT: #define __GCC_ASM_FLAG_OUTPUTS__ 1 // AARCH64-NEXT: #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 1 +// AARCH64-NEXT: #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16 1 // AARCH64-NEXT: #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 1 // AARCH64-NEXT: #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 1 // AARCH64-NEXT: #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 1 @@ -217,6 +218,11 @@ // AARCH64-NEXT: #define __LONG_MAX__ 9223372036854775807L // AARCH64-NEXT: #define __LONG_WIDTH__ 64 // AARCH64-NEXT: #define __LP64__ 1 +// AARCH64-NEXT: #define __MEMORY_SCOPE_DEVICE 1 +// AARCH64-NEXT: #define __MEMORY_SCOPE_SINGLE 4 +// AARCH64-NEXT: #define __MEMORY_SCOPE_SYSTEM 0 +// AARCH64-NEXT: #define __MEMORY_SCOPE_WRKGRP 2 +// AARCH64-NEXT: #define __MEMORY_SCOPE_WVFRNT 3 // AARCH64-NEXT: #define __NO_INLINE__ 1 // AARCH64-NEXT: #define __NO_MATH_ERRNO__ 1 // AARCH64-NEXT: #define __OBJC_BOOL_IS_BOOL 0 diff --git a/clang/test/Preprocessor/init-loongarch.c b/clang/test/Preprocessor/init-loongarch.c index e235a728302153a62617eae9c1eb17e87347fe34..10a4cc7e66e830ace7a796c38a665fc5f9262b2a 100644 --- a/clang/test/Preprocessor/init-loongarch.c +++ b/clang/test/Preprocessor/init-loongarch.c @@ -177,6 +177,11 @@ // LA32: #define __LONG_LONG_MAX__ 9223372036854775807LL // LA32: #define __LONG_MAX__ 2147483647L // LA32: #define __LONG_WIDTH__ 32 +// LA32: #define __MEMORY_SCOPE_DEVICE 1 +// LA32: #define __MEMORY_SCOPE_SINGLE 4 +// LA32: #define __MEMORY_SCOPE_SYSTEM 0 +// LA32: #define __MEMORY_SCOPE_WRKGRP 2 +// LA32: #define __MEMORY_SCOPE_WVFRNT 3 // LA32: #define __NO_INLINE__ 1 // LA32: #define __NO_MATH_ERRNO__ 1 // LA32: #define __OBJC_BOOL_IS_BOOL 0 @@ -494,6 +499,11 @@ // LA64: #define __LONG_MAX__ 9223372036854775807L // LA64: #define __LONG_WIDTH__ 64 // LA64: #define __LP64__ 1 +// LA64: #define __MEMORY_SCOPE_DEVICE 1 +// LA64: #define __MEMORY_SCOPE_SINGLE 4 +// LA64: #define __MEMORY_SCOPE_SYSTEM 0 +// LA64: #define __MEMORY_SCOPE_WRKGRP 2 +// LA64: #define __MEMORY_SCOPE_WVFRNT 3 // LA64: #define __NO_INLINE__ 1 // LA64: #define __NO_MATH_ERRNO__ 1 // LA64: #define __OBJC_BOOL_IS_BOOL 0 diff --git a/clang/test/Preprocessor/init.c b/clang/test/Preprocessor/init.c index a0a2879cb58c7fc50cffe383f78f2f7a03e309de..c3dbd94b2f741bd46df56e98d62363e407f7f04f 100644 --- a/clang/test/Preprocessor/init.c +++ b/clang/test/Preprocessor/init.c @@ -1742,6 +1742,11 @@ // WEBASSEMBLY64-NEXT:#define __LONG_MAX__ 9223372036854775807L // WEBASSEMBLY64-NEXT:#define __LONG_WIDTH__ 64 // WEBASSEMBLY64-NEXT:#define __LP64__ 1 +// WEBASSEMBLY-NEXT:#define __MEMORY_SCOPE_DEVICE 1 +// WEBASSEMBLY-NEXT:#define __MEMORY_SCOPE_SINGLE 4 +// WEBASSEMBLY-NEXT:#define __MEMORY_SCOPE_SYSTEM 0 +// WEBASSEMBLY-NEXT:#define __MEMORY_SCOPE_WRKGRP 2 +// WEBASSEMBLY-NEXT:#define __MEMORY_SCOPE_WVFRNT 3 // WEBASSEMBLY-NEXT:#define __NO_INLINE__ 1 // WEBASSEMBLY-NEXT:#define __NO_MATH_ERRNO__ 1 // WEBASSEMBLY-NEXT:#define __OBJC_BOOL_IS_BOOL 0 @@ -2057,6 +2062,11 @@ // AVR:#define __LDBL_MIN__ 1.17549435e-38L // AVR:#define __LONG_LONG_MAX__ 9223372036854775807LL // AVR:#define __LONG_MAX__ 2147483647L +// AVR:#define __MEMORY_SCOPE_DEVICE 1 +// AVR:#define __MEMORY_SCOPE_SINGLE 4 +// AVR:#define __MEMORY_SCOPE_SYSTEM 0 +// AVR:#define __MEMORY_SCOPE_WRKGRP 2 +// AVR:#define __MEMORY_SCOPE_WVFRNT 3 // AVR:#define __NO_INLINE__ 1 // AVR:#define __ORDER_BIG_ENDIAN__ 4321 // AVR:#define __ORDER_LITTLE_ENDIAN__ 1234 @@ -2348,6 +2358,11 @@ // RISCV32: #define __LITTLE_ENDIAN__ 1 // RISCV32: #define __LONG_LONG_MAX__ 9223372036854775807LL // RISCV32: #define __LONG_MAX__ 2147483647L +// RISCV32: #define __MEMORY_SCOPE_DEVICE 1 +// RISCV32: #define __MEMORY_SCOPE_SINGLE 4 +// RISCV32: #define __MEMORY_SCOPE_SYSTEM 0 +// RISCV32: #define __MEMORY_SCOPE_WRKGRP 2 +// RISCV32: #define __MEMORY_SCOPE_WVFRNT 3 // RISCV32: #define __NO_INLINE__ 1 // RISCV32: #define __POINTER_WIDTH__ 32 // RISCV32: #define __PRAGMA_REDEFINE_EXTNAME 1 @@ -2555,6 +2570,11 @@ // RISCV64: #define __LONG_LONG_MAX__ 9223372036854775807LL // RISCV64: #define __LONG_MAX__ 9223372036854775807L // RISCV64: #define __LP64__ 1 +// RISCV64: #define __MEMORY_SCOPE_DEVICE 1 +// RISCV64: #define __MEMORY_SCOPE_SINGLE 4 +// RISCV64: #define __MEMORY_SCOPE_SYSTEM 0 +// RISCV64: #define __MEMORY_SCOPE_WRKGRP 2 +// RISCV64: #define __MEMORY_SCOPE_WVFRNT 3 // RISCV64: #define __NO_INLINE__ 1 // RISCV64: #define __POINTER_WIDTH__ 64 // RISCV64: #define __PRAGMA_REDEFINE_EXTNAME 1 diff --git a/clang/test/Preprocessor/pragma_unknown.c b/clang/test/Preprocessor/pragma_unknown.c index a7c4829c279dd14162416ec7f6c89ebd35226237..1d39f8229eb53b2f46142ebab2e217408a744498 100644 --- a/clang/test/Preprocessor/pragma_unknown.c +++ b/clang/test/Preprocessor/pragma_unknown.c @@ -27,6 +27,8 @@ #pragma STDC CX_LIMITED_RANGE // expected-warning {{expected 'ON' or 'OFF' or 'DEFAULT' in pragma}} #pragma STDC CX_LIMITED_RANGE ON FULL POWER // expected-warning {{expected end of directive in pragma}} +//expected-error@-1 {{unknown type name 'POWER'}} +//expected-error@-2 {{expected identifier or '('}} // CHECK: {{^}}#pragma STDC CX_LIMITED_RANGE{{$}} // CHECK: {{^}}#pragma STDC CX_LIMITED_RANGE ON FULL POWER{{$}} diff --git a/clang/test/Sema/aarch64-sme2-intrinsics/acle_sme2_imm.cpp b/clang/test/Sema/aarch64-sme2-intrinsics/acle_sme2_imm.cpp index 70987ad395f735a2655084bea8aeddc1768c2028..3750045fd8dff36c922688ef26d4157620b10e84 100644 --- a/clang/test/Sema/aarch64-sme2-intrinsics/acle_sme2_imm.cpp +++ b/clang/test/Sema/aarch64-sme2-intrinsics/acle_sme2_imm.cpp @@ -20,7 +20,168 @@ void test_outer_product(svbool_t pred, svint16_t s16, svuint16_t u16, svint32_t svbmops_za32_s32_m(4, pred, pred, s32, s32); // expected-error {{argument value 4 is outside the valid range [0, 3]}} } -void test_ldr_str_zt(const void *const_base, void *base) __arm_streaming_compatible __arm_shared_za __arm_preserves_za { +void test_ldr_zt(const void *const_base) __arm_streaming_compatible __arm_shared_za { svldr_zt(1, const_base); // expected-error {{argument value 1 is outside the valid range [0, 0]}} +} + +void test_str_zt(void *base) __arm_streaming_compatible __arm_shared_za __arm_preserves_za { svstr_zt(1, base); // expected-error {{argument value 1 is outside the valid range [0, 0]}} } + +void test_svluti2_lane_zt_x4(svuint8_t zn) __arm_streaming __arm_shared_za __arm_preserves_za { + // Test Reg Offset + svluti2_lane_zt_u8_x4(1, zn, 0); // expected-error {{argument value 1 is outside the valid range [0, 0]}} + // Test index value range + svluti2_lane_zt_u8_x4(0, zn, 4); // expected-error {{argument value 4 is outside the valid range [0, 3]}} + // Test Reg Offset + svluti2_lane_zt_u16_x4(1, zn, 3); // expected-error {{argument value 1 is outside the valid range [0, 0]}} + // Test index value range + svluti2_lane_zt_u16_x4(0, zn, 4); // expected-error {{argument value 4 is outside the valid range [0, 3]}} + // Test Reg Offset + svluti2_lane_zt_u32_x4(1, zn, 3); // expected-error {{argument value 1 is outside the valid range [0, 0]}} + // Test index value range + svluti2_lane_zt_u32_x4(0, zn, 4); // expected-error {{argument value 4 is outside the valid range [0, 3]}} + // Test Reg Offset + svluti2_lane_zt_f16_x4(1, zn, 3); // expected-error {{argument value 1 is outside the valid range [0, 0]}} + // Test index value range + svluti2_lane_zt_f16_x4(0, zn, 4); // expected-error {{argument value 4 is outside the valid range [0, 3]}} + // Test Reg Offset + svluti2_lane_zt_bf16_x4(1, zn, 3); // expected-error {{argument value 1 is outside the valid range [0, 0]}} + // Test index value range + svluti2_lane_zt_bf16_x4(0, zn, 4); // expected-error {{argument value 4 is outside the valid range [0, 3]}} + // Test Reg Offset + svluti2_lane_zt_f32_x4(1, zn, 3); // expected-error {{argument value 1 is outside the valid range [0, 0]}} + // Test index value range + svluti2_lane_zt_f32_x4(0, zn, 4); // expected-error {{argument value 4 is outside the valid range [0, 3]}} +} + +void test_svluti4_lane_zt_x4(svuint8_t zn) __arm_streaming __arm_shared_za __arm_preserves_za { + // Test Reg Offset + svluti4_lane_zt_u16_x4(1, zn, 0); // expected-error {{argument value 1 is outside the valid range [0, 0]}} + // Test index value range + svluti4_lane_zt_u16_x4(0, zn, 2); // expected-error {{argument value 2 is outside the valid range [0, 1]}} + // Test Reg Offset + svluti4_lane_zt_u32_x4(1, zn, 1); // expected-error {{argument value 1 is outside the valid range [0, 0]}} + // Test index value range + svluti4_lane_zt_u32_x4(0, zn, 2); // expected-error {{argument value 2 is outside the valid range [0, 1]}} + // Test Reg Offset + svluti4_lane_zt_f16_x4(1, zn, 0); // expected-error {{argument value 1 is outside the valid range [0, 0]}} + // Test index value range + svluti4_lane_zt_f16_x4(0, zn, 2); // expected-error {{argument value 2 is outside the valid range [0, 1]}} + // Test Reg Offset + svluti4_lane_zt_bf16_x4(1, zn, 0); // expected-error {{argument value 1 is outside the valid range [0, 0]}} + // Test index value range + svluti4_lane_zt_bf16_x4(0, zn, 2); // expected-error {{argument value 2 is outside the valid range [0, 1]}} + // Test Reg Offset + svluti4_lane_zt_f32_x4(1, zn, 1); // expected-error {{argument value 1 is outside the valid range [0, 0]}} + // Test index value range + svluti4_lane_zt_f32_x4(0, zn, 2); // expected-error {{argument value 2 is outside the valid range [0, 1]}} +} + +void test_svluti2_lane_zt(svuint8_t zn_u8) __arm_streaming __arm_shared_za __arm_preserves_za { + // Test Reg Offset + svluti2_lane_zt_u8(1, zn_u8, 2); // expected-error {{argument value 1 is outside the valid range [0, 0]}} + // Test index value range + svluti2_lane_zt_u8(0, zn_u8, 16); // expected-error {{argument value 16 is outside the valid range [0, 15]}} + // Test Reg Offset + svluti2_lane_zt_u16(1, zn_u8, 2); // expected-error {{argument value 1 is outside the valid range [0, 0]}} + // Test index value range + svluti2_lane_zt_u16(0, zn_u8, 16); // expected-error {{argument value 16 is outside the valid range [0, 15]}} + // Test Reg Offset + svluti2_lane_zt_f16(1, zn_u8, 2); // expected-error {{argument value 1 is outside the valid range [0, 0]}} + // Test index value range + svluti2_lane_zt_f16(0, zn_u8, 16); // expected-error {{argument value 16 is outside the valid range [0, 15]}} + // Test Reg Offset + svluti2_lane_zt_bf16(1, zn_u8, 2); // expected-error {{argument value 1 is outside the valid range [0, 0]}} + // Test index value range + svluti2_lane_zt_bf16(0, zn_u8, 16); // expected-error {{argument value 16 is outside the valid range [0, 15]}} + // Test Reg Offset + svluti2_lane_zt_u32(1, zn_u8, 2); // expected-error {{argument value 1 is outside the valid range [0, 0]}} + // Test index value range + svluti2_lane_zt_u32(0, zn_u8, 16); // expected-error {{argument value 16 is outside the valid range [0, 15]}} + // Test Reg Offset + svluti2_lane_zt_f32(1, zn_u8, 2); // expected-error {{argument value 1 is outside the valid range [0, 0]}} + // Test index value range + svluti2_lane_zt_f32(0, zn_u8, 16); // expected-error {{argument value 16 is outside the valid range [0, 15]}} +} + +void test_svluti4_lane_zt(svuint8_t zn_u8) __arm_streaming __arm_shared_za __arm_preserves_za { + // Test Reg Offset + svluti4_lane_zt_u8(1, zn_u8, 2); // expected-error {{argument value 1 is outside the valid range [0, 0]}} + // Test index value range + svluti4_lane_zt_u8(0, zn_u8, 8); // expected-error {{argument value 8 is outside the valid range [0, 7]}} + // Test Reg Offset + svluti4_lane_zt_u16(1, zn_u8, 2); // expected-error {{argument value 1 is outside the valid range [0, 0]}} + // Test index value range + svluti4_lane_zt_u16(0, zn_u8, 8); // expected-error {{argument value 8 is outside the valid range [0, 7]}} + // Test Reg Offset + svluti4_lane_zt_f16(1, zn_u8, 2); // expected-error {{argument value 1 is outside the valid range [0, 0]}} + // Test index value range + svluti4_lane_zt_f16(0, zn_u8, 8); // expected-error {{argument value 8 is outside the valid range [0, 7]}} + // Test Reg Offset + svluti4_lane_zt_bf16(1, zn_u8, 2); // expected-error {{argument value 1 is outside the valid range [0, 0]}} + // Test index value range + svluti4_lane_zt_bf16(0, zn_u8, 8); // expected-error {{argument value 8 is outside the valid range [0, 7]}} + // Test Reg Offset + svluti4_lane_zt_u32(1, zn_u8, 2); // expected-error {{argument value 1 is outside the valid range [0, 0]}} + // Test index value range + svluti4_lane_zt_u32(0, zn_u8, 8); // expected-error {{argument value 8 is outside the valid range [0, 7]}} + // Test Reg Offset + svluti4_lane_zt_f32(1, zn_u8, 2); // expected-error {{argument value 1 is outside the valid range [0, 0]}} + // Test index value range + svluti4_lane_zt_f32(0, zn_u8, 8); // expected-error {{argument value 8 is outside the valid range [0, 7]}} +} + +void test_svluti2_lane_zt_x2(svuint8_t zn_u8) __arm_streaming __arm_shared_za __arm_preserves_za { + // Test Reg Offset + svluti2_lane_zt_u8_x2(1, zn_u8, 2); // expected-error {{argument value 1 is outside the valid range [0, 0]}} + // Test index value range + svluti2_lane_zt_u8_x2(0, zn_u8, 8); // expected-error {{argument value 8 is outside the valid range [0, 7]}} + // Test Reg Offset + svluti2_lane_zt_u16_x2(1, zn_u8, 2); // expected-error {{argument value 1 is outside the valid range [0, 0]}} + // Test index value range + svluti2_lane_zt_u16_x2(0, zn_u8, 8); // expected-error {{argument value 8 is outside the valid range [0, 7]}} + // Test Reg Offset + svluti2_lane_zt_u32_x2(1, zn_u8, 2); // expected-error {{argument value 1 is outside the valid range [0, 0]}} + // Test index value range + svluti2_lane_zt_u32_x2(0, zn_u8, 8); // expected-error {{argument value 8 is outside the valid range [0, 7]}} + // Test Reg Offset + svluti2_lane_zt_f16_x2(1, zn_u8, 2); // expected-error {{argument value 1 is outside the valid range [0, 0]}} + // Test index value range + svluti2_lane_zt_f16_x2(0, zn_u8, 8); // expected-error {{argument value 8 is outside the valid range [0, 7]}} + // Test Reg Offset + svluti2_lane_zt_bf16_x2(1, zn_u8, 2); // expected-error {{argument value 1 is outside the valid range [0, 0]}} + // Test index value range + svluti2_lane_zt_bf16_x2(0, zn_u8, 8); // expected-error {{argument value 8 is outside the valid range [0, 7]}} + // Test Reg Offset + svluti2_lane_zt_f32_x2(1, zn_u8, 2); // expected-error {{argument value 1 is outside the valid range [0, 0]}} + // Test index value range + svluti2_lane_zt_f32_x2(0, zn_u8, 8); // expected-error {{argument value 8 is outside the valid range [0, 7]}} +} + +void test_svluti4_lane_zt_x2(svuint8_t zn_u8) __arm_streaming __arm_shared_za __arm_preserves_za { + // Test Reg Offset + svluti4_lane_zt_u8_x2(1, zn_u8, 2); // expected-error {{argument value 1 is outside the valid range [0, 0]}} + // Test index value range + svluti4_lane_zt_u8_x2(0, zn_u8, 4); // expected-error {{argument value 4 is outside the valid range [0, 3]}} + // Test Reg Offset + svluti4_lane_zt_u16_x2(1, zn_u8, 2); // expected-error {{argument value 1 is outside the valid range [0, 0]}} + // Test index value range + svluti4_lane_zt_u16_x2(0, zn_u8, 4); // expected-error {{argument value 4 is outside the valid range [0, 3]}} + // Test Reg Offset + svluti4_lane_zt_u32_x2(1, zn_u8, 2); // expected-error {{argument value 1 is outside the valid range [0, 0]}} + // Test index value range + svluti4_lane_zt_u32_x2(0, zn_u8, 4); // expected-error {{argument value 4 is outside the valid range [0, 3]}} + // Test Reg Offset + svluti4_lane_zt_f16_x2(1, zn_u8, 2); // expected-error {{argument value 1 is outside the valid range [0, 0]}} + // Test index value range + svluti4_lane_zt_f16_x2(0, zn_u8, 4); // expected-error {{argument value 4 is outside the valid range [0, 3]}} + // Test Reg Offset + svluti4_lane_zt_bf16_x2(1, zn_u8, 2); // expected-error {{argument value 1 is outside the valid range [0, 0]}} + // Test index value range + svluti4_lane_zt_bf16_x2(0, zn_u8, 4); // expected-error {{argument value 4 is outside the valid range [0, 3]}} + // Test Reg Offset + svluti4_lane_zt_f32_x2(1, zn_u8, 2); // expected-error {{argument value 1 is outside the valid range [0, 0]}} + // Test index value range + svluti4_lane_zt_f32_x2(0, zn_u8, 4); // expected-error {{argument value 4 is outside the valid range [0, 3]}} +} diff --git a/clang/test/Sema/aarch64-sve2p1-intrinsics/acle_sve2p1_imm.cpp b/clang/test/Sema/aarch64-sve2p1-intrinsics/acle_sve2p1_imm.cpp index 35bf99bfcf4c5b07e62317fd14f3ea2108a9fb3c..f90ae0fb50e5fca0200dd5213b1516d14dda9c7c 100644 --- a/clang/test/Sema/aarch64-sve2p1-intrinsics/acle_sve2p1_imm.cpp +++ b/clang/test/Sema/aarch64-sve2p1-intrinsics/acle_sve2p1_imm.cpp @@ -167,3 +167,21 @@ void test_svpmov_lane(){ zn_u32 = svpmov_lane_u32_m(zn_u32, pn, 5); // expected-error {{argument value 5 is outside the valid range [1, 3]}} zn_u64 = svpmov_lane_u64_m(zn_u64, pn, 8); // expected-error {{argument value 8 is outside the valid range [1, 7]}} } + +__attribute__((target("+sve2p1"))) +void test_svget_svset_b(uint64_t idx, svboolx2_t tuple2, svboolx4_t tuple4, svbool_t res){ + svset2(tuple2, -1, res); // expected-error {{argument value 18446744073709551615 is outside the valid range [0, 1]}} + svset2(tuple2, 2, res); // expected-error {{argument value 2 is outside the valid range [0, 1]}} + svset4(tuple4, -1, res); // expected-error {{argument value 18446744073709551615 is outside the valid range [0, 3]}} + svset4(tuple4, 4, res); // expected-error {{argument value 4 is outside the valid range [0, 3]}} + + svget2(tuple2, -1); // expected-error {{argument value 18446744073709551615 is outside the valid range [0, 1]}} + svget2(tuple2, 2); // expected-error {{argument value 2 is outside the valid range [0, 1]}} + svget4(tuple4, -1); // expected-error {{argument value 18446744073709551615 is outside the valid range [0, 3]}} + svget4(tuple4, 4); // expected-error {{argument value 4 is outside the valid range [0, 3]}} + + svset2(tuple2, idx, res); // expected-error {{argument to 'svste2' must be a constant integer}} + svset4(tupl4, idx, res); // expected-error {{argument to 'svset4' must be a constant integer}} + svget2(tuple2, idx); // expected-error {{argument to 'svget2' must be a constant integer}} + svget4(tuple4, idx); // expected-error {{argument to 'svget4' must be a constant integer}} +} diff --git a/clang/test/Sema/bpf-attr-preserve-static-offset-warns-nonbpf.c b/clang/test/Sema/bpf-attr-preserve-static-offset-warns-nonbpf.c new file mode 100644 index 0000000000000000000000000000000000000000..d543e6f999529d0a96539c2879f7b677472ed6c1 --- /dev/null +++ b/clang/test/Sema/bpf-attr-preserve-static-offset-warns-nonbpf.c @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +#define __pso __attribute__((preserve_static_offset)) + +struct foo { int a; } __pso; // expected-warning{{unknown attribute}} +union quux { int a; } __pso; // expected-warning{{unknown attribute}} diff --git a/clang/test/Sema/bpf-attr-preserve-static-offset-warns.c b/clang/test/Sema/bpf-attr-preserve-static-offset-warns.c new file mode 100644 index 0000000000000000000000000000000000000000..1067ebe8f82b051e6fd194f095f3dcbe1a0c3483 --- /dev/null +++ b/clang/test/Sema/bpf-attr-preserve-static-offset-warns.c @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -triple bpf-pc-linux-gnu %s + +#define __pso __attribute__((preserve_static_offset)) + +// These are correct usages. +struct foo { int a; } __pso; +union quux { int a; } __pso; +struct doug { int a; } __pso __attribute__((packed)); + +// Rest are incorrect usages. +typedef int bar __pso; // expected-error{{attribute only applies to}} +struct goo { + int a __pso; // expected-error{{attribute only applies to}} +}; +int g __pso; // expected-error{{attribute only applies to}} +__pso void ffunc1(void); // expected-error{{attribute only applies to}} +void ffunc2(int a __pso); // expected-error{{attribute only applies to}} +void ffunc3(void) { + int a __pso; // expected-error{{attribute only applies to}} +} + +struct buz { int a; } __attribute__((preserve_static_offset("hello"))); // \ + expected-error{{attribute takes no arguments}} diff --git a/clang/test/Sema/bpf-attr-preserve-static-offset.c b/clang/test/Sema/bpf-attr-preserve-static-offset.c new file mode 100644 index 0000000000000000000000000000000000000000..5f53469869f3d7d9538efd20c367c8cd6012d436 --- /dev/null +++ b/clang/test/Sema/bpf-attr-preserve-static-offset.c @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -fsyntax-only -ast-dump -triple bpf-pc-linux-gnu %s | FileCheck %s + +// The 'preserve_static_offset' attribute should be propagated to +// inline declarations (foo's 'b', 'bb', 'c' but not 'd'). +// +// CHECK: RecordDecl {{.*}} struct foo definition +// CHECK-NEXT: BPFPreserveStaticOffsetAttr +// CHECK-NEXT: FieldDecl {{.*}} a +// CHECK-NEXT: RecordDecl {{.*}} struct definition +// CHECK-NEXT: FieldDecl {{.*}} aa +// CHECK-NEXT: FieldDecl {{.*}} b +// CHECK-NEXT: RecordDecl {{.*}} union bar definition +// CHECK-NEXT: BPFPreserveStaticOffsetAttr +// CHECK-NEXT: FieldDecl {{.*}} a +// CHECK-NEXT: FieldDecl {{.*}} b + +struct foo { + int a; + struct { + int aa; + } b; +} __attribute__((preserve_static_offset)); + +union bar { + int a; + long b; +} __attribute__((preserve_static_offset)); diff --git a/clang/test/Sema/builtin-expect-with-probability.cpp b/clang/test/Sema/builtin-expect-with-probability.cpp index 2b72c7b27ae93e83f61fa4a5024766b59e7b695b..c55cde84b254834895ffb440e19e7f0ef3350a3c 100644 --- a/clang/test/Sema/builtin-expect-with-probability.cpp +++ b/clang/test/Sema/builtin-expect-with-probability.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -verify -fexperimental-new-constant-interpreter %s __attribute__((noreturn)) extern void bar(); diff --git a/clang/test/Sema/riscv-vector-v-check.c b/clang/test/Sema/riscv-vector-v-check.c index 8faa92c7b3cf126e999c535c7f292cf5f7a68a80..a1091c1e5d6668d7472fdfd5fa52880af49f00c9 100644 --- a/clang/test/Sema/riscv-vector-v-check.c +++ b/clang/test/Sema/riscv-vector-v-check.c @@ -4,194 +4,194 @@ #include vint64m1_t test_vsmul_vv_i64m1(vint64m1_t op1, vint64m1_t op2, size_t vl) { - return __riscv_vsmul_vv_i64m1(op1, op2, __RISCV_VXRM_RNU, vl); /* expected-error {{builtin requires: v}} */ + return __riscv_vsmul_vv_i64m1(op1, op2, __RISCV_VXRM_RNU, vl); /* expected-error {{builtin requires at least one of the following extensions: v}} */ } vint64m1_t test_vsmul_vx_i64m1(vint64m1_t op1, int64_t op2, size_t vl) { - return __riscv_vsmul_vx_i64m1(op1, op2, __RISCV_VXRM_RNU, vl); /* expected-error {{builtin requires: v}} */ + return __riscv_vsmul_vx_i64m1(op1, op2, __RISCV_VXRM_RNU, vl); /* expected-error {{builtin requires at least one of the following extensions: v}} */ } vint64m2_t test_vsmul_vv_i64m2(vint64m2_t op1, vint64m2_t op2, size_t vl) { - return __riscv_vsmul_vv_i64m2(op1, op2, __RISCV_VXRM_RNU, vl); /* expected-error {{builtin requires: v}} */ + return __riscv_vsmul_vv_i64m2(op1, op2, __RISCV_VXRM_RNU, vl); /* expected-error {{builtin requires at least one of the following extensions: v}} */ } vint64m2_t test_vsmul_vx_i64m2(vint64m2_t op1, int64_t op2, size_t vl) { - return __riscv_vsmul_vx_i64m2(op1, op2, __RISCV_VXRM_RNU, vl); /* expected-error {{builtin requires: v}} */ + return __riscv_vsmul_vx_i64m2(op1, op2, __RISCV_VXRM_RNU, vl); /* expected-error {{builtin requires at least one of the following extensions: v}} */ } vint64m4_t test_vsmul_vv_i64m4(vint64m4_t op1, vint64m4_t op2, size_t vl) { - return __riscv_vsmul_vv_i64m4(op1, op2, __RISCV_VXRM_RNU, vl); /* expected-error {{builtin requires: v}} */ + return __riscv_vsmul_vv_i64m4(op1, op2, __RISCV_VXRM_RNU, vl); /* expected-error {{builtin requires at least one of the following extensions: v}} */ } vint64m4_t test_vsmul_vx_i64m4(vint64m4_t op1, int64_t op2, size_t vl) { - return __riscv_vsmul_vx_i64m4(op1, op2, __RISCV_VXRM_RNU, vl); /* expected-error {{builtin requires: v}} */ + return __riscv_vsmul_vx_i64m4(op1, op2, __RISCV_VXRM_RNU, vl); /* expected-error {{builtin requires at least one of the following extensions: v}} */ } vint64m8_t test_vsmul_vv_i64m8(vint64m8_t op1, vint64m8_t op2, size_t vl) { - return __riscv_vsmul_vv_i64m8(op1, op2, __RISCV_VXRM_RNU, vl); /* expected-error {{builtin requires: v}} */ + return __riscv_vsmul_vv_i64m8(op1, op2, __RISCV_VXRM_RNU, vl); /* expected-error {{builtin requires at least one of the following extensions: v}} */ } vint64m8_t test_vsmul_vx_i64m8(vint64m8_t op1, int64_t op2, size_t vl) { - return __riscv_vsmul_vx_i64m8(op1, op2, __RISCV_VXRM_RNU, vl); /* expected-error {{builtin requires: v}} */ + return __riscv_vsmul_vx_i64m8(op1, op2, __RISCV_VXRM_RNU, vl); /* expected-error {{builtin requires at least one of the following extensions: v}} */ } vint64m1_t test_vsmul_vv_i64m1_m(vbool64_t mask, vint64m1_t op1, vint64m1_t op2, size_t vl) { - return __riscv_vsmul_vv_i64m1_m(mask, op1, op2, __RISCV_VXRM_RNU, vl); /* expected-error {{builtin requires: v}} */ + return __riscv_vsmul_vv_i64m1_m(mask, op1, op2, __RISCV_VXRM_RNU, vl); /* expected-error {{builtin requires at least one of the following extensions: v}} */ } vint64m1_t test_vsmul_vx_i64m1_m(vbool64_t mask, vint64m1_t op1, int64_t op2, size_t vl) { - return __riscv_vsmul_vx_i64m1_m(mask, op1, op2, __RISCV_VXRM_RNU, vl); /* expected-error {{builtin requires: v}} */ + return __riscv_vsmul_vx_i64m1_m(mask, op1, op2, __RISCV_VXRM_RNU, vl); /* expected-error {{builtin requires at least one of the following extensions: v}} */ } vint64m2_t test_vsmul_vv_i64m2_m(vbool32_t mask, vint64m2_t op1, vint64m2_t op2, size_t vl) { - return __riscv_vsmul_vv_i64m2_m(mask, op1, op2, __RISCV_VXRM_RNU, vl); /* expected-error {{builtin requires: v}} */ + return __riscv_vsmul_vv_i64m2_m(mask, op1, op2, __RISCV_VXRM_RNU, vl); /* expected-error {{builtin requires at least one of the following extensions: v}} */ } vint64m2_t test_vsmul_vx_i64m2_m(vbool32_t mask, vint64m2_t op1, int64_t op2, size_t vl) { - return __riscv_vsmul_vx_i64m2_m(mask, op1, op2, __RISCV_VXRM_RNU, vl); /* expected-error {{builtin requires: v}} */ + return __riscv_vsmul_vx_i64m2_m(mask, op1, op2, __RISCV_VXRM_RNU, vl); /* expected-error {{builtin requires at least one of the following extensions: v}} */ } vint64m4_t test_vsmul_vv_i64m4_m(vbool16_t mask, vint64m4_t op1, vint64m4_t op2, size_t vl) { - return __riscv_vsmul_vv_i64m4_m(mask, op1, op2, __RISCV_VXRM_RNU, vl); /* expected-error {{builtin requires: v}} */ + return __riscv_vsmul_vv_i64m4_m(mask, op1, op2, __RISCV_VXRM_RNU, vl); /* expected-error {{builtin requires at least one of the following extensions: v}} */ } vint64m4_t test_vsmul_vx_i64m4_m(vbool16_t mask, vint64m4_t op1, int64_t op2, size_t vl) { - return __riscv_vsmul_vx_i64m4_m(mask, op1, op2, __RISCV_VXRM_RNU, vl); /* expected-error {{builtin requires: v}} */ + return __riscv_vsmul_vx_i64m4_m(mask, op1, op2, __RISCV_VXRM_RNU, vl); /* expected-error {{builtin requires at least one of the following extensions: v}} */ } vint64m8_t test_vsmul_vv_i64m8_m(vbool8_t mask, vint64m8_t op1, vint64m8_t op2, size_t vl) { - return __riscv_vsmul_vv_i64m8_m(mask, op1, op2, __RISCV_VXRM_RNU, vl); /* expected-error {{builtin requires: v}} */ + return __riscv_vsmul_vv_i64m8_m(mask, op1, op2, __RISCV_VXRM_RNU, vl); /* expected-error {{builtin requires at least one of the following extensions: v}} */ } vint64m8_t test_vsmul_vx_i64m8_m(vbool8_t mask, vint64m8_t op1, int64_t op2, size_t vl) { - return __riscv_vsmul_vx_i64m8_m(mask, op1, op2, __RISCV_VXRM_RNU, vl); /* expected-error {{builtin requires: v}} */ + return __riscv_vsmul_vx_i64m8_m(mask, op1, op2, __RISCV_VXRM_RNU, vl); /* expected-error {{builtin requires at least one of the following extensions: v}} */ } vint64m1_t test_vmulh_vv_i64m1(vint64m1_t op1, vint64m1_t op2, size_t vl) { - return __riscv_vmulh_vv_i64m1(op1, op2, vl); /* expected-error {{builtin requires: v}} */ + return __riscv_vmulh_vv_i64m1(op1, op2, vl); /* expected-error {{builtin requires at least one of the following extensions: v}} */ } vint64m1_t test_vmulh_vx_i64m1(vint64m1_t op1, int64_t op2, size_t vl) { - return __riscv_vmulh_vx_i64m1(op1, op2, vl); /* expected-error {{builtin requires: v}} */ + return __riscv_vmulh_vx_i64m1(op1, op2, vl); /* expected-error {{builtin requires at least one of the following extensions: v}} */ } vint64m2_t test_vmulh_vv_i64m2(vint64m2_t op1, vint64m2_t op2, size_t vl) { - return __riscv_vmulh_vv_i64m2(op1, op2, vl); /* expected-error {{builtin requires: v}} */ + return __riscv_vmulh_vv_i64m2(op1, op2, vl); /* expected-error {{builtin requires at least one of the following extensions: v}} */ } vint64m2_t test_vmulh_vx_i64m2(vint64m2_t op1, int64_t op2, size_t vl) { - return __riscv_vmulh_vx_i64m2(op1, op2, vl); /* expected-error {{builtin requires: v}} */ + return __riscv_vmulh_vx_i64m2(op1, op2, vl); /* expected-error {{builtin requires at least one of the following extensions: v}} */ } vint64m4_t test_vmulh_vv_i64m4(vint64m4_t op1, vint64m4_t op2, size_t vl) { - return __riscv_vmulh_vv_i64m4(op1, op2, vl); /* expected-error {{builtin requires: v}} */ + return __riscv_vmulh_vv_i64m4(op1, op2, vl); /* expected-error {{builtin requires at least one of the following extensions: v}} */ } vint64m4_t test_vmulh_vx_i64m4(vint64m4_t op1, int64_t op2, size_t vl) { - return __riscv_vmulh_vx_i64m4(op1, op2, vl); /* expected-error {{builtin requires: v}} */ + return __riscv_vmulh_vx_i64m4(op1, op2, vl); /* expected-error {{builtin requires at least one of the following extensions: v}} */ } vint64m8_t test_vmulh_vv_i64m8(vint64m8_t op1, vint64m8_t op2, size_t vl) { - return __riscv_vmulh_vv_i64m8(op1, op2, vl); /* expected-error {{builtin requires: v}} */ + return __riscv_vmulh_vv_i64m8(op1, op2, vl); /* expected-error {{builtin requires at least one of the following extensions: v}} */ } vint64m8_t test_vmulh_vx_i64m8(vint64m8_t op1, int64_t op2, size_t vl) { - return __riscv_vmulh_vx_i64m8(op1, op2, vl); /* expected-error {{builtin requires: v}} */ + return __riscv_vmulh_vx_i64m8(op1, op2, vl); /* expected-error {{builtin requires at least one of the following extensions: v}} */ } vint64m1_t test_vmulh_vv_i64m1_m(vbool64_t mask, vint64m1_t op1, vint64m1_t op2, size_t vl) { - return __riscv_vmulh_vv_i64m1_m(mask, op1, op2, vl); /* expected-error {{builtin requires: v}} */ + return __riscv_vmulh_vv_i64m1_m(mask, op1, op2, vl); /* expected-error {{builtin requires at least one of the following extensions: v}} */ } vint64m1_t test_vmulh_vx_i64m1_m(vbool64_t mask, vint64m1_t op1, int64_t op2, size_t vl) { - return __riscv_vmulh_vx_i64m1_m(mask, op1, op2, vl); /* expected-error {{builtin requires: v}} */ + return __riscv_vmulh_vx_i64m1_m(mask, op1, op2, vl); /* expected-error {{builtin requires at least one of the following extensions: v}} */ } vint64m2_t test_vmulh_vv_i64m2_m(vbool32_t mask, vint64m2_t op1, vint64m2_t op2, size_t vl) { - return __riscv_vmulh_vv_i64m2_m(mask, op1, op2, vl); /* expected-error {{builtin requires: v}} */ + return __riscv_vmulh_vv_i64m2_m(mask, op1, op2, vl); /* expected-error {{builtin requires at least one of the following extensions: v}} */ } vint64m2_t test_vmulh_vx_i64m2_m(vbool32_t mask, vint64m2_t op1, int64_t op2, size_t vl) { - return __riscv_vmulh_vx_i64m2_m(mask, op1, op2, vl); /* expected-error {{builtin requires: v}} */ + return __riscv_vmulh_vx_i64m2_m(mask, op1, op2, vl); /* expected-error {{builtin requires at least one of the following extensions: v}} */ } vint64m4_t test_vmulh_vv_i64m4_m(vbool16_t mask, vint64m4_t op1, vint64m4_t op2, size_t vl) { - return __riscv_vmulh_vv_i64m4_m(mask, op1, op2, vl); /* expected-error {{builtin requires: v}} */ + return __riscv_vmulh_vv_i64m4_m(mask, op1, op2, vl); /* expected-error {{builtin requires at least one of the following extensions: v}} */ } vint64m4_t test_vmulh_vx_i64m4_m(vbool16_t mask, vint64m4_t op1, int64_t op2, size_t vl) { - return __riscv_vmulh_vx_i64m4_m(mask, op1, op2, vl); /* expected-error {{builtin requires: v}} */ + return __riscv_vmulh_vx_i64m4_m(mask, op1, op2, vl); /* expected-error {{builtin requires at least one of the following extensions: v}} */ } vint64m8_t test_vmulh_vv_i64m8_m(vbool8_t mask, vint64m8_t op1, vint64m8_t op2, size_t vl) { - return __riscv_vmulh_vv_i64m8_m(mask, op1, op2, vl); /* expected-error {{builtin requires: v}} */ + return __riscv_vmulh_vv_i64m8_m(mask, op1, op2, vl); /* expected-error {{builtin requires at least one of the following extensions: v}} */ } vint64m8_t test_vmulh_vx_i64m8_m(vbool8_t mask, vint64m8_t op1, int64_t op2, size_t vl) { - return __riscv_vmulh_vx_i64m8_m(mask, op1, op2, vl); /* expected-error {{builtin requires: v}} */ + return __riscv_vmulh_vx_i64m8_m(mask, op1, op2, vl); /* expected-error {{builtin requires at least one of the following extensions: v}} */ } vuint64m1_t test_vmulhu_vv_u64m1(vuint64m1_t op1, vuint64m1_t op2, size_t vl) { - return __riscv_vmulhu_vv_u64m1(op1, op2, vl); /* expected-error {{builtin requires: v}} */ + return __riscv_vmulhu_vv_u64m1(op1, op2, vl); /* expected-error {{builtin requires at least one of the following extensions: v}} */ } vuint64m1_t test_vmulhu_vx_u64m1(vuint64m1_t op1, uint64_t op2, size_t vl) { - return __riscv_vmulhu_vx_u64m1(op1, op2, vl); /* expected-error {{builtin requires: v}} */ + return __riscv_vmulhu_vx_u64m1(op1, op2, vl); /* expected-error {{builtin requires at least one of the following extensions: v}} */ } vuint64m2_t test_vmulhu_vv_u64m2(vuint64m2_t op1, vuint64m2_t op2, size_t vl) { - return __riscv_vmulhu_vv_u64m2(op1, op2, vl); /* expected-error {{builtin requires: v}} */ + return __riscv_vmulhu_vv_u64m2(op1, op2, vl); /* expected-error {{builtin requires at least one of the following extensions: v}} */ } vuint64m2_t test_vmulhu_vx_u64m2(vuint64m2_t op1, uint64_t op2, size_t vl) { - return __riscv_vmulhu_vx_u64m2(op1, op2, vl); /* expected-error {{builtin requires: v}} */ + return __riscv_vmulhu_vx_u64m2(op1, op2, vl); /* expected-error {{builtin requires at least one of the following extensions: v}} */ } vuint64m4_t test_vmulhu_vv_u64m4(vuint64m4_t op1, vuint64m4_t op2, size_t vl) { - return __riscv_vmulhu_vv_u64m4(op1, op2, vl); /* expected-error {{builtin requires: v}} */ + return __riscv_vmulhu_vv_u64m4(op1, op2, vl); /* expected-error {{builtin requires at least one of the following extensions: v}} */ } vuint64m4_t test_vmulhu_vx_u64m4(vuint64m4_t op1, uint64_t op2, size_t vl) { - return __riscv_vmulhu_vx_u64m4(op1, op2, vl); /* expected-error {{builtin requires: v}} */ + return __riscv_vmulhu_vx_u64m4(op1, op2, vl); /* expected-error {{builtin requires at least one of the following extensions: v}} */ } vuint64m8_t test_vmulhu_vv_u64m8(vuint64m8_t op1, vuint64m8_t op2, size_t vl) { - return __riscv_vmulhu_vv_u64m8(op1, op2, vl); /* expected-error {{builtin requires: v}} */ + return __riscv_vmulhu_vv_u64m8(op1, op2, vl); /* expected-error {{builtin requires at least one of the following extensions: v}} */ } vuint64m8_t test_vmulhu_vx_u64m8(vuint64m8_t op1, uint64_t op2, size_t vl) { - return __riscv_vmulhu_vx_u64m8(op1, op2, vl); /* expected-error {{builtin requires: v}} */ + return __riscv_vmulhu_vx_u64m8(op1, op2, vl); /* expected-error {{builtin requires at least one of the following extensions: v}} */ } vuint64m1_t test_vmulhu_vv_u64m1_m(vbool64_t mask, vuint64m1_t op1, vuint64m1_t op2, size_t vl) { - return __riscv_vmulhu_vv_u64m1_m(mask, op1, op2, vl); /* expected-error {{builtin requires: v}} */ + return __riscv_vmulhu_vv_u64m1_m(mask, op1, op2, vl); /* expected-error {{builtin requires at least one of the following extensions: v}} */ } vuint64m1_t test_vmulhu_vx_u64m1_m(vbool64_t mask, vuint64m1_t op1, uint64_t op2, size_t vl) { - return __riscv_vmulhu_vx_u64m1_m(mask, op1, op2, vl); /* expected-error {{builtin requires: v}} */ + return __riscv_vmulhu_vx_u64m1_m(mask, op1, op2, vl); /* expected-error {{builtin requires at least one of the following extensions: v}} */ } vuint64m2_t test_vmulhu_vv_u64m2_m(vbool32_t mask, vuint64m2_t op1, vuint64m2_t op2, size_t vl) { - return __riscv_vmulhu_vv_u64m2_m(mask, op1, op2, vl); /* expected-error {{builtin requires: v}} */ + return __riscv_vmulhu_vv_u64m2_m(mask, op1, op2, vl); /* expected-error {{builtin requires at least one of the following extensions: v}} */ } vuint64m2_t test_vmulhu_vx_u64m2_m(vbool32_t mask, vuint64m2_t op1, uint64_t op2, size_t vl) { - return __riscv_vmulhu_vx_u64m2_m(mask, op1, op2, vl); /* expected-error {{builtin requires: v}} */ + return __riscv_vmulhu_vx_u64m2_m(mask, op1, op2, vl); /* expected-error {{builtin requires at least one of the following extensions: v}} */ } vuint64m4_t test_vmulhu_vv_u64m4_m(vbool16_t mask, vuint64m4_t op1, vuint64m4_t op2, size_t vl) { - return __riscv_vmulhu_vv_u64m4_m(mask, op1, op2, vl); /* expected-error {{builtin requires: v}} */ + return __riscv_vmulhu_vv_u64m4_m(mask, op1, op2, vl); /* expected-error {{builtin requires at least one of the following extensions: v}} */ } vuint64m4_t test_vmulhu_vx_u64m4_m(vbool16_t mask, vuint64m4_t op1, uint64_t op2, size_t vl) { - return __riscv_vmulhu_vx_u64m4_m(mask, op1, op2, vl); /* expected-error {{builtin requires: v}} */ + return __riscv_vmulhu_vx_u64m4_m(mask, op1, op2, vl); /* expected-error {{builtin requires at least one of the following extensions: v}} */ } vuint64m8_t test_vmulhu_vv_u64m8_m(vbool8_t mask, vuint64m8_t op1, vuint64m8_t op2, size_t vl) { - return __riscv_vmulhu_vv_u64m8_m(mask, op1, op2, vl); /* expected-error {{builtin requires: v}} */ + return __riscv_vmulhu_vv_u64m8_m(mask, op1, op2, vl); /* expected-error {{builtin requires at least one of the following extensions: v}} */ } vuint64m8_t test_vmulhu_vx_u64m8_m(vbool8_t mask, vuint64m8_t op1, uint64_t op2, size_t vl) { - return __riscv_vmulhu_vx_u64m8_m(mask, op1, op2, vl); /* expected-error {{builtin requires: v}} */ + return __riscv_vmulhu_vx_u64m8_m(mask, op1, op2, vl); /* expected-error {{builtin requires at least one of the following extensions: v}} */ } vint64m1_t test_vmulhsu_vv_i64m1(vint64m1_t op1, vuint64m1_t op2, size_t vl) { - return __riscv_vmulhsu_vv_i64m1(op1, op2, vl); /* expected-error {{builtin requires: v}} */ + return __riscv_vmulhsu_vv_i64m1(op1, op2, vl); /* expected-error {{builtin requires at least one of the following extensions: v}} */ } vint64m1_t test_vmulhsu_vx_i64m1(vint64m1_t op1, uint64_t op2, size_t vl) { - return __riscv_vmulhsu_vx_i64m1(op1, op2, vl); /* expected-error {{builtin requires: v}} */ + return __riscv_vmulhsu_vx_i64m1(op1, op2, vl); /* expected-error {{builtin requires at least one of the following extensions: v}} */ } vint64m2_t test_vmulhsu_vv_i64m2(vint64m2_t op1, vuint64m2_t op2, size_t vl) { - return __riscv_vmulhsu_vv_i64m2(op1, op2, vl); /* expected-error {{builtin requires: v}} */ + return __riscv_vmulhsu_vv_i64m2(op1, op2, vl); /* expected-error {{builtin requires at least one of the following extensions: v}} */ } vint64m2_t test_vmulhsu_vx_i64m2(vint64m2_t op1, uint64_t op2, size_t vl) { - return __riscv_vmulhsu_vx_i64m2(op1, op2, vl); /* expected-error {{builtin requires: v}} */ + return __riscv_vmulhsu_vx_i64m2(op1, op2, vl); /* expected-error {{builtin requires at least one of the following extensions: v}} */ } vint64m4_t test_vmulhsu_vv_i64m4(vint64m4_t op1, vuint64m4_t op2, size_t vl) { - return __riscv_vmulhsu_vv_i64m4(op1, op2, vl); /* expected-error {{builtin requires: v}} */ + return __riscv_vmulhsu_vv_i64m4(op1, op2, vl); /* expected-error {{builtin requires at least one of the following extensions: v}} */ } vint64m4_t test_vmulhsu_vx_i64m4(vint64m4_t op1, uint64_t op2, size_t vl) { - return __riscv_vmulhsu_vx_i64m4(op1, op2, vl); /* expected-error {{builtin requires: v}} */ + return __riscv_vmulhsu_vx_i64m4(op1, op2, vl); /* expected-error {{builtin requires at least one of the following extensions: v}} */ } vint64m8_t test_vmulhsu_vv_i64m8(vint64m8_t op1, vuint64m8_t op2, size_t vl) { - return __riscv_vmulhsu_vv_i64m8(op1, op2, vl); /* expected-error {{builtin requires: v}} */ + return __riscv_vmulhsu_vv_i64m8(op1, op2, vl); /* expected-error {{builtin requires at least one of the following extensions: v}} */ } vint64m8_t test_vmulhsu_vx_i64m8(vint64m8_t op1, uint64_t op2, size_t vl) { - return __riscv_vmulhsu_vx_i64m8(op1, op2, vl); /* expected-error {{builtin requires: v}} */ + return __riscv_vmulhsu_vx_i64m8(op1, op2, vl); /* expected-error {{builtin requires at least one of the following extensions: v}} */ } vint64m1_t test_vmulhsu_vv_i64m1_m(vbool64_t mask, vint64m1_t op1, vuint64m1_t op2, size_t vl) { - return __riscv_vmulhsu_vv_i64m1_m(mask, op1, op2, vl); /* expected-error {{builtin requires: v}} */ + return __riscv_vmulhsu_vv_i64m1_m(mask, op1, op2, vl); /* expected-error {{builtin requires at least one of the following extensions: v}} */ } vint64m1_t test_vmulhsu_vx_i64m1_m(vbool64_t mask, vint64m1_t op1, uint64_t op2, size_t vl) { - return __riscv_vmulhsu_vx_i64m1_m(mask, op1, op2, vl); /* expected-error {{builtin requires: v}} */ + return __riscv_vmulhsu_vx_i64m1_m(mask, op1, op2, vl); /* expected-error {{builtin requires at least one of the following extensions: v}} */ } vint64m2_t test_vmulhsu_vv_i64m2_m(vbool32_t mask, vint64m2_t op1, vuint64m2_t op2, size_t vl) { - return __riscv_vmulhsu_vv_i64m2_m(mask, op1, op2, vl); /* expected-error {{builtin requires: v}} */ + return __riscv_vmulhsu_vv_i64m2_m(mask, op1, op2, vl); /* expected-error {{builtin requires at least one of the following extensions: v}} */ } vint64m2_t test_vmulhsu_vx_i64m2_m(vbool32_t mask, vint64m2_t op1, uint64_t op2, size_t vl) { - return __riscv_vmulhsu_vx_i64m2_m(mask, op1, op2, vl); /* expected-error {{builtin requires: v}} */ + return __riscv_vmulhsu_vx_i64m2_m(mask, op1, op2, vl); /* expected-error {{builtin requires at least one of the following extensions: v}} */ } vint64m4_t test_vmulhsu_vv_i64m4_m(vbool16_t mask, vint64m4_t op1, vuint64m4_t op2, size_t vl) { - return __riscv_vmulhsu_vv_i64m4_m(mask, op1, op2, vl); /* expected-error {{builtin requires: v}} */ + return __riscv_vmulhsu_vv_i64m4_m(mask, op1, op2, vl); /* expected-error {{builtin requires at least one of the following extensions: v}} */ } vint64m4_t test_vmulhsu_vx_i64m4_m(vbool16_t mask, vint64m4_t op1, uint64_t op2, size_t vl) { - return __riscv_vmulhsu_vx_i64m4_m(mask, op1, op2, vl); /* expected-error {{builtin requires: v}} */ + return __riscv_vmulhsu_vx_i64m4_m(mask, op1, op2, vl); /* expected-error {{builtin requires at least one of the following extensions: v}} */ } vint64m8_t test_vmulhsu_vv_i64m8_m(vbool8_t mask, vint64m8_t op1, vuint64m8_t op2, size_t vl) { - return __riscv_vmulhsu_vv_i64m8_m(mask, op1, op2, vl); /* expected-error {{builtin requires: v}} */ + return __riscv_vmulhsu_vv_i64m8_m(mask, op1, op2, vl); /* expected-error {{builtin requires at least one of the following extensions: v}} */ } vint64m8_t test_vmulhsu_vx_i64m8_m(vbool8_t mask, vint64m8_t op1, uint64_t op2, size_t vl) { - return __riscv_vmulhsu_vx_i64m8_m(mask, op1, op2, vl); /* expected-error {{builtin requires: v}} */ + return __riscv_vmulhsu_vx_i64m8_m(mask, op1, op2, vl); /* expected-error {{builtin requires at least one of the following extensions: v}} */ } diff --git a/clang/test/Sema/scoped-atomic-ops.c b/clang/test/Sema/scoped-atomic-ops.c new file mode 100644 index 0000000000000000000000000000000000000000..59e638c646664c309998611d307f941f46db4c64 --- /dev/null +++ b/clang/test/Sema/scoped-atomic-ops.c @@ -0,0 +1,101 @@ +// RUN: %clang_cc1 -x c -triple=amdgcn-amd-amdhsa -verify -fsyntax-only %s +// RUN: %clang_cc1 -x c -triple=x86_64-pc-linux-gnu -verify -fsyntax-only %s + +int fi1a(int *i) { + int v; + __scoped_atomic_load(i, &v, __ATOMIC_RELAXED); // expected-error {{too few arguments to function call, expected 4, have 3}} + __scoped_atomic_load(i, &v, __ATOMIC_RELAXED, 42); // expected-error {{synchronization scope argument to atomic operation is invalid}} + __scoped_atomic_load(i, &v, __ATOMIC_RELAXED, __MEMORY_SCOPE_SYSTEM); + return v; +} + +int fi1b(int *i) { + *i = __scoped_atomic_load_n(i, __ATOMIC_RELAXED); // expected-error {{too few arguments to function call, expected 3, have 2}} + *i = __scoped_atomic_load_n(i, __ATOMIC_RELAXED, 42); // expected-error {{synchronization scope argument to atomic operation is invalid}} + *i = __scoped_atomic_load_n(i, __ATOMIC_RELAXED, __MEMORY_SCOPE_SYSTEM); + return *i; +} + +int fi2a(int *i) { + int v; + __scoped_atomic_store(i, &v, __ATOMIC_RELAXED); // expected-error {{too few arguments to function call, expected 4, have 3}} + __scoped_atomic_store(i, &v, __ATOMIC_RELAXED, 42); // expected-error {{synchronization scope argument to atomic operation is invalid}} + __scoped_atomic_store(i, &v, __ATOMIC_RELAXED, __MEMORY_SCOPE_SYSTEM); + return v; +} + +void fi2b(int *i) { + __scoped_atomic_store_n(i, 1, __ATOMIC_RELAXED); // expected-error {{too few arguments to function call, expected 4, have 3}} + __scoped_atomic_store_n(i, 1, __ATOMIC_RELAXED, 42); // expected-error {{synchronization scope argument to atomic operation is invalid}} + __scoped_atomic_store_n(i, 1, __ATOMIC_RELAXED, __MEMORY_SCOPE_SYSTEM); +} + +void fi3a(int *a, int *b, int *c, int *d, int *e, int *f, int *g, int *h) { + *a = __scoped_atomic_fetch_add(a, 1, __ATOMIC_RELAXED, __MEMORY_SCOPE_SYSTEM); + *b = __scoped_atomic_fetch_sub(b, 1, __ATOMIC_RELAXED, __MEMORY_SCOPE_SYSTEM); + *c = __scoped_atomic_fetch_and(c, 1, __ATOMIC_RELAXED, __MEMORY_SCOPE_SYSTEM); + *d = __scoped_atomic_fetch_or(d, 1, __ATOMIC_RELAXED, __MEMORY_SCOPE_SYSTEM); + *e = __scoped_atomic_fetch_xor(e, 1, __ATOMIC_RELAXED, __MEMORY_SCOPE_SYSTEM); + *f = __scoped_atomic_fetch_nand(f, 1, __ATOMIC_RELAXED, __MEMORY_SCOPE_SYSTEM); + *g = __scoped_atomic_fetch_min(g, 1, __ATOMIC_RELAXED, __MEMORY_SCOPE_SYSTEM); + *h = __scoped_atomic_fetch_max(h, 1, __ATOMIC_RELAXED, __MEMORY_SCOPE_SYSTEM); +} + +void fi3b(int *a, int *b, int *c, int *d, int *e, int *f, int *g, int *h) { + *a = __scoped_atomic_fetch_add(1, 1, __ATOMIC_RELAXED, __MEMORY_SCOPE_SYSTEM); // expected-error {{address argument to atomic builtin must be a pointer ('int' invalid)}} + *b = __scoped_atomic_fetch_sub(1, 1, __ATOMIC_RELAXED, __MEMORY_SCOPE_SYSTEM); // expected-error {{address argument to atomic builtin must be a pointer ('int' invalid)}} + *c = __scoped_atomic_fetch_and(1, 1, __ATOMIC_RELAXED, __MEMORY_SCOPE_SYSTEM); // expected-error {{address argument to atomic builtin must be a pointer ('int' invalid)}} + *d = __scoped_atomic_fetch_or(1, 1, __ATOMIC_RELAXED, __MEMORY_SCOPE_SYSTEM); // expected-error {{address argument to atomic builtin must be a pointer ('int' invalid)}} + *e = __scoped_atomic_fetch_xor(1, 1, __ATOMIC_RELAXED, __MEMORY_SCOPE_SYSTEM); // expected-error {{address argument to atomic builtin must be a pointer ('int' invalid)}} + *f = __scoped_atomic_fetch_nand(1, 1, __ATOMIC_RELAXED, __MEMORY_SCOPE_SYSTEM); // expected-error {{address argument to atomic builtin must be a pointer ('int' invalid)}} + *g = __scoped_atomic_fetch_min(1, 1, __ATOMIC_RELAXED, __MEMORY_SCOPE_SYSTEM); // expected-error {{address argument to atomic builtin must be a pointer ('int' invalid)}} + *h = __scoped_atomic_fetch_max(1, 1, __ATOMIC_RELAXED, __MEMORY_SCOPE_SYSTEM); // expected-error {{address argument to atomic builtin must be a pointer ('int' invalid)}} +} + +void fi3c(int *a, int *b, int *c, int *d, int *e, int *f, int *g, int *h) { + *a = __scoped_atomic_fetch_add(a, 1, __ATOMIC_RELAXED); // expected-error {{too few arguments to function call, expected 4, have 3}} + *b = __scoped_atomic_fetch_sub(b, 1, __ATOMIC_RELAXED); // expected-error {{too few arguments to function call, expected 4, have 3}} + *c = __scoped_atomic_fetch_and(c, 1, __ATOMIC_RELAXED); // expected-error {{too few arguments to function call, expected 4, have 3}} + *d = __scoped_atomic_fetch_or(d, 1, __ATOMIC_RELAXED); // expected-error {{too few arguments to function call, expected 4, have 3}} + *e = __scoped_atomic_fetch_xor(e, 1, __ATOMIC_RELAXED); // expected-error {{too few arguments to function call, expected 4, have 3}} + *f = __scoped_atomic_fetch_nand(f, 1, __ATOMIC_RELAXED); // expected-error {{too few arguments to function call, expected 4, have 3}} + *g = __scoped_atomic_fetch_min(g, 1, __ATOMIC_RELAXED); // expected-error {{too few arguments to function call, expected 4, have 3}} + *h = __scoped_atomic_fetch_max(h, 1, __ATOMIC_RELAXED); // expected-error {{too few arguments to function call, expected 4, have 3}} +} + +void fi3d(int *a, int *b, int *c, int *d, int *e, int *f, int *g, int *h) { + *a = __scoped_atomic_fetch_add(a, 1, __ATOMIC_RELAXED, 42); // expected-error {{synchronization scope argument to atomic operation is invalid}} + *b = __scoped_atomic_fetch_sub(b, 1, __ATOMIC_RELAXED, 42); // expected-error {{synchronization scope argument to atomic operation is invalid}} + *c = __scoped_atomic_fetch_and(c, 1, __ATOMIC_RELAXED, 42); // expected-error {{synchronization scope argument to atomic operation is invalid}} + *d = __scoped_atomic_fetch_or(d, 1, __ATOMIC_RELAXED, 42); // expected-error {{synchronization scope argument to atomic operation is invalid}} + *e = __scoped_atomic_fetch_xor(e, 1, __ATOMIC_RELAXED, 42); // expected-error {{synchronization scope argument to atomic operation is invalid}} + *f = __scoped_atomic_fetch_nand(f, 1, __ATOMIC_RELAXED, 42); // expected-error {{synchronization scope argument to atomic operation is invalid}} + *g = __scoped_atomic_fetch_min(g, 1, __ATOMIC_RELAXED, 42); // expected-error {{synchronization scope argument to atomic operation is invalid}} + *h = __scoped_atomic_fetch_max(h, 1, __ATOMIC_RELAXED, 42); // expected-error {{synchronization scope argument to atomic operation is invalid}} +} + +int fi4a(int *i) { + int cmp = 0; + int desired = 1; + return __scoped_atomic_compare_exchange(i, &cmp, &desired, 0, + __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE, + __MEMORY_SCOPE_SYSTEM); +} + +int fi5a(int *i) { + int cmp = 0; + return __scoped_atomic_compare_exchange_n(i, &cmp, 1, 1, __ATOMIC_ACQUIRE, + __ATOMIC_ACQUIRE, + __MEMORY_SCOPE_SYSTEM); +} + +int fi6a(int *c, int *d) { + int ret; + __scoped_atomic_exchange(c, d, &ret, __ATOMIC_RELAXED, __MEMORY_SCOPE_SYSTEM); + return ret; +} + +int fi7a(_Bool *c) { + return __scoped_atomic_exchange_n(c, 1, __ATOMIC_RELAXED, + __MEMORY_SCOPE_SYSTEM); +} diff --git a/clang/test/Sema/switch-default.c b/clang/test/Sema/switch-default.c new file mode 100644 index 0000000000000000000000000000000000000000..854b561b37c48e4e2d12ec7737a8509fa742ba19 --- /dev/null +++ b/clang/test/Sema/switch-default.c @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -Wswitch-default %s + +int f1(int a) { + switch (a) { // expected-warning {{'switch' missing 'default' label}} + case 1: a++; break; + case 2: a += 2; break; + } + return a; +} + +int f2(int a) { + switch (a) { // no-warning + default: + ; + } + return a; +} diff --git a/clang/test/SemaCXX/builtin-dump-struct.cpp b/clang/test/SemaCXX/builtin-dump-struct.cpp index b3d2a2d808ce26744c8c28963372609d6d408295..91ffa7c8c05bdeefbb6856d63d581207acb6dd01 100644 --- a/clang/test/SemaCXX/builtin-dump-struct.cpp +++ b/clang/test/SemaCXX/builtin-dump-struct.cpp @@ -149,7 +149,15 @@ B { } )"[1]); +class Incomplete; // #incomplete-type + +template +class Class { + T value = {}; +}; + void errors(B b) { + ConstexprString cs; __builtin_dump_struct(); // expected-error {{too few arguments to function call, expected 2, have 0}} __builtin_dump_struct(1); // expected-error {{too few arguments to function call, expected 2, have 1}} __builtin_dump_struct(1, 2); // expected-error {{expected pointer to struct as 1st argument to '__builtin_dump_struct', found 'int'}} @@ -157,6 +165,10 @@ void errors(B b) { __builtin_dump_struct(&b, Format, 0); // expected-error {{no matching function for call to 'Format'}} // expected-note@-1 {{in call to printing function with arguments '(0, "%s", "B")' while dumping struct}} // expected-note@#Format {{no known conversion from 'int' to 'ConstexprString &' for 1st argument}} + __builtin_dump_struct((Incomplete *)nullptr, Format, cs); // expected-error {{incomplete type 'Incomplete' where a complete type is required}} + // expected-note@#incomplete-type {{forward declaration of 'Incomplete'}} + // Ensure the Class gets instantiated; otherwise crash happens. + __builtin_dump_struct((Class *)nullptr, Format, cs); } #endif diff --git a/clang/test/SemaCXX/coro-lifetimebound.cpp b/clang/test/SemaCXX/coro-lifetimebound.cpp index d3e2d673ebb3c0d4ff949a48be265a40aeeb42df..b4dc029a13984846f54447eaed9ef327059f7e3c 100644 --- a/clang/test/SemaCXX/coro-lifetimebound.cpp +++ b/clang/test/SemaCXX/coro-lifetimebound.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple x86_64-apple-darwin9 %s -std=c++20 -fsyntax-only -verify -Wall -Wextra -Wno-error=unreachable-code -Wno-unused +// RUN: %clang_cc1 -triple x86_64-apple-darwin9 %s -std=c++20 -fsyntax-only -verify -Wall -Wextra -Wno-error=unreachable-code -Wno-unused -Wno-c++23-lambda-attributes #include "Inputs/std-coroutine.h" @@ -64,14 +64,8 @@ Co bar_coro(const int &b, int c) { : bar_coro(0, 1); // expected-warning {{returning address of local temporary object}} } -#define CORO_WRAPPER \ - _Pragma("clang diagnostic push") \ - _Pragma("clang diagnostic ignored \"-Wc++23-extensions\"") \ - [[clang::coro_wrapper]] \ - _Pragma("clang diagnostic pop") - void lambdas() { - auto unsafe_lambda = [] CORO_WRAPPER (int b) { + auto unsafe_lambda = [] [[clang::coro_wrapper]] (int b) { return foo_coro(b); // expected-warning {{address of stack memory associated with parameter}} }; auto coro_lambda = [] (const int&) -> Co { diff --git a/clang/test/SemaCXX/coro-return-type-and-wrapper.cpp b/clang/test/SemaCXX/coro-return-type-and-wrapper.cpp index 5f8076f1c782ac3ca7213580104d81aac00179a3..ac49e03ba9d90ad2d670fbe5c72f11f2443847c5 100644 --- a/clang/test/SemaCXX/coro-return-type-and-wrapper.cpp +++ b/clang/test/SemaCXX/coro-return-type-and-wrapper.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple x86_64-apple-darwin9 %s -std=c++20 -fsyntax-only -verify -Wall -Wextra +// RUN: %clang_cc1 -triple x86_64-apple-darwin9 %s -std=c++20 -fsyntax-only -verify -Wall -Wextra -Wno-c++23-lambda-attributes #include "Inputs/std-coroutine.h" using std::suspend_always; @@ -45,11 +45,6 @@ Co non_marked_wrapper(int b) { return foo_coro(b); } } // namespace using_decl namespace lambdas { -#define CORO_WRAPPER \ - _Pragma("clang diagnostic push") \ - _Pragma("clang diagnostic ignored \"-Wc++23-extensions\"") \ - [[clang::coro_wrapper]] \ - _Pragma("clang diagnostic pop") void foo() { auto coro_lambda = []() -> Gen { @@ -59,7 +54,7 @@ void foo() { auto not_allowed_wrapper = []() -> Gen { return foo_coro(1); }; - auto allowed_wrapper = [] CORO_WRAPPER() -> Gen { + auto allowed_wrapper = [] [[clang::coro_wrapper]] () -> Gen { return foo_coro(1); }; } diff --git a/clang/test/SemaCXX/cxx1z-copy-omission.cpp b/clang/test/SemaCXX/cxx1z-copy-omission.cpp index a850cf6143cd48057f0a0eaaed05eb332af9e52a..f46a17af833867737a297c0d7d4a08bf27eb0179 100644 --- a/clang/test/SemaCXX/cxx1z-copy-omission.cpp +++ b/clang/test/SemaCXX/cxx1z-copy-omission.cpp @@ -171,3 +171,30 @@ namespace CtorTemplateBeatsNonTemplateConversionFn { Foo f(Derived d) { return d; } // expected-error {{invokes a deleted function}} Foo g(Derived d) { return Foo(d); } // ok, calls constructor } + +// Make sure we don't consider conversion functions for guaranteed copy elision +namespace GH39319 { +struct A { + A(); + A(const A&) = delete; // expected-note {{'A' has been explicitly marked deleted here}} +}; +struct B { + operator A(); +} C; +A::A() : A(C) {} // expected-error {{call to deleted constructor of}} + +struct A2 { + struct B2 { + operator A2(); + }; + A2() : A2(B2()) {} // expected-error {{call to deleted constructor of}} + A2(const A2&) = delete; // expected-note {{'A2' has been explicitly marked deleted here}} +}; + +template +class B3 : A3 { + template()> // expected-warning 2{{use of function template name with no prior declaration in function call with explicit}} + B3(); +}; B3(); // expected-error {{deduction guide declaration without trailing return type}} \ + // expected-note {{while building implicit deduction guide first needed here}} +} diff --git a/clang/test/SemaCXX/friend.cpp b/clang/test/SemaCXX/friend.cpp index 367d6a6c1807c92049a5ae9d85154635a8e89de8..53e6bbfcf42a8ed8bc898bc4a7674c8fbb70ae4b 100644 --- a/clang/test/SemaCXX/friend.cpp +++ b/clang/test/SemaCXX/friend.cpp @@ -162,7 +162,7 @@ namespace test9 { class C { }; struct A { - friend void C::f(int, int, int) {} // expected-error {{friend function definition cannot be qualified with 'C::'}} + friend void C::f(int, int, int) {} // expected-error {{friend declaration of 'f' does not match any declaration in 'test9::C'}} }; } diff --git a/clang/test/SemaCXX/ms-constexpr-invalid.cpp b/clang/test/SemaCXX/ms-constexpr-invalid.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e5bec0c7119b02871681e5a8465ce7815689af46 --- /dev/null +++ b/clang/test/SemaCXX/ms-constexpr-invalid.cpp @@ -0,0 +1,52 @@ +// RUN: %clang_cc1 -fms-compatibility -fms-compatibility-version=19.33 -std=c++20 -verify %s +// RUN: %clang_cc1 -fms-compatibility -fms-compatibility-version=19.33 -std=c++17 -verify %s + +// Check explicitly invalid code + +void runtime() {} // expected-note {{declared here}} + +[[msvc::constexpr]] void f0() { runtime(); } // expected-error {{constexpr function never produces a constant expression}} \ + // expected-note {{non-constexpr function 'runtime' cannot be used in a constant expression}} +[[msvc::constexpr]] constexpr void f1() {} // expected-error {{attribute 'msvc::constexpr' cannot be applied to the constexpr function 'f1'}} +#if __cplusplus >= 202202L +[[msvc::constexpr]] consteval void f2() {} // expected-error {{attribute 'msvc::constexpr' cannot be applied to the consteval function 'f1'}} +#endif + +struct B1 {}; +struct D1 : virtual B1 { // expected-note {{virtual base class declared here}} + [[msvc::constexpr]] D1() {} // expected-error {{constexpr constructor not allowed in struct with virtual base class}} +}; + +struct [[msvc::constexpr]] S2{}; // expected-error {{'constexpr' attribute only applies to functions and return statements}} + +// Check invalid code mixed with valid code + +[[msvc::constexpr]] int f4(int x) { return x > 1 ? 1 + f4(x / 2) : 0; } // expected-note {{non-constexpr function 'f4' cannot be used in a constant expression}} \ + // expected-note {{declared here}} \ + // expected-note {{declared here}} \ + // expected-note {{declared here}} +constexpr bool f5() { [[msvc::constexpr]] return f4(32) == 5; } // expected-note {{in call to 'f4(32)'}} +static_assert(f5()); // expected-error {{static assertion expression is not an integral constant expression}} \ + // expected-note {{in call to 'f5()'}} + +int f6(int x) { [[msvc::constexpr]] return x > 1 ? 1 + f6(x / 2) : 0; } // expected-note {{declared here}} \ + // expected-note {{declared here}} +constexpr bool f7() { [[msvc::constexpr]] return f6(32) == 5; } // expected-error {{constexpr function never produces a constant expression}} \ + // expected-note {{non-constexpr function 'f6' cannot be used in a constant expression}} \ + // expected-note {{non-constexpr function 'f6' cannot be used in a constant expression}} +static_assert(f7()); // expected-error {{static assertion expression is not an integral constant expression}} \ + // expected-note {{in call to 'f7()'}} + +constexpr bool f8() { // expected-error {{constexpr function never produces a constant expression}} + [[msvc::constexpr]] f4(32); // expected-error {{'constexpr' attribute only applies to functions and return statements}} \ + // expected-note {{non-constexpr function 'f4' cannot be used in a constant expression}} \ + // expected-note {{non-constexpr function 'f4' cannot be used in a constant expression}} + [[msvc::constexpr]] int i5 = f4(32); // expected-error {{'constexpr' attribute only applies to functions and return statements}} + return i5 == 5; +} +static_assert(f8()); // expected-error {{static assertion expression is not an integral constant expression}} \ + // expected-note {{in call to 'f8()'}} + +#if __cplusplus == 201702L +struct S1 { [[msvc::constexpr]] virtual bool vm() const { return true; } }; // expected-error {{attribute 'msvc::constexpr' ignored, it only applies to function definitions and return statements}} +#endif diff --git a/clang/test/SemaCXX/ms-constexpr-new.cpp b/clang/test/SemaCXX/ms-constexpr-new.cpp new file mode 100644 index 0000000000000000000000000000000000000000..30567740b2ecbbe383f4ce4c0f70d6f9f29148b7 --- /dev/null +++ b/clang/test/SemaCXX/ms-constexpr-new.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -fms-compatibility -fms-compatibility-version=19.33 -std=c++20 -verify=supported %s +// RUN: %clang_cc1 -fms-compatibility -fms-compatibility-version=19.32 -std=c++20 -verify=unsupported %s +// supported-no-diagnostics + +[[nodiscard]] +[[msvc::constexpr]] // unsupported-warning {{unknown attribute 'constexpr' ignored}} +inline void* operator new(decltype(sizeof(void*)), void* p) noexcept { return p; } + +namespace std { + constexpr int* construct_at(int* p, int v) { + [[msvc::constexpr]] return ::new (p) int(v); // unsupported-warning {{unknown attribute 'constexpr' ignored}} + } +} + +constexpr bool check_construct_at() { int x; return *std::construct_at(&x, 42) == 42; } +static_assert(check_construct_at()); diff --git a/clang/test/SemaCXX/ms-constexpr.cpp b/clang/test/SemaCXX/ms-constexpr.cpp new file mode 100644 index 0000000000000000000000000000000000000000..79f71a34cb7d8485b1f95cdd34c8798bfa7e0f4b --- /dev/null +++ b/clang/test/SemaCXX/ms-constexpr.cpp @@ -0,0 +1,37 @@ +// RUN: %clang_cc1 -fms-compatibility -fms-compatibility-version=19.33 -std=c++20 -verify %s + +[[msvc::constexpr]] int log2(int x) { [[msvc::constexpr]] return x > 1 ? 1 + log2(x / 2) : 0; } +constexpr bool test_log2() { [[msvc::constexpr]] return log2(32) == 5; } +static_assert(test_log2()); + +[[msvc::constexpr]] int get_value(int x) +{ + switch (x) + { + case 42: return 1337; + default: + if (x < 0) [[msvc::constexpr]] return log2(-x); + else return x; + } +} + +constexpr bool test_complex_expr() { + [[msvc::constexpr]] return get_value(get_value(42) - 1337 + get_value(-32) - 5 + (get_value(1) ? get_value(0) : get_value(2))) == get_value(0); +} +static_assert(test_complex_expr()); + +constexpr bool get_constexpr_true() { return true; } +[[msvc::constexpr]] bool get_msconstexpr_true() { return get_constexpr_true(); } +constexpr bool test_get_msconstexpr_true() { [[msvc::constexpr]] return get_msconstexpr_true(); } +static_assert(test_get_msconstexpr_true()); + +// TODO (#72149): Add support for [[msvc::constexpr]] constructor; this code is valid for MSVC. +struct S2 { + [[msvc::constexpr]] S2() {} + [[msvc::constexpr]] bool value() { return true; } + static constexpr bool check() { [[msvc::constexpr]] return S2{}.value(); } // expected-error {{constexpr function never produces a constant expression}} \ + // expected-note {{non-literal type 'S2' cannot be used in a constant expression}} \ + // expected-note {{non-literal type 'S2' cannot be used in a constant expression}} +}; +static_assert(S2::check()); // expected-error {{static assertion expression is not an integral constant expression}} \ + // expected-note {{in call to 'check()'}} diff --git a/clang/test/SemaCXX/warn-thread-safety-analysis.cpp b/clang/test/SemaCXX/warn-thread-safety-analysis.cpp index 205cfa284f6c9c96c4db5e811050d62b5afd8666..dfb966d3b5902d6bd2564cc7bdf2772089cf552b 100644 --- a/clang/test/SemaCXX/warn-thread-safety-analysis.cpp +++ b/clang/test/SemaCXX/warn-thread-safety-analysis.cpp @@ -1702,6 +1702,8 @@ struct TestScopedLockable { bool getBool(); + bool lock2Bool(MutexLock); + void foo1() { MutexLock mulock(&mu1); a = 5; @@ -1718,6 +1720,12 @@ struct TestScopedLockable { MutexLock{&mu1}, a = 5; } + void temporary_cfg(int x) { + // test the case where a pair of temporary Ctor and Dtor is in different CFG blocks + lock2Bool(MutexLock{&mu1}) || x; + MutexLock{&mu1}; // no-warn + } + void lifetime_extension() { const MutexLock &mulock = MutexLock(&mu1); a = 5; diff --git a/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-add-assign.cpp b/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-add-assign.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5c03cc10025c684b563ee4ea43d67dd2da0f21ba --- /dev/null +++ b/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-add-assign.cpp @@ -0,0 +1,59 @@ +// RUN: %clang_cc1 -std=c++20 -Wunsafe-buffer-usage \ +// RUN: -fsafe-buffer-usage-suggestions \ +// RUN: -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s +void foo(int * , int *); + +void add_assign_test(unsigned int n, int *a, int y) { + int *p = new int[10]; + // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span p" + // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"{" + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:23-[[@LINE-3]]:23}:", 10}" + p += 2; + // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:7}:"p = p.subspan(" + // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:9-[[@LINE-2]]:9}:")" + + int *r = p; + // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span r" + // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"{" + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:13-[[@LINE-3]]:13}:", <# placeholder #>}" + while (*r != 0) { + // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:10-[[@LINE-1]]:11}:"" + // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"[0]" + r += 2; + // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:5-[[@LINE-1]]:9}:"r = r.subspan(" + // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:11-[[@LINE-2]]:11}:")" + } + + if (*p == 0) { + // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:7-[[@LINE-1]]:8}:"" + // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:9-[[@LINE-2]]:9}:"[0]" + p += n; + // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:5-[[@LINE-1]]:9}:"p = p.subspan(" + // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:11-[[@LINE-2]]:11}:")" + } + + if (*p == 1) + // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:7-[[@LINE-1]]:8}:"" + // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:9-[[@LINE-2]]:9}:"[0]" + p += 3; + // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:5-[[@LINE-1]]:9}:"p = p.subspan(" + // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:11-[[@LINE-2]]:11}:")" + + a += -9; + // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:5-[[@LINE-1]]:9}:"p = p.subspan(" + + a += y; + // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:5-[[@LINE-1]]:9}:"p = p.subspan(" +} + +int expr_test(unsigned x, int *q, int y) { + char *p = new char[8]; + // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:12}:"std::span p" + // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:13-[[@LINE-2]]:13}:"{" + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:24-[[@LINE-3]]:24}:", 8}" + p += (x + 1); + // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:7}:"p = p.subspan" + + q += (y + 7); + // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:7}:"q = q.subspan" +} diff --git a/clang/test/SemaHLSL/BuiltIns/RWBuffers.hlsl b/clang/test/SemaHLSL/BuiltIns/RWBuffers.hlsl index a9f6567aa00b8c3ed2c6246b9a3711af0799ad40..7e79ae3bf005fccef670103b4f18622195468a7b 100644 --- a/clang/test/SemaHLSL/BuiltIns/RWBuffers.hlsl +++ b/clang/test/SemaHLSL/BuiltIns/RWBuffers.hlsl @@ -5,6 +5,14 @@ typedef vector float3; RWBuffer Buffer; +// expected-error@+2 {{class template 'RWBuffer' requires template arguments}} +// expected-note@*:* {{template declaration from hidden source: template class RWBuffer final}} +RWBuffer BufferErr1; + +// expected-error@+2 {{too few template arguments for class template 'RWBuffer'}} +// expected-note@*:* {{template declaration from hidden source: template class RWBuffer final}} +RWBuffer<> BufferErr2; + [numthreads(1,1,1)] void main() { (void)Buffer.h; // expected-error {{'h' is a private member of 'hlsl::RWBuffer'}} diff --git a/clang/test/SemaHLSL/BuiltIns/vector-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/vector-errors.hlsl index d2598a57400b0451e84ce7463e3ea69b232c8b0a..6aedb9304ed9339a0f54e6aa9afba13524c91b9c 100644 --- a/clang/test/SemaHLSL/BuiltIns/vector-errors.hlsl +++ b/clang/test/SemaHLSL/BuiltIns/vector-errors.hlsl @@ -2,17 +2,16 @@ // Some bad declarations hlsl::vector ShouldWorkSomeday; // expected-error{{use of alias template 'hlsl::vector' requires template arguments}} +// expected-note@*:* {{template declaration from hidden source: template using vector = element __attribute__((ext_vector_type(element_count)))}} hlsl::vector<1> BadVec; // expected-error{{template argument for template type parameter must be a type}} -// expected-note@*:* {{template is declared here}} -// expected-note@*:* {{template parameter is declared here}} - +// expected-note@*:* {{template parameter from hidden source: class element = float}} hlsl::vector AnotherBadVec; // expected-error{{template argument for non-type template parameter must be an expression}} -// expected-note@*:* {{template parameter is declared here}} +// expected-note@*:* {{template parameter from hidden source: int element_count = 4}} hlsl::vector YABV; // expected-error{{too many template arguments for alias template 'vector'}} -// expected-note@*:* {{template is declared here}} +// expected-note@*:* {{template declaration from hidden source: template using vector = element __attribute__((ext_vector_type(element_count)))}} // This code is rejected by clang because clang puts the HLSL built-in types // into the HLSL namespace. diff --git a/clang/test/SemaTemplate/GH71595.cpp b/clang/test/SemaTemplate/GH71595.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7d34d1bf054e4bc49de6b0abb4691a4763e64126 --- /dev/null +++ b/clang/test/SemaTemplate/GH71595.cpp @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -std=c++20 -verify %s + +template +concept C = true; + +class non_temp { + template T> + friend void f(); + + non_temp(); +}; + +template T> +void f() { + auto v = non_temp(); +} + +template +class temp { + template T> + friend void g(); + + temp(); // expected-note {{implicitly declared private here}} +}; + +template> T> +void g() { + auto v = temp(); // expected-error {{calling a private constructor of class 'temp'}} +} + +void h() { + f(); + g(); // expected-note {{in instantiation of function template specialization 'g' requested here}} +} diff --git a/clang/tools/clang-format/ClangFormat.cpp b/clang/tools/clang-format/ClangFormat.cpp index 829f85b93bc73cbb1577d35137a0acaaa8ea5ef6..d2e3d8d43aef21a2f10bf094e0042138374fa633 100644 --- a/clang/tools/clang-format/ClangFormat.cpp +++ b/clang/tools/clang-format/ClangFormat.cpp @@ -398,8 +398,8 @@ class ClangFormatDiagConsumer : public DiagnosticConsumer { }; // Returns true on error. -static bool format(StringRef FileName) { - if (!OutputXML && Inplace && FileName == "-") { +static bool format(StringRef FileName, bool IsSTDIN) { + if (!OutputXML && Inplace && IsSTDIN) { errs() << "error: cannot use -i when reading from stdin.\n"; return false; } @@ -423,7 +423,7 @@ static bool format(StringRef FileName) { if (InvalidBOM) { errs() << "error: encoding with unsupported byte order mark \"" << InvalidBOM << "\" detected"; - if (FileName != "-") + if (!IsSTDIN) errs() << " in file '" << FileName << "'"; errs() << ".\n"; return true; @@ -432,7 +432,7 @@ static bool format(StringRef FileName) { std::vector Ranges; if (fillRanges(Code.get(), Ranges)) return true; - StringRef AssumedFileName = (FileName == "-") ? AssumeFileName : FileName; + StringRef AssumedFileName = IsSTDIN ? AssumeFileName : FileName; if (AssumedFileName.empty()) { llvm::errs() << "error: empty filenames are not allowed\n"; return true; @@ -544,28 +544,23 @@ static void PrintVersion(raw_ostream &OS) { } // Dump the configuration. -static int dumpConfig() { - StringRef FileName; +static int dumpConfig(bool IsSTDIN) { std::unique_ptr Code; - if (FileNames.empty()) { - // We can't read the code to detect the language if there's no - // file name, so leave Code empty here. - FileName = AssumeFileName; - } else { - // Read in the code in case the filename alone isn't enough to - // detect the language. + // We can't read the code to detect the language if there's no file name. + if (!IsSTDIN) { + // Read in the code in case the filename alone isn't enough to detect the + // language. ErrorOr> CodeOrErr = MemoryBuffer::getFileOrSTDIN(FileNames[0]); if (std::error_code EC = CodeOrErr.getError()) { llvm::errs() << EC.message() << "\n"; return 1; } - FileName = (FileNames[0] == "-") ? AssumeFileName : FileNames[0]; Code = std::move(CodeOrErr.get()); } llvm::Expected FormatStyle = - clang::format::getStyle(Style, FileName, FallbackStyle, - Code ? Code->getBuffer() : ""); + clang::format::getStyle(Style, IsSTDIN ? AssumeFileName : FileNames[0], + FallbackStyle, Code ? Code->getBuffer() : ""); if (!FormatStyle) { llvm::errs() << llvm::toString(FormatStyle.takeError()) << "\n"; return 1; @@ -596,8 +591,11 @@ int main(int argc, const char **argv) { return 0; } + if (FileNames.empty()) + FileNames.push_back("-"); + if (DumpConfig) - return dumpConfig(); + return dumpConfig(FileNames[0] == "-"); if (!Files.empty()) { std::ifstream ExternalFileOfFiles{std::string(Files)}; @@ -610,11 +608,6 @@ int main(int argc, const char **argv) { errs() << "Clang-formating " << LineNo << " files\n"; } - bool Error = false; - if (FileNames.empty()) { - Error = clang::format::format("-"); - return Error ? 1 : 0; - } if (FileNames.size() != 1 && (!Offsets.empty() || !Lengths.empty() || !LineRanges.empty())) { errs() << "error: -offset, -length and -lines can only be used for " @@ -623,12 +616,13 @@ int main(int argc, const char **argv) { } unsigned FileNo = 1; + bool Error = false; for (const auto &FileName : FileNames) { if (Verbose) { errs() << "Formatting [" << FileNo++ << "/" << FileNames.size() << "] " << FileName << "\n"; } - Error |= clang::format::format(FileName); + Error |= clang::format::format(FileName, FileName == "-"); } return Error ? 1 : 0; } diff --git a/clang/tools/clang-format/clang-format-diff.py b/clang/tools/clang-format/clang-format-diff.py index b25ee8f4337518e53ac43e54dffa82882ea9b772..0a2c24743678d0d9928f2a020942901720061372 100755 --- a/clang/tools/clang-format/clang-format-diff.py +++ b/clang/tools/clang-format/clang-format-diff.py @@ -25,7 +25,6 @@ from __future__ import absolute_import, division, print_function import argparse import difflib -import os import re import subprocess import sys @@ -37,9 +36,8 @@ else: def main(): - basename = os.path.basename(sys.argv[0]) parser = argparse.ArgumentParser( - description=__doc__.format(clang_format_diff=basename), + description=__doc__.format(clang_format_diff="%(prog)s"), formatter_class=argparse.RawDescriptionHelpFormatter, ) parser.add_argument( diff --git a/clang/tools/clang-format/git-clang-format b/clang/tools/clang-format/git-clang-format index 6e827e17b4ee291e9a8494a49cdd5afa03a623c2..d33fd478d77fd9f397c3e9394750c654c3309650 100755 --- a/clang/tools/clang-format/git-clang-format +++ b/clang/tools/clang-format/git-clang-format @@ -132,6 +132,10 @@ def main(): help='passed to clang-format'), p.add_argument('-v', '--verbose', action='count', default=0, help='print extra information') + p.add_argument('--diff_from_common_commit', action='store_true', + help=('diff from the last common commit for commits in ' + 'separate branches rather than the exact point of the ' + 'commits')) # We gather all the remaining positional arguments into 'args' since we need # to use some heuristics to determine whether or not was present. # However, to print pretty messages, we make use of metavar and help. @@ -145,16 +149,23 @@ def main(): del opts.quiet commits, files = interpret_args(opts.args, dash_dash, opts.commit) - if len(commits) > 1: + if len(commits) > 2: + die('at most two commits allowed; %d given' % len(commits)) + if len(commits) == 2: if opts.staged: die('--staged is not allowed when two commits are given') if not opts.diff: die('--diff is required when two commits are given') - else: - if len(commits) > 2: - die('at most two commits allowed; %d given' % len(commits)) - opts.binary=os.path.abspath(opts.binary) - changed_lines = compute_diff_and_extract_lines(commits, files, opts.staged) + elif opts.diff_from_common_commit: + die('--diff_from_common_commit is only allowed when two commits are given') + + if os.path.dirname(opts.binary): + opts.binary = os.path.abspath(opts.binary) + + changed_lines = compute_diff_and_extract_lines(commits, + files, + opts.staged, + opts.diff_from_common_commit) if opts.verbose >= 1: ignored_files = set(changed_lines) filter_by_extension(changed_lines, opts.extensions.lower().split(',')) @@ -302,9 +313,9 @@ def get_object_type(value): return convert_string(stdout.strip()) -def compute_diff_and_extract_lines(commits, files, staged): +def compute_diff_and_extract_lines(commits, files, staged, diff_common_commit): """Calls compute_diff() followed by extract_lines().""" - diff_process = compute_diff(commits, files, staged) + diff_process = compute_diff(commits, files, staged, diff_common_commit) changed_lines = extract_lines(diff_process.stdout) diff_process.stdout.close() diff_process.wait() @@ -314,7 +325,7 @@ def compute_diff_and_extract_lines(commits, files, staged): return changed_lines -def compute_diff(commits, files, staged): +def compute_diff(commits, files, staged, diff_common_commit): """Return a subprocess object producing the diff from `commits`. The return value's `stdin` file object will produce a patch with the @@ -324,10 +335,13 @@ def compute_diff(commits, files, staged): Zero context lines are used in the patch.""" git_tool = 'diff-index' extra_args = [] - if len(commits) > 1: + if len(commits) == 2: git_tool = 'diff-tree' + if diff_common_commit: + commits = [f'{commits[0]}...{commits[1]}'] elif staged: extra_args += ['--cached'] + cmd = ['git', git_tool, '-p', '-U0'] + extra_args + commits + ['--'] cmd.extend(files) p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE) diff --git a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp index db0ce3e2a1901922aa31640eafd947b96492bf36..5d2fe98fe56011588a4fa21748cd2c9bc10565a8 100644 --- a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp +++ b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp @@ -428,7 +428,7 @@ Expected clang(ArrayRef InputFiles, const ArgList &Args) { std::back_inserter(CmdArgs)); for (StringRef Arg : Args.getAllArgValues(OPT_linker_arg_EQ)) - CmdArgs.push_back(Args.MakeArgString("-Wl," + Arg)); + CmdArgs.push_back(Args.MakeArgString(Arg)); for (StringRef Arg : Args.getAllArgValues(OPT_builtin_bitcode_EQ)) { if (llvm::Triple(Arg.split('=').first) == Triple) diff --git a/clang/tools/clang-linker-wrapper/OffloadWrapper.cpp b/clang/tools/clang-linker-wrapper/OffloadWrapper.cpp index 3e1dd874216ccf3b04053a1be14a78a71e105a0c..f4f500b173572d2e62f64451059c1ae1b5414b43 100644 --- a/clang/tools/clang-linker-wrapper/OffloadWrapper.cpp +++ b/clang/tools/clang-linker-wrapper/OffloadWrapper.cpp @@ -26,19 +26,6 @@ namespace { constexpr unsigned CudaFatMagic = 0x466243b1; constexpr unsigned HIPFatMagic = 0x48495046; -/// Copied from clang/CGCudaRuntime.h. -enum OffloadEntryKindFlag : uint32_t { - /// Mark the entry as a global entry. This indicates the presense of a - /// kernel if the size size field is zero and a variable otherwise. - OffloadGlobalEntry = 0x0, - /// Mark the entry as a managed global variable. - OffloadGlobalManagedEntry = 0x1, - /// Mark the entry as a surface variable. - OffloadGlobalSurfaceEntry = 0x2, - /// Mark the entry as a texture variable. - OffloadGlobalTextureEntry = 0x3, -}; - IntegerType *getSizeTTy(Module &M) { return M.getDataLayout().getIntPtrType(M.getContext()); } @@ -333,6 +320,24 @@ Function *createRegisterGlobalsFunction(Module &M, bool IsHIP) { FunctionCallee RegVar = M.getOrInsertFunction( IsHIP ? "__hipRegisterVar" : "__cudaRegisterVar", RegVarTy); + // Get the __cudaRegisterSurface function declaration. + auto *RegSurfaceTy = + FunctionType::get(Type::getVoidTy(C), + {Int8PtrPtrTy, Int8PtrTy, Int8PtrTy, Int8PtrTy, + Type::getInt32Ty(C), Type::getInt32Ty(C)}, + /*isVarArg=*/false); + FunctionCallee RegSurface = M.getOrInsertFunction( + IsHIP ? "__hipRegisterSurface" : "__cudaRegisterSurface", RegSurfaceTy); + + // Get the __cudaRegisterTexture function declaration. + auto *RegTextureTy = FunctionType::get( + Type::getVoidTy(C), + {Int8PtrPtrTy, Int8PtrTy, Int8PtrTy, Int8PtrTy, Type::getInt32Ty(C), + Type::getInt32Ty(C), Type::getInt32Ty(C)}, + /*isVarArg=*/false); + FunctionCallee RegTexture = M.getOrInsertFunction( + IsHIP ? "__hipRegisterTexture" : "__cudaRegisterTexture", RegTextureTy); + auto *RegGlobalsTy = FunctionType::get(Type::getVoidTy(C), Int8PtrPtrTy, /*isVarArg*/ false); auto *RegGlobalsFn = @@ -375,7 +380,31 @@ Function *createRegisterGlobalsFunction(Module &M, bool IsHIP) { Builder.CreateInBoundsGEP(offloading::getEntryTy(M), Entry, {ConstantInt::get(getSizeTTy(M), 0), ConstantInt::get(Type::getInt32Ty(C), 3)}); - auto *Flags = Builder.CreateLoad(Type::getInt32Ty(C), FlagsPtr, "flag"); + auto *Flags = Builder.CreateLoad(Type::getInt32Ty(C), FlagsPtr, "flags"); + auto *DataPtr = + Builder.CreateInBoundsGEP(offloading::getEntryTy(M), Entry, + {ConstantInt::get(getSizeTTy(M), 0), + ConstantInt::get(Type::getInt32Ty(C), 4)}); + auto *Data = Builder.CreateLoad(Type::getInt32Ty(C), DataPtr, "textype"); + auto *Kind = Builder.CreateAnd( + Flags, ConstantInt::get(Type::getInt32Ty(C), 0x7), "type"); + + // Extract the flags stored in the bit-field and convert them to C booleans. + auto *ExternBit = Builder.CreateAnd( + Flags, ConstantInt::get(Type::getInt32Ty(C), + llvm::offloading::OffloadGlobalExtern)); + auto *Extern = Builder.CreateLShr( + ExternBit, ConstantInt::get(Type::getInt32Ty(C), 3), "extern"); + auto *ConstantBit = Builder.CreateAnd( + Flags, ConstantInt::get(Type::getInt32Ty(C), + llvm::offloading::OffloadGlobalConstant)); + auto *Const = Builder.CreateLShr( + ConstantBit, ConstantInt::get(Type::getInt32Ty(C), 4), "constant"); + auto *NormalizedBit = Builder.CreateAnd( + Flags, ConstantInt::get(Type::getInt32Ty(C), + llvm::offloading::OffloadGlobalNormalized)); + auto *Normalized = Builder.CreateLShr( + NormalizedBit, ConstantInt::get(Type::getInt32Ty(C), 5), "normalized"); auto *FnCond = Builder.CreateICmpEQ(Size, ConstantInt::getNullValue(getSizeTTy(M))); Builder.CreateCondBr(FnCond, IfThenBB, IfElseBB); @@ -392,30 +421,37 @@ Function *createRegisterGlobalsFunction(Module &M, bool IsHIP) { Builder.CreateBr(IfEndBB); Builder.SetInsertPoint(IfElseBB); - auto *Switch = Builder.CreateSwitch(Flags, IfEndBB); + auto *Switch = Builder.CreateSwitch(Kind, IfEndBB); // Create global variable registration code. Builder.SetInsertPoint(SwGlobalBB); - Builder.CreateCall(RegVar, {RegGlobalsFn->arg_begin(), Addr, Name, Name, - ConstantInt::get(Type::getInt32Ty(C), 0), Size, - ConstantInt::get(Type::getInt32Ty(C), 0), - ConstantInt::get(Type::getInt32Ty(C), 0)}); + Builder.CreateCall(RegVar, + {RegGlobalsFn->arg_begin(), Addr, Name, Name, Extern, Size, + Const, ConstantInt::get(Type::getInt32Ty(C), 0)}); Builder.CreateBr(IfEndBB); - Switch->addCase(Builder.getInt32(OffloadGlobalEntry), SwGlobalBB); + Switch->addCase(Builder.getInt32(llvm::offloading::OffloadGlobalEntry), + SwGlobalBB); // Create managed variable registration code. Builder.SetInsertPoint(SwManagedBB); Builder.CreateBr(IfEndBB); - Switch->addCase(Builder.getInt32(OffloadGlobalManagedEntry), SwManagedBB); + Switch->addCase(Builder.getInt32(llvm::offloading::OffloadGlobalManagedEntry), + SwManagedBB); // Create surface variable registration code. Builder.SetInsertPoint(SwSurfaceBB); + Builder.CreateCall( + RegSurface, {RegGlobalsFn->arg_begin(), Addr, Name, Name, Data, Extern}); Builder.CreateBr(IfEndBB); - Switch->addCase(Builder.getInt32(OffloadGlobalSurfaceEntry), SwSurfaceBB); + Switch->addCase(Builder.getInt32(llvm::offloading::OffloadGlobalSurfaceEntry), + SwSurfaceBB); // Create texture variable registration code. Builder.SetInsertPoint(SwTextureBB); + Builder.CreateCall(RegTexture, {RegGlobalsFn->arg_begin(), Addr, Name, Name, + Data, Normalized, Extern}); Builder.CreateBr(IfEndBB); - Switch->addCase(Builder.getInt32(OffloadGlobalTextureEntry), SwTextureBB); + Switch->addCase(Builder.getInt32(llvm::offloading::OffloadGlobalTextureEntry), + SwTextureBB); Builder.SetInsertPoint(IfEndBB); auto *NewEntry = Builder.CreateInBoundsGEP( diff --git a/clang/tools/libclang/CXIndexDataConsumer.cpp b/clang/tools/libclang/CXIndexDataConsumer.cpp index 5ca484fbc8cd82bf7175489e6f891f4975e60805..c1022263a51280263812244fb19047f08971650f 100644 --- a/clang/tools/libclang/CXIndexDataConsumer.cpp +++ b/clang/tools/libclang/CXIndexDataConsumer.cpp @@ -1074,8 +1074,8 @@ CXIndexDataConsumer::getClientContainerForDC(const DeclContext *DC) const { return DC ? ContainerMap.lookup(DC) : nullptr; } -CXIdxClientFile CXIndexDataConsumer::getIndexFile(const FileEntry *File) { - return File ? FileMap.lookup(File) : nullptr; +CXIdxClientFile CXIndexDataConsumer::getIndexFile(OptionalFileEntryRef File) { + return File ? FileMap.lookup(*File) : nullptr; } CXIdxLoc CXIndexDataConsumer::getIndexLoc(SourceLocation Loc) const { @@ -1104,8 +1104,8 @@ void CXIndexDataConsumer::translateLoc(SourceLocation Loc, if (FID.isInvalid()) return; - - OptionalFileEntryRefDegradesToFileEntryPtr FE = SM.getFileEntryRefForID(FID); + + OptionalFileEntryRef FE = SM.getFileEntryRefForID(FID); if (indexFile) *indexFile = getIndexFile(FE); if (file) diff --git a/clang/tools/libclang/CXIndexDataConsumer.h b/clang/tools/libclang/CXIndexDataConsumer.h index afa2239ed653f9dd19e01afb32ecfd8ef8cf3560..54a3add3a9c8d0b30e9616b4f348297b73f93736 100644 --- a/clang/tools/libclang/CXIndexDataConsumer.h +++ b/clang/tools/libclang/CXIndexDataConsumer.h @@ -460,8 +460,8 @@ private: const DeclContext *getEntityContainer(const Decl *D) const; - CXIdxClientFile getIndexFile(const FileEntry *File); - + CXIdxClientFile getIndexFile(OptionalFileEntryRef File); + CXIdxLoc getIndexLoc(SourceLocation Loc) const; void getEntityInfo(const NamedDecl *D, diff --git a/clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp b/clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp index 3569b0eac7005eb63d709bb86e1248255409eea8..003434a58b1075f3d4e89420d1ab06517e433f67 100644 --- a/clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp @@ -25,6 +25,7 @@ namespace { using namespace clang; using namespace dataflow; using ::clang::dataflow::test::getFieldValue; +using ::testing::Contains; using ::testing::IsNull; using ::testing::NotNull; @@ -311,6 +312,57 @@ TEST_F(EnvironmentTest, InitGlobalVarsConstructor) { EXPECT_THAT(Env.getValue(*Var), NotNull()); } +// Pointers to Members are a tricky case of accessor calls, complicated further +// when using templates where the pointer to the member is a template argument. +// This is a repro of a failure case seen in the wild. +TEST_F(EnvironmentTest, + ModelMemberForAccessorUsingMethodPointerThroughTemplate) { + using namespace ast_matchers; + + std::string Code = R"cc( + struct S { + int accessor() {return member;} + + int member = 0; + }; + + template + int Target(S* S) { + return (S->*method)(); + } + + // We want to analyze the instantiation of Target for the accessor. + int Instantiator () {S S; return Target<&S::accessor>(&S); } + )cc"; + + auto Unit = + // C++17 for the simplifying use of auto in the template declaration. + tooling::buildASTFromCodeWithArgs(Code, {"-fsyntax-only", "-std=c++17"}); + auto &Context = Unit->getASTContext(); + + ASSERT_EQ(Context.getDiagnostics().getClient()->getNumErrors(), 0U); + + auto Results = match( + decl(anyOf(functionDecl(hasName("Target"), isTemplateInstantiation()) + .bind("target"), + fieldDecl(hasName("member")).bind("member"), + recordDecl(hasName("S")).bind("struct"))), + Context); + const auto *Fun = selectFirst("target", Results); + const auto *Struct = selectFirst("struct", Results); + const auto *Member = selectFirst("member", Results); + ASSERT_THAT(Fun, NotNull()); + ASSERT_THAT(Struct, NotNull()); + ASSERT_THAT(Member, NotNull()); + + // Verify that `member` is modeled for `S` when we analyze + // `Target<&S::accessor>`. + Environment Env(DAContext, *Fun); + Env.initialize(); + EXPECT_THAT(DAContext.getModeledFields(QualType(Struct->getTypeForDecl(), 0)), + Contains(Member)); +} + TEST_F(EnvironmentTest, RefreshRecordValue) { using namespace ast_matchers; diff --git a/clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp b/clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp index f92afd8c3d84a08305033dbd0677bdea3a8c25d9..4c3cb322eacfb3a3b018d5c3fc8a6275255aa278 100644 --- a/clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp @@ -514,8 +514,17 @@ TEST_F(NoreturnDestructorTest, ConditionalOperatorNestedBranchReturns) { class SpecialBoolAnalysis final : public DataflowAnalysis { public: - explicit SpecialBoolAnalysis(ASTContext &Context) - : DataflowAnalysis(Context) {} + explicit SpecialBoolAnalysis(ASTContext &Context, Environment &Env) + : DataflowAnalysis(Context) { + Env.getDataflowAnalysisContext().setSyntheticFieldCallback( + [](QualType Ty) -> llvm::StringMap { + RecordDecl *RD = Ty->getAsRecordDecl(); + if (RD == nullptr || RD->getIdentifier() == nullptr || + RD->getName() != "SpecialBool") + return {}; + return {{"is_set", RD->getASTContext().BoolTy}}; + }); + } static NoopLattice initialElement() { return {}; } @@ -530,67 +539,18 @@ public: if (const auto *E = selectFirst( "call", match(cxxConstructExpr(HasSpecialBoolType).bind("call"), *S, getASTContext()))) { - cast(Env.getValue(*E)) - ->setProperty("is_set", Env.getBoolLiteralValue(false)); + Env.setValue(Env.getResultObjectLocation(*E).getSyntheticField("is_set"), + Env.getBoolLiteralValue(false)); } else if (const auto *E = selectFirst( "call", match(cxxMemberCallExpr(callee(cxxMethodDecl(ofClass( SpecialBoolRecordDecl)))) .bind("call"), *S, getASTContext()))) { - auto &ObjectLoc = - *cast(getImplicitObjectLocation(*E, Env)); - - refreshRecordValue(ObjectLoc, Env) - .setProperty("is_set", Env.getBoolLiteralValue(true)); + if (RecordStorageLocation *ObjectLoc = getImplicitObjectLocation(*E, Env)) + Env.setValue(ObjectLoc->getSyntheticField("is_set"), + Env.getBoolLiteralValue(true)); } } - - ComparisonResult compare(QualType Type, const Value &Val1, - const Environment &Env1, const Value &Val2, - const Environment &Env2) override { - const auto *Decl = Type->getAsCXXRecordDecl(); - if (Decl == nullptr || Decl->getIdentifier() == nullptr || - Decl->getName() != "SpecialBool") - return ComparisonResult::Unknown; - - auto *IsSet1 = cast_or_null(Val1.getProperty("is_set")); - auto *IsSet2 = cast_or_null(Val2.getProperty("is_set")); - if (IsSet1 == nullptr) - return IsSet2 == nullptr ? ComparisonResult::Same - : ComparisonResult::Different; - - if (IsSet2 == nullptr) - return ComparisonResult::Different; - - return Env1.proves(IsSet1->formula()) == Env2.proves(IsSet2->formula()) - ? ComparisonResult::Same - : ComparisonResult::Different; - } - - // Always returns `true` to accept the `MergedVal`. - bool merge(QualType Type, const Value &Val1, const Environment &Env1, - const Value &Val2, const Environment &Env2, Value &MergedVal, - Environment &MergedEnv) override { - const auto *Decl = Type->getAsCXXRecordDecl(); - if (Decl == nullptr || Decl->getIdentifier() == nullptr || - Decl->getName() != "SpecialBool") - return true; - - auto *IsSet1 = cast_or_null(Val1.getProperty("is_set")); - if (IsSet1 == nullptr) - return true; - - auto *IsSet2 = cast_or_null(Val2.getProperty("is_set")); - if (IsSet2 == nullptr) - return true; - - auto &IsSet = MergedEnv.makeAtomicBoolValue(); - MergedVal.setProperty("is_set", IsSet); - if (Env1.proves(IsSet1->formula()) && Env2.proves(IsSet2->formula())) - MergedEnv.assume(IsSet.formula()); - - return true; - } }; class JoinFlowConditionsTest : public Test { @@ -602,7 +562,7 @@ protected: AnalysisInputs( Code, ast_matchers::hasName("target"), [](ASTContext &Context, Environment &Env) { - return SpecialBoolAnalysis(Context); + return SpecialBoolAnalysis(Context, Env); }) .withASTBuildArgs({"-fsyntax-only", "-std=c++17"}), /*VerifyResults=*/[&Match](const llvm::StringMap< @@ -650,7 +610,9 @@ TEST_F(JoinFlowConditionsTest, JoinDistinctButProvablyEquivalentValues) { ASSERT_THAT(FooDecl, NotNull()); auto GetFoo = [FooDecl](const Environment &Env) -> const Formula & { - return cast(Env.getValue(*FooDecl)->getProperty("is_set")) + auto *Loc = + cast(Env.getStorageLocation(*FooDecl)); + return cast(Env.getValue(Loc->getSyntheticField("is_set"))) ->formula(); }; diff --git a/clang/unittests/Basic/FileEntryTest.cpp b/clang/unittests/Basic/FileEntryTest.cpp index dcd196417da731ec9940b9629f23917cbb501d8d..f8a0b4a4edcdaf402ae37aaa273c76a72b25ef19 100644 --- a/clang/unittests/Basic/FileEntryTest.cpp +++ b/clang/unittests/Basic/FileEntryTest.cpp @@ -92,24 +92,6 @@ TEST(FileEntryTest, FileEntryRef) { EXPECT_EQ(CE1, &R1.getFileEntry()); } -TEST(FileEntryTest, OptionalFileEntryRefDegradesToFileEntryPtr) { - FileEntryTestHelper Refs; - OptionalFileEntryRefDegradesToFileEntryPtr M0; - OptionalFileEntryRefDegradesToFileEntryPtr M1 = Refs.addFile("1"); - OptionalFileEntryRefDegradesToFileEntryPtr M2 = Refs.addFile("2"); - OptionalFileEntryRefDegradesToFileEntryPtr M0Also = std::nullopt; - OptionalFileEntryRefDegradesToFileEntryPtr M1Also = - Refs.addFileAlias("1-also", *M1); - - EXPECT_EQ(M0, M0Also); - EXPECT_EQ(StringRef("1"), M1->getName()); - EXPECT_EQ(StringRef("2"), M2->getName()); - EXPECT_EQ(StringRef("1-also"), M1Also->getName()); - - const FileEntry *CE1 = M1; - EXPECT_EQ(CE1, &M1->getFileEntry()); -} - TEST(FileEntryTest, equals) { FileEntryTestHelper Refs; FileEntryRef R1 = Refs.addFile("1"); @@ -126,13 +108,6 @@ TEST(FileEntryTest, equals) { EXPECT_NE(R1, R2); EXPECT_EQ(R1, R1Redirect); EXPECT_EQ(R1, R1Redirect2); - - OptionalFileEntryRefDegradesToFileEntryPtr M1 = R1; - - EXPECT_EQ(M1, &R1.getFileEntry()); - EXPECT_EQ(&R1.getFileEntry(), M1); - EXPECT_NE(M1, &R2.getFileEntry()); - EXPECT_NE(&R2.getFileEntry(), M1); } TEST(FileEntryTest, isSameRef) { diff --git a/clang/unittests/Basic/FileManagerTest.cpp b/clang/unittests/Basic/FileManagerTest.cpp index bf30fabb7cd8878882edbe7fc1ca8b8a9dd233a7..43339676c4a6a2c209a827146083950aeab6ed3a 100644 --- a/clang/unittests/Basic/FileManagerTest.cpp +++ b/clang/unittests/Basic/FileManagerTest.cpp @@ -284,7 +284,9 @@ TEST_F(FileManagerTest, getFileRefReturnsCorrectNameForDifferentStatPath) { ASSERT_FALSE(!F1Alias); ASSERT_FALSE(!F1Alias2); EXPECT_EQ("dir/f1.cpp", F1->getName()); + LLVM_SUPPRESS_DEPRECATED_DECLARATIONS_PUSH EXPECT_EQ("dir/f1.cpp", F1->getFileEntry().getName()); + LLVM_SUPPRESS_DEPRECATED_DECLARATIONS_POP EXPECT_EQ("dir/f1.cpp", F1Alias->getName()); EXPECT_EQ("dir/f1.cpp", F1Alias2->getName()); EXPECT_EQ(&F1->getFileEntry(), &F1Alias->getFileEntry()); @@ -303,7 +305,9 @@ TEST_F(FileManagerTest, getFileRefReturnsCorrectNameForDifferentStatPath) { ASSERT_FALSE(!F2Alias); ASSERT_FALSE(!F2Alias2); EXPECT_EQ("dir/f2.cpp", F2->getName()); + LLVM_SUPPRESS_DEPRECATED_DECLARATIONS_PUSH EXPECT_EQ("dir/f2.cpp", F2->getFileEntry().getName()); + LLVM_SUPPRESS_DEPRECATED_DECLARATIONS_POP EXPECT_EQ("dir/f2.cpp", F2Alias->getName()); EXPECT_EQ("dir/f2.cpp", F2Alias2->getName()); EXPECT_EQ(&F2->getFileEntry(), &F2Alias->getFileEntry()); diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index 8782cb7c49cad33f9328d6ab64609cec537e6c8a..24b2fd599dc39733911c56a2a7cf64d0ffb8a189 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -13950,6 +13950,19 @@ TEST_F(FormatTest, PullTrivialFunctionDefinitionsIntoSingleLine) { " void f() { int i; } \\\n" " int j;", getLLVMStyleWithColumns(23)); + + verifyFormat( + "void aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(\n" + " aaaaaaaaaaaaaaaaaa,\n" + " aaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb) {}"); + + constexpr StringRef Code{"void foo() { /* Empty */ }"}; + verifyFormat(Code); + verifyFormat(Code, "void foo() { /* Empty */\n" + "}"); + verifyFormat(Code, "void foo() {\n" + "/* Empty */\n" + "}"); } TEST_F(FormatTest, PullEmptyFunctionDefinitionsIntoSingleLine) { diff --git a/clang/unittests/Format/FormatTestComments.cpp b/clang/unittests/Format/FormatTestComments.cpp index 9770d5090703c777385a22dd2fc76e7d52372eff..c249f4d9333fd079744a0cc22b26af369d641f2c 100644 --- a/clang/unittests/Format/FormatTestComments.cpp +++ b/clang/unittests/Format/FormatTestComments.cpp @@ -386,15 +386,16 @@ TEST_F(FormatTestComments, UnderstandsBlockComments) { " /* Leading comment for bb... */ bbbbbbbbbbbbbbbbbbbbbbbbb);", format("f(aaaaaaaaaaaaaaaaaaaaaaaaa , \n" "/* Leading comment for bb... */ bbbbbbbbbbbbbbbbbbbbbbbbb);")); - EXPECT_EQ( + + verifyFormat( "void aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(\n" " aaaaaaaaaaaaaaaaaa,\n" - " aaaaaaaaaaaaaaaaaa) { /*aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa*/\n" - "}", - format("void aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(\n" - " aaaaaaaaaaaaaaaaaa ,\n" - " aaaaaaaaaaaaaaaaaa) { /*aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa*/\n" - "}")); + " aaaaaaaaaaaaaaaaaa) { /*aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa*/ }", + "void aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(\n" + " aaaaaaaaaaaaaaaaaa ,\n" + " aaaaaaaaaaaaaaaaaa) { /*aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa*/\n" + "}"); + verifyFormat("f(/* aaaaaaaaaaaaaaaaaa = */\n" " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa);"); diff --git a/clang/unittests/Format/ObjCPropertyAttributeOrderFixerTest.cpp b/clang/unittests/Format/ObjCPropertyAttributeOrderFixerTest.cpp index 109eaa785ca5f17c9ac9b0dd25eb190a2b01103b..79ded66735916fc6135c1dddd3225715a3dd80aa 100644 --- a/clang/unittests/Format/ObjCPropertyAttributeOrderFixerTest.cpp +++ b/clang/unittests/Format/ObjCPropertyAttributeOrderFixerTest.cpp @@ -171,18 +171,18 @@ TEST_F(ObjCPropertyAttributeOrderFixerTest, HandlesDuplicatedAttributes) { Style.ObjCPropertyAttributeOrder = {"a", "b", "c"}; // Just a dup and nothing else. - verifyFormat("@property(a, a) int p;", Style); + verifyFormat("@property(a) int p;", "@property(a, a) int p;", Style); // A dup and something else. - verifyFormat("@property(a, a, b) int p;", "@property(a, b, a) int p;", Style); + verifyFormat("@property(a, b) int p;", "@property(a, b, a) int p;", Style); - // Duplicates using `=`: stable-sort irrespective of their value. - verifyFormat("@property(a=A, a=A, b=X, b=Y) int p;", + // Duplicates using `=`. + verifyFormat("@property(a=A, b=X) int p;", "@property(a=A, b=X, a=A, b=Y) int p;", Style); - verifyFormat("@property(a=A, a=A, b=Y, b=X) int p;", + verifyFormat("@property(a=A, b=Y) int p;", "@property(a=A, b=Y, a=A, b=X) int p;", Style); - verifyFormat("@property(a, a=A, b=B, b) int p;", - "@property(a, b=B, a=A, b) int p;", Style); + verifyFormat("@property(a, b=B) int p;", "@property(a, b=B, a=A, b) int p;", + Style); } TEST_F(ObjCPropertyAttributeOrderFixerTest, SortsInPPDirective) { @@ -200,7 +200,7 @@ TEST_F(ObjCPropertyAttributeOrderFixerTest, SortsInPPDirective) { } TEST_F(ObjCPropertyAttributeOrderFixerTest, HandlesAllAttributes) { - // 'class' is the only attribute that is a keyword, so make sure it works too. + // `class` is the only attribute that is a keyword, so make sure it works too. FormatStyle Style = getLLVMStyle(); Style.Language = FormatStyle::LK_ObjC; Style.ObjCPropertyAttributeOrder = {"FIRST", @@ -282,7 +282,7 @@ TEST_F(ObjCPropertyAttributeOrderFixerTest, HandlesAllAttributes) { verifyFormat("@property(FIRST, null_resettable, LAST) int p;", Style); verifyFormat("@property(FIRST, null_unspecified, LAST) int p;", Style); - // Reorder: put 'FIRST' and/or 'LAST' in the wrong spot. + // Reorder: put `FIRST` and/or `LAST` in the wrong spot. verifyFormat("@property(class, LAST) int p;", "@property(LAST, class) int p;", Style); verifyFormat("@property(direct, LAST) int p;", diff --git a/clang/utils/TableGen/SveEmitter.cpp b/clang/utils/TableGen/SveEmitter.cpp index b380bd9dfe6643a60df8f5f5a96cd27bff4359ad..b8a1fb4bab0f499d74cc1e0c2cf9128c32d8754d 100644 --- a/clang/utils/TableGen/SveEmitter.cpp +++ b/clang/utils/TableGen/SveEmitter.cpp @@ -744,6 +744,12 @@ void SVEType::applyModifier(char Mod) { BFloat = false; ElementBitwidth = 64; break; + case '[': + Signed = false; + Float = false; + BFloat = false; + ElementBitwidth = 8; + break; case 't': Signed = true; Float = false; diff --git a/clang/www/analyzer/alpha_checks.html b/clang/www/analyzer/alpha_checks.html index cff0284777bc78a33058092cde0e96040000cc1b..11ef7d405dd4c817da6671c5df9a36d5be44085c 100644 --- a/clang/www/analyzer/alpha_checks.html +++ b/clang/www/analyzer/alpha_checks.html @@ -370,25 +370,6 @@ void sink(NonVirtual *x) { } -

- - -

().g()), ""); @@ -214,57 +258,64 @@ namespace dr1330 { // dr1330: 4 c++11 static_assert(!noexcept(B().g()), ""); #endif - template int f() throw(typename T::error) { return 0; } // expected-error 1-4{{prior to '::'}} expected-note 0-1{{prior to '::'}} expected-note 0-1{{requested here}} -#if __cplusplus > 201402L - // expected-error@-2 0-1{{C++17}} expected-note@-2 0-1{{noexcept}} -#endif + template int f() throw(typename T::error) { return 0; } // #dr1330-f + // expected-error@#dr1330-f {{type 'int' cannot be used prior to '::' because it has no members}} + // cxx98-note@#dr1330-f-int {{in instantiation of function template specialization 'dr1330::f' requested here}} + // since-cxx11-note@#dr1330-f-int {{in instantiation of exception specification for 'f' requested here}} + // cxx98-14-error@#dr1330-f {{type 'short' cannot be used prior to '::' because it has no members}} + // cxx98-14-note@#dr1330-f-short {{in instantiation of function template specialization 'dr1330::f' requested here}} + // cxx11-14-note@#dr1330-f {{in instantiation of exception specification for 'f' requested here}} + // since-cxx11-error@#dr1330-f {{type 'char' cannot be used prior to '::' because it has no members}} + // since-cxx11-note@#dr1330-f-char {{in instantiation of exception specification for 'f' requested here}} + // since-cxx11-error@#dr1330-f {{type 'float' cannot be used prior to '::' because it has no members}} + // since-cxx11-note@#dr1330-f-float {{in instantiation of exception specification for 'f' requested here}} + // since-cxx17-error@#dr1330-f {{ISO C++17 does not allow dynamic exception specifications}} + // since-cxx17-note@#dr1330-f {{use 'noexcept(false)' instead}} + // An exception-specification is needed even if the function is only used in // an unevaluated operand. - int f1 = sizeof(f()); // expected-note {{instantiation of}} + int f1 = sizeof(f()); // #dr1330-f-int #if __cplusplus >= 201103L - decltype(f()) f2; // expected-note {{instantiation of}} - bool f3 = noexcept(f()); // expected-note {{instantiation of}} + decltype(f()) f2; // #dr1330-f-char + bool f3 = noexcept(f()); /// #dr1330-f-float #endif // In C++17 onwards, substituting explicit template arguments into the // function type substitutes into the exception specification (because it's // part of the type). In earlier languages, we don't notice there's a problem // until we've already started to instantiate. - template int f(); -#if __cplusplus >= 201703L - // expected-error@-2 {{does not refer to a function template}} -#else - // expected-note@-4 {{instantiation of}} -#endif + template int f(); // #dr1330-f-short + // since-cxx17-error@-1 {{explicit instantiation of 'f' does not refer to a function template, variable template, member function, member class, or static data member}} + // since-cxx17-note@#dr1330-f {{candidate template ignored: substitution failure [with T = short]: type 'short' cannot be used prior to '::' because it has no members}} template struct C { - C() throw(typename T::type); // expected-error 1-2{{prior to '::'}} -#if __cplusplus > 201402L - // expected-error@-2 0-1{{C++17}} expected-note@-2 0-1{{noexcept}} -#endif + C() throw(typename T::type); // #dr1330-C + // since-cxx17-error@-1 {{ISO C++17 does not allow dynamic exception specifications}} + // since-cxx17-note@-2 {{use 'noexcept(false)' instead}} + // cxx98-error@#dr1330-C {{type 'void' cannot be used prior to '::' because it has no members}} + // cxx98-note@#dr1330-C-void {{in instantiation of template class 'dr1330::C' requested here}} + // expected-error@#dr1330-C {{type 'int' cannot be used prior to '::' because it has no members}} + // cxx98-note@#dr1330-C-int {{in instantiation of template class 'dr1330::C' requested here}} + // since-cxx11-note@#dr1330-C-int {{in instantiation of exception specification for 'C' requested here}} + // since-cxx11-note@#dr1330-e {{in evaluation of exception specification for 'dr1330::E::E' needed here}} }; - struct D : C {}; // ok -#if __cplusplus < 201103L - // expected-note@-2 {{instantiation of}} -#endif + struct D : C {}; // #dr1330-C-void void f(D &d) { d = d; } // ok - struct E : C {}; // expected-note {{in instantiation of}} -#if __cplusplus >= 201103L - E e; // expected-note {{needed here}} -#endif + struct E : C {}; // #dr1330-C-int + E e; // #dr1330-e } namespace dr1341 { // dr1341: sup P0683R1 #if __cplusplus >= 202002L int a; -const int b = 0; // #dr1341-b-decl +const int b = 0; // #dr1341-b struct S { int x1 : 8 = 42; int x2 : 8 { 42 }; int y1 : true ? 8 : a = 42; int y2 : true ? 8 : b = 42; - // expected-error@-1 {{cannot assign to variable 'b' with const-qualified type 'const int'}} - // expected-note@#dr1341-b-decl {{variable 'b' declared const here}} + // since-cxx20-error@-1 {{cannot assign to variable 'b' with const-qualified type 'const int'}} + // since-cxx20-note@#dr1341-b {{variable 'b' declared const here}} int y3 : (true ? 8 : b) = 42; int z : 1 || new int { 0 }; }; @@ -272,44 +323,66 @@ struct S { } namespace dr1346 { // dr1346: 3.5 - auto a(1); // expected-error 0-1{{extension}} - auto b(1, 2); // expected-error {{multiple expressions}} expected-error 0-1{{extension}} + auto a(1); + // cxx98-error@-1 {{'auto' type specifier is a C++11 extension}} + auto b(1, 2); + // cxx98-error@-1 {{'auto' type specifier is a C++11 extension}} + // expected-error@-2 {{initializer for variable 'b' with type 'auto' contains multiple expressions}} #if __cplusplus >= 201103L - auto c({}); // expected-error {{parenthesized initializer list}} - auto d({1}); // expected-error {{parenthesized initializer list}} - auto e({1, 2}); // expected-error {{parenthesized initializer list}} + auto c({}); + // since-cxx11-error@-1 {{cannot deduce type for variable 'c' with type 'auto' from parenthesized initializer list}} + auto d({1}); + // since-cxx11-error@-1 {{cannot deduce type for variable 'd' with type 'auto' from parenthesized initializer list}} + auto e({1, 2}); + // since-cxx11-error@-1 {{cannot deduce type for variable 'e' with type 'auto' from parenthesized initializer list}} #endif - template void f(Ts ...ts) { // expected-error 0-1{{extension}} - auto x(ts...); // expected-error {{empty}} expected-error 0-1{{extension}} + template void f(Ts ...ts) { + // cxx98-error@-1 {{variadic templates are a C++11 extension}} + auto x(ts...); + // cxx98-error@-1 {{'auto' type specifier is a C++11 extension}} + // expected-error@-2 {{initializer for variable 'x' with type 'auto' is empty}} + // expected-note@#dr1346-f {{in instantiation of function template specialization 'dr1346::f<>' requested here}} } - template void f(); // expected-note {{instantiation}} + template void f(); // #dr1346-f #if __cplusplus >= 201103L void init_capture() { - [a(1)] {} (); // expected-error 0-1{{extension}} - [b(1, 2)] {} (); // expected-error {{multiple expressions}} expected-error 0-1{{extension}} -#if __cplusplus >= 201103L - [c({})] {} (); // expected-error {{parenthesized initializer list}} expected-error 0-1{{extension}} - [d({1})] {} (); // expected-error {{parenthesized initializer list}} expected-error 0-1{{extension}} - [e({1, 2})] {} (); // expected-error {{parenthesized initializer list}} expected-error 0-1{{extension}} -#endif + [a(1)] {} (); + // cxx11-error@-1 {{initialized lambda captures are a C++14 extension}} + [b(1, 2)] {} (); + // cxx11-error@-1 {{initialized lambda captures are a C++14 extension}} + // since-cxx11-error@-2 {{initializer for lambda capture 'b' contains multiple expressions}} + [c({})] {} (); + // cxx11-error@-1 {{initialized lambda captures are a C++14 extension}} + // since-cxx11-error@-2 {{cannot deduce type for lambda capture 'c' from parenthesized initializer list}} + [d({1})] {} (); + // cxx11-error@-1 {{initialized lambda captures are a C++14 extension}} + // since-cxx11-error@-2 {{cannot deduce type for lambda capture 'd' from parenthesized initializer list}} + [e({1, 2})] {} (); + // cxx11-error@-1 {{initialized lambda captures are a C++14 extension}} + // since-cxx11-error@-2 {{cannot deduce type for lambda capture 'e' from parenthesized initializer list}} } #endif } -namespace dr1347 { // dr1347: yes - auto x = 5, *y = &x; // expected-error 0-1{{extension}} - auto z = y, *q = y; // expected-error {{'auto' deduced as 'int *' in declaration of 'z' and deduced as 'int' in declaration of 'q'}} expected-error 0-1{{extension}} +namespace dr1347 { // dr1347: 3.1 + auto x = 5, *y = &x; + // cxx98-error@-1 {{'auto' type specifier is a C++11 extension}} + auto z = y, *q = y; + // cxx98-error@-1 {{'auto' type specifier is a C++11 extension}} + // expected-error@-2 {{'auto' deduced as 'int *' in declaration of 'z' and deduced as 'int' in declaration of 'q'}} #if __cplusplus >= 201103L - auto a = 5, b = {1, 2}; // expected-error {{'auto' deduced as 'int' in declaration of 'a' and deduced as 'std::initializer_list' in declaration of 'b'}} - auto (*fp)(int) -> int, i = 0; // expected-error {{declaration with trailing return type must be the only declaration in its group}} + auto a = 5, b = {1, 2}; + // since-cxx11-error@-1 {{'auto' deduced as 'int' in declaration of 'a' and deduced as 'std::initializer_list' in declaration of 'b'}} + auto (*fp)(int) -> int, i = 0; + // since-cxx11-error@-1 {{declaration with trailing return type must be the only declaration in its group}} #endif } -namespace dr1358 { // dr1358: yes +namespace dr1358 { // dr1358: 3.1 #if __cplusplus >= 201103L struct Lit { constexpr operator int() const { return 0; } }; - struct NonLit { NonLit(); operator int(); }; // expected-note 2{{no constexpr constructors}} + struct NonLit { NonLit(); operator int(); }; // #dr1358-NonLit struct NonConstexprConv { constexpr operator int() const; }; struct Virt { virtual int f(int) const; }; @@ -336,8 +409,12 @@ namespace dr1358 { // dr1358: yes // But the corresponding non-template cases are rejected. struct B : Virt { int member; - constexpr B(NonLit u) : member(u) {} // expected-error {{not a literal type}} - constexpr NonLit f(NonLit u) const { return NonLit(); } // expected-error {{not a literal type}} + constexpr B(NonLit u) : member(u) {} + // since-cxx11-error@-1 {{constexpr constructor's 1st parameter type 'NonLit' is not a literal type}} + // since-cxx11-note@#dr1358-NonLit {{'NonLit' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}} + constexpr NonLit f(NonLit u) const { return NonLit(); } + // since-cxx11-error@-1 {{constexpr function's return type 'NonLit' is not a literal type}} + // since-cxx11-note@#dr1358-NonLit {{'NonLit' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}} }; #endif } @@ -345,65 +422,113 @@ namespace dr1358 { // dr1358: yes namespace dr1359 { // dr1359: 3.5 #if __cplusplus >= 201103L union A { constexpr A() = default; }; - union B { constexpr B() = default; int a; }; // expected-error {{not constexpr}} expected-note 2{{candidate}} - union C { constexpr C() = default; int a, b; }; // expected-error {{not constexpr}} expected-note 2{{candidate}} - struct X { constexpr X() = default; union {}; }; // expected-error {{does not declare anything}} - struct Y { constexpr Y() = default; union { int a; }; }; // expected-error {{not constexpr}} expected-note 2{{candidate}} + union B { constexpr B() = default; int a; }; // #dr1359-B + // cxx11-17-error@-1 {{defaulted definition of default constructor is not constexpr}} + union C { constexpr C() = default; int a, b; }; // #dr1359-C + // cxx11-17-error@-1 {{defaulted definition of default constructor is not constexpr}} + struct X { constexpr X() = default; union {}; }; + // since-cxx11-error@-1 {{declaration does not declare anything}} + struct Y { constexpr Y() = default; union { int a; }; }; // #dr1359-Y + // cxx11-17-error@-1 {{defaulted definition of default constructor is not constexpr}} constexpr A a = A(); - constexpr B b = B(); // expected-error {{no matching}} - constexpr C c = C(); // expected-error {{no matching}} + constexpr B b = B(); + // cxx11-17-error@-1 {{no matching constructor for initialization of 'B'}} + // cxx11-17-note@#dr1359-B {{candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 0 were provided}} + // cxx11-17-note@#dr1359-B {{candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 0 were provided}} + constexpr C c = C(); + // cxx11-17-error@-1 {{no matching constructor for initialization of 'C'}} + // cxx11-17-note@#dr1359-C {{candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 0 were provided}} + // cxx11-17-note@#dr1359-C {{candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 0 were provided}} constexpr X x = X(); - constexpr Y y = Y(); // expected-error {{no matching}} + constexpr Y y = Y(); + // cxx11-17-error@-1 {{no matching constructor for initialization of 'Y'}} + // cxx11-17-note@#dr1359-Y {{candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 0 were provided}} + // cxx11-17-note@#dr1359-Y {{candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 0 were provided}} #endif } namespace dr1388 { // dr1388: 4 - template void f(T..., A); // expected-note 1+{{candidate}} expected-error 0-1{{C++11}} - template void g(T..., int); // expected-note 1+{{candidate}} expected-error 0-1{{C++11}} - template void h(T..., A); // expected-note 1+{{candidate}} expected-error 0-1{{C++11}} + template void f(T..., A); // #dr1388-f + // cxx98-error@-1 {{variadic templates are a C++11 extension}} + template void g(T..., int); // #dr1388-g + // cxx98-error@-1 {{variadic templates are a C++11 extension}} + template void h(T..., A); // #dr1388-h + // cxx98-error@-1 {{variadic templates are a C++11 extension}} void test_f() { f(0); // ok, trailing parameter pack deduced to empty - f(0, 0); // expected-error {{no matching}} + f(0, 0); + // expected-error@-1 {{no matching function for call to 'f'}} + // expected-note@#dr1388-f {{candidate function [with A = int, T = <>] not viable: requires 1 argument, but 2 were provided}} f(0); - f(0, 0); // expected-error {{no matching}} + f(0, 0); + // expected-error@-1 {{no matching function for call to 'f'}} + // expected-note@#dr1388-f {{candidate function [with A = int, T = <>] not viable: requires 1 argument, but 2 were provided}} f(0, 0); - f(0, 0); // expected-error {{no matching}} + f(0, 0); + // expected-error@-1 {{no matching function for call to 'f'}} + // expected-note@#dr1388-f {{candidate function [with A = int, T = ] not viable: requires 3 arguments, but 2 were provided}} g(0); - g(0, 0); // expected-error {{no matching}} + g(0, 0); + // expected-error@-1 {{no matching function for call to 'g'}} + // expected-note@#dr1388-g {{candidate function [with T = <>] not viable: requires 1 argument, but 2 were provided}} g<>(0); - g(0); // expected-error {{no matching}} + g(0); + // expected-error@-1 {{no matching function for call to 'g'}} + // expected-note@#dr1388-g {{candidate function [with T = ] not viable: requires 2 arguments, but 1 was provided}} g(0, 0); h(0); - h(0, 0); // expected-error {{no matching}} + h(0, 0); + // expected-error@-1 {{no matching function for call to 'h'}} + // expected-note@#dr1388-h {{candidate function [with T = <>, A = int] not viable: requires 1 argument, but 2 were provided}} h(0, 0); - h(0, 0); // expected-error {{no matching}} + h(0, 0); + // expected-error@-1 {{no matching function for call to 'h'}} + // expected-note@#dr1388-h {{candidate template ignored: couldn't infer template argument 'A'}} } // A non-trailing parameter pack is still a non-deduced context, even though // we know exactly how many arguments correspond to it. template struct pair {}; - template struct tuple { typedef char type; }; // expected-error 0-2{{C++11}} - template void f_pair_1(pair..., int); // expected-error 0-2{{C++11}} expected-note {{[with T = ]: deduced incomplete pack <(no value), (no value)> for template parameter 'U'}} - template void f_pair_2(pair..., U); // expected-error 0-2{{C++11}} - template void f_pair_3(pair..., tuple); // expected-error 0-2{{C++11}} expected-note {{deduced packs of different lengths for parameter 'U' (<(no value), (no value)> vs. )}} - template void f_pair_4(pair..., T...); // expected-error 0-2{{C++11}} expected-note {{ vs. }} + template struct tuple { typedef char type; }; // + // cxx98-error@-1 {{variadic templates are a C++11 extension}} + template void f_pair_1(pair..., int); // #dr1388-f-1 + // cxx98-error@-1 {{variadic templates are a C++11 extension}} + // cxx98-error@-2 {{variadic templates are a C++11 extension}} + template void f_pair_2(pair..., U); + // cxx98-error@-1 {{variadic templates are a C++11 extension}} + template void f_pair_3(pair..., tuple); // #dr1388-f-3 + // cxx98-error@-1 {{variadic templates are a C++11 extension}} + // cxx98-error@-2 {{variadic templates are a C++11 extension}} + template void f_pair_4(pair..., T...); // #dr1388-f-4 + // cxx98-error@-1 {{variadic templates are a C++11 extension}} void g(pair a, pair b, tuple c) { - f_pair_1(a, b, 0); // expected-error {{no match}} + f_pair_1(a, b, 0); + // expected-error@-1 {{no matching function for call to 'f_pair_1'}} + // expected-note@#dr1388-f-1 {{candidate template ignored: substitution failure [with T = ]: deduced incomplete pack <(no value), (no value)> for template parameter 'U'}} f_pair_2(a, b, 0); f_pair_3(a, b, c); - f_pair_3(a, b, tuple()); // expected-error {{no match}} + f_pair_3(a, b, tuple()); + // expected-error@-1 {{no matching function for call to 'f_pair_3'}} + // expected-note@#dr1388-f-3 {{candidate template ignored: deduced packs of different lengths for parameter 'U' (<(no value), (no value)> vs. )}} f_pair_4(a, b, 0, 0L); - f_pair_4(a, b, 0, 0L, "foo"); // expected-error {{no match}} + f_pair_4(a, b, 0, 0L, "foo"); + // expected-error@-1 {{no matching function for call to 'f_pair_4'}} + // expected-note@#dr1388-f-4 {{candidate template ignored: deduced packs of different lengths for parameter 'T' ( vs. )}} } } namespace dr1391 { // dr1391: partial struct A {}; struct B : A {}; - template struct C { C(int); typename T::error error; }; // expected-error 2{{'::'}} + template struct C { C(int); typename T::error error; }; // #dr1391-C + // expected-error@#dr1391-C {{type 'int' cannot be used prior to '::' because it has no members}} + // expected-note@#dr1391-b {{in instantiation of template class 'dr1391::C' requested here}} + // expected-note@#dr1391-b {{while substituting deduced template arguments into function template 'b' [with T = int]}} + // expected-error@#dr1391-C {{type 'double' cannot be used prior to '::' because it has no members}} + // expected-note@#dr1391-c {{in instantiation of template class 'dr1391::C' requested here}} template struct D {}; // No deduction is performed for parameters with no deducible template-parameters, therefore types do not need to match. @@ -444,28 +569,36 @@ namespace dr1391 { // dr1391: partial void test_b() { b(0, 0); // ok, deduction fails prior to forming a conversion sequence and instantiating C // FIXME: The "while substituting" note should point at the overload candidate. - b(0, 0); // expected-note {{instantiation of}} expected-note {{while substituting}} + b(0, 0); // #dr1391-b } template struct Id { typedef T type; }; template void c(T, typename Id >::type); void test_c() { // Implicit conversion sequences for dependent types are checked later. - c(0.0, 0); // expected-note {{instantiation of}} + c(0.0, 0); // #dr1391-c } namespace partial_ordering { // FIXME: Second template should be considered more specialized because non-dependent parameter is ignored. - template int a(T, short) = delete; // expected-error 0-1{{extension}} expected-note {{candidate}} - template int a(T*, char); // expected-note {{candidate}} - int test_a = a((int*)0, 0); // FIXME: expected-error {{ambiguous}} + template int a(T, short) = delete; // #dr1391-a-short + // cxx98-error@-1 {{deleted function definitions are a C++11 extension}} + template int a(T*, char); // #dr1391-a-char + int test_a = a((int*)0, 0); + // expected-error@-1 {{call to 'a' is ambiguous}} FIXME + // expected-note@#dr1391-a-short {{candidate function [with T = int *] has been explicitly deleted}} + // expected-note@#dr1391-a-char {{candidate function [with T = int]}} // FIXME: Second template should be considered more specialized: // deducing #1 from #2 ignores the second P/A pair, so deduction succeeds, // deducing #2 from #1 fails to deduce T, so deduction fails. - template int b(T, int) = delete; // expected-error 0-1{{extension}} expected-note {{candidate}} - template int b(T*, U); // expected-note {{candidate}} - int test_b = b((int*)0, 0); // FIXME: expected-error {{ambiguous}} + template int b(T, int) = delete; // #dr1391-b-int + // cxx98-error@-1 {{deleted function definitions are a C++11 extension}} + template int b(T*, U); // #dr1391-b-U + int test_b = b((int*)0, 0); + // expected-error@-1 {{call to 'b' is ambiguous}} FIXME + // expected-note@#dr1391-b-int {{candidate function [with T = int *] has been explicitly deleted}} + // expected-note@#dr1391-b-U {{candidate function [with T = int, U = int]}} // Unintended consequences: because partial ordering does not consider // explicit template arguments, and deduction from a non-dependent type @@ -499,26 +632,26 @@ namespace dr1395 { // dr1395: 16 namespace dr1397 { // dr1397: 3.2 #if __cplusplus >= 201103L -struct A { // #dr1397-struct-A - void *p = A{}; // #dr1397-void-p -#if __cplusplus == 201103L - // expected-error@#dr1397-struct-A {{default member initializer for 'p' needed within definition of enclosing class 'A' outside of member functions}} - // expected-note@#dr1397-void-p {{in evaluation of exception specification for 'dr1397::A::A' needed here}} - // expected-note@#dr1397-void-p {{default member initializer declared here}} -#elif __cplusplus >= 201402L - // expected-error@#dr1397-void-p {{default member initializer for 'p' needed within definition of enclosing class 'A' outside of member functions}} - // expected-note@#dr1397-void-p {{default member initializer declared here}} -#endif +struct A { +// cxx11-error@-1 {{default member initializer for 'p' needed within definition of enclosing class 'A' outside of member functions}} +// cxx11-note@#dr1397-p {{in evaluation of exception specification for 'dr1397::A::A' needed here}} +// cxx11-note@#dr1397-p {{default member initializer declared here}} + void *p = A{}; // #dr1397-p + // since-cxx14-error@-1 {{default member initializer for 'p' needed within definition of enclosing class 'A' outside of member functions}} + // since-cxx14-note@-2 {{default member initializer declared here}} operator void*() const { return nullptr; } }; #endif } // namespace dr1397 namespace dr1399 { // dr1399: dup 1388 - template void f(T..., int, T...) {} // expected-note {{candidate}} expected-error 0-1{{C++11}} + template void f(T..., int, T...) {} // #dr1399-f + // cxx98-error@-1 {{variadic templates are a C++11 extension}} void g() { f(0); f(0, 0, 0); - f(0, 0, 0); // expected-error {{no match}} + f(0, 0, 0); + // expected-error@-1 {{no matching function for call to 'f'}} + // expected-note@#dr1399-f {{candidate template ignored: deduced packs of different lengths for parameter 'T' (<> vs. )}} } } diff --git a/clang/test/CXX/drs/dr14xx.cpp b/clang/test/CXX/drs/dr14xx.cpp index ea41a03d3587a80284b7557f6e403e055bcfbbcf..d262f6f9dcab796f0d7105d08496e677a8a2c5e3 100644 --- a/clang/test/CXX/drs/dr14xx.cpp +++ b/clang/test/CXX/drs/dr14xx.cpp @@ -1,8 +1,10 @@ -// RUN: %clang_cc1 -std=c++98 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++11 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++14 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++17 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++2a %s -verify -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++98 %s -verify=expected -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++11 %s -verify=expected,cxx11-17,since-cxx11, -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++14 %s -verify=expected,cxx14-17,cxx11-17,since-cxx11,since-cxx14 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++17 %s -verify=expected,cxx14-17,cxx11-17,since-cxx11,since-cxx14 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++20 %s -verify=expected,since-cxx11,since-cxx14,since-cxx20 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++23 %s -verify=expected,since-cxx11,since-cxx14,since-cxx20 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++2c %s -verify=expected,since-cxx11,since-cxx14,since-cxx20 -fexceptions -fcxx-exceptions -pedantic-errors namespace dr1413 { // dr1413: 12 template struct Check { @@ -15,24 +17,41 @@ namespace dr1413 { // dr1413: 12 void d(); void f() { - Check::type *var1; // expected-error {{undeclared identifier 'var1'}} - Check::type *var2; // ok, variable declaration expected-note 0+{{here}} - Check::type *var3; // expected-error {{undeclared identifier 'var3'}} - Check::type *var4; // expected-error {{undeclared identifier 'var4'}} + Check::type *var1; + // expected-error@-1 {{use of undeclared identifier 'var1'}} + + // ok, variable declaration + Check::type *var2; // #dr1413-var2 + Check::type *var3; + // expected-error@-1 {{use of undeclared identifier 'var3'}} + // expected-note@#dr1413-var2 {{'var2' declared here}} + Check::type *var4; + // expected-error@-1 {{use of undeclared identifier 'var4'}} + // expected-note@#dr1413-var2 {{'var2' declared here}} + // value-dependent because of the implied type-dependent 'this->', not because of 'd' - Check::type *var5; // expected-error {{undeclared identifier 'var5'}} + Check::type *var5; + // expected-error@-1 {{use of undeclared identifier 'var5'}} + // expected-note@#dr1413-var2 {{'var2' declared here}} + // value-dependent because of the value-dependent '&' operator, not because of 'A::d' - Check::type *var5; // expected-error {{undeclared identifier 'var5'}} + Check::type *var5; + // expected-error@-1 {{use of undeclared identifier 'var5'}} + // expected-note@#dr1413-var2 {{'var2' declared here}} } }; } namespace dr1423 { // dr1423: 11 #if __cplusplus >= 201103L - bool b1 = nullptr; // expected-error {{cannot initialize}} - bool b2(nullptr); // expected-warning {{implicit conversion of nullptr constant to 'bool'}} - bool b3 = {nullptr}; // expected-error {{cannot initialize}} - bool b4{nullptr}; // expected-warning {{implicit conversion of nullptr constant to 'bool'}} + bool b1 = nullptr; + // since-cxx11-error@-1 {{cannot initialize a variable of type 'bool' with an rvalue of type 'std::nullptr_t'}} + bool b2(nullptr); + // since-cxx11-warning@-1 {{implicit conversion of nullptr constant to 'bool'}} + bool b3 = {nullptr}; + // since-cxx11-error@-1 {{cannot initialize a variable of type 'bool' with an rvalue of type 'std::nullptr_t'}} + bool b4{nullptr}; + // since-cxx11-warning@-1 {{implicit conversion of nullptr constant to 'bool'}} #endif } @@ -62,7 +81,8 @@ namespace dr1432 { // dr1432: 16 namespace dr1443 { // dr1443: yes struct A { int i; - A() { void foo(int=i); } // expected-error {{default argument references 'this'}} + A() { void foo(int=i); } + // expected-error@-1 {{default argument references 'this'}} }; } @@ -70,49 +90,54 @@ namespace dr1460 { // dr1460: 3.5 #if __cplusplus >= 201103L namespace DRExample { union A { - union {}; // expected-error {{does not declare anything}} - union {}; // expected-error {{does not declare anything}} + union {}; + // expected-error@-1 {{declaration does not declare anything}} + union {}; + // expected-error@-1 {{declaration does not declare anything}} constexpr A() {} }; constexpr A a = A(); union B { - union {}; // expected-error {{does not declare anything}} - union {}; // expected-error {{does not declare anything}} + union {}; + // expected-error@-1 {{declaration does not declare anything}} + union {}; + // expected-error@-1 {{declaration does not declare anything}} constexpr B() = default; }; constexpr B b = B(); union C { - union {}; // expected-error {{does not declare anything}} - union {}; // expected-error {{does not declare anything}} + union {}; + // expected-error@-1 {{declaration does not declare anything}} + union {}; + // expected-error@-1 {{declaration does not declare anything}} }; constexpr C c = C(); -#if __cplusplus > 201103L +#if __cplusplus >= 201403L constexpr void f() { C c; } static_assert((f(), true), ""); #endif } union A {}; - union B { int n; }; // expected-note 0+{{here}} + union B { int n; }; // #dr1460-B union C { int n = 0; }; - struct D { union {}; }; // expected-error {{does not declare anything}} - struct E { union { int n; }; }; // expected-note 0+{{here}} + struct D { union {}; }; + // expected-error@-1 {{declaration does not declare anything}} + struct E { union { int n; }; }; // #dr1460-E struct F { union { int n = 0; }; }; struct X { friend constexpr A::A() noexcept; friend constexpr B::B() noexcept; -#if __cplusplus <= 201703L - // expected-error@-2 {{follows non-constexpr declaration}} -#endif + // cxx11-17-error@-1 {{constexpr declaration of 'B' follows non-constexpr declaration}} + // cxx11-17-note@#dr1460-B {{previous declaration is here}} friend constexpr C::C() noexcept; friend constexpr D::D() noexcept; friend constexpr E::E() noexcept; -#if __cplusplus <= 201703L - // expected-error@-2 {{follows non-constexpr declaration}} -#endif + // cxx11-17-error@-1 {{constexpr declaration of 'E' follows non-constexpr declaration}} + // cxx11-17-note@#dr1460-E {{previous declaration is here}} friend constexpr F::F() noexcept; }; @@ -128,79 +153,77 @@ namespace dr1460 { // dr1460: 3.5 namespace Defaulted { union A { constexpr A() = default; }; union B { int n; constexpr B() = default; }; -#if __cplusplus <= 201703L - // expected-error@-2 {{not constexpr}} -#endif + // cxx11-17-error@-1 {{defaulted definition of default constructor is not constexpr}} union C { int n = 0; constexpr C() = default; }; - struct D { union {}; constexpr D() = default; }; // expected-error {{does not declare anything}} + struct D { union {}; constexpr D() = default; }; + // expected-error@-1 {{declaration does not declare anything}} struct E { union { int n; }; constexpr E() = default; }; -#if __cplusplus <= 201703L - // expected-error@-2 {{not constexpr}} -#endif + // cxx11-17-error@-1 {{defaulted definition of default constructor is not constexpr}} struct F { union { int n = 0; }; constexpr F() = default; }; struct G { union { int n = 0; }; union { int m; }; constexpr G() = default; }; -#if __cplusplus <= 201703L - // expected-error@-2 {{not constexpr}} -#endif + // cxx11-17-error@-1 {{defaulted definition of default constructor is not constexpr}} struct H { union { int n = 0; }; - union { // expected-note 0-2{{member not initialized}} + union { // #dr1460-H-union int m; }; constexpr H() {} -#if __cplusplus <= 201703L - // expected-error@-2 {{initialize all members}} -#endif + // cxx11-17-error@-1 {{constexpr constructor that does not initialize all members is a C++20 extension}} + // cxx11-17-note@#dr1460-H-union {{member not initialized by constructor}} constexpr H(bool) : m(1) {} constexpr H(char) : n(1) {} -#if __cplusplus <= 201703L - // expected-error@-2 {{initialize all members}} -#endif + // cxx11-17-error@-1 {{constexpr constructor that does not initialize all members is a C++20 extension}} + // cxx11-17-note@#dr1460-H-union {{member not initialized by constructor}} constexpr H(double) : m(1), n(1) {} }; } -#if __cplusplus > 201103L +#if __cplusplus >= 201403L template constexpr bool check() { - T t; -#if __cplusplus <= 201703L - // expected-note-re@-2 2{{non-constexpr constructor '{{[BE]}}'}} -#endif + T t; // #dr1460-t return true; } static_assert(check(), ""); - static_assert(check(), ""); -#if __cplusplus <= 201703L - // expected-error@-2 {{constant}} expected-note@-2 {{in call}} -#endif + static_assert(check(), ""); // #dr1460-check-B + // cxx14-17-error@-1 {{static assertion expression is not an integral constant expression}} + // cxx14-17-note@#dr1460-t {{non-constexpr constructor 'B' cannot be used in a constant expression}} + // cxx14-17-note@#dr1460-check-B {{in call to 'check()'}} + // cxx14-17-note@#dr1460-B {{declared here}} static_assert(check(), ""); static_assert(check(), ""); - static_assert(check(), ""); -#if __cplusplus <= 201703L - // expected-error@-2 {{constant}} expected-note@-2 {{in call}} -#endif + static_assert(check(), ""); // #dr1460-check-E + // cxx14-17-error@-1 {{static assertion expression is not an integral constant expression}} + // cxx14-17-note@#dr1460-t {{non-constexpr constructor 'E' cannot be used in a constant expression}} + // cxx14-17-note@#dr1460-check-E {{in call to 'check()'}} + // cxx14-17-note@#dr1460-E {{declared here}} static_assert(check(), ""); #endif union G { - int a = 0; // expected-note {{previous initialization is here}} - int b = 0; // expected-error {{initializing multiple members of union}} + int a = 0; // #dr1460-G-a + int b = 0; + // expected-error@-1 {{initializing multiple members of union}} + // expected-note@#dr1460-G-a {{previous initialization is here}} }; union H { union { - int a = 0; // expected-note {{previous initialization is here}} + int a = 0; // #dr1460-H-a }; union { - int b = 0; // expected-error {{initializing multiple members of union}} + int b = 0; + // expected-error@-1 {{initializing multiple members of union}} + // expected-note@#dr1460-H-a {{previous initialization is here}} }; }; struct I { union { - int a = 0; // expected-note {{previous initialization is here}} - int b = 0; // expected-error {{initializing multiple members of union}} + int a = 0; // #dr1460-I-a + int b = 0; + // expected-error@-1 {{initializing multiple members of union}} + // expected-note@#dr1460-I-a {{previous initialization is here}} }; }; struct J { @@ -223,14 +246,24 @@ namespace dr1460 { // dr1460: 3.5 constexpr B(const char*) {} }; static_assert(B().a == 1, ""); - static_assert(B().b == 2, ""); // expected-error {{constant}} expected-note {{read of}} - static_assert(B('x').a == 0, ""); // expected-error {{constant}} expected-note {{read of}} + static_assert(B().b == 2, ""); + // expected-error@-1 {{static assertion expression is not an integral constant expression}} + // expected-note@-2 {{read of member 'b' of union with active member 'a' is not allowed in a constant expression}} + static_assert(B('x').a == 0, ""); + // expected-error@-1 {{static assertion expression is not an integral constant expression}} + // expected-note@-2 {{read of member 'a' of union with active member 'b' is not allowed in a constant expression}} static_assert(B('x').b == 4, ""); - static_assert(B(123).b == 2, ""); // expected-error {{constant}} expected-note {{read of}} + static_assert(B(123).b == 2, ""); + // expected-error@-1 {{static assertion expression is not an integral constant expression}} + // expected-note@-2 {{read of member 'b' of union with active member 'c' is not allowed in a constant expression}} static_assert(B(123).c == 3, ""); - static_assert(B("").a == 1, ""); // expected-error {{constant}} expected-note {{read of}} + static_assert(B("").a == 1, ""); + // expected-error@-1 {{static assertion expression is not an integral constant expression}} + // expected-note@-2 {{read of member 'a' of union with active member 'b' is not allowed in a constant expression}} static_assert(B("").b == 2, ""); - static_assert(B("").c == 3, ""); // expected-error {{constant}} expected-note {{read of}} + static_assert(B("").c == 3, ""); + // expected-error@-1 {{static assertion expression is not an integral constant expression}} + // expected-note@-2 {{read of member 'c' of union with active member 'b' is not allowed in a constant expression}} struct C { union { int a, b = 2, c; }; @@ -243,31 +276,55 @@ namespace dr1460 { // dr1460: 3.5 }; static_assert(C().a == 1, ""); - static_assert(C().b == 2, ""); // expected-error {{constant}} expected-note {{read of}} - static_assert(C().d == 4, ""); // expected-error {{constant}} expected-note {{read of}} + static_assert(C().b == 2, ""); + // expected-error@-1 {{static assertion expression is not an integral constant expression}} + // expected-note@-2 {{read of member 'b' of union with active member 'a' is not allowed in a constant expression}} + static_assert(C().d == 4, ""); + // expected-error@-1 {{static assertion expression is not an integral constant expression}} + // expected-note@-2 {{read of member 'd' of union with active member 'e' is not allowed in a constant expression}} static_assert(C().e == 5, ""); - static_assert(C('x').b == 2, ""); // expected-error {{constant}} expected-note {{read of}} + static_assert(C('x').b == 2, ""); + // expected-error@-1 {{static assertion expression is not an integral constant expression}} + // expected-note@-2 {{read of member 'b' of union with active member 'c' is not allowed in a constant expression}} static_assert(C('x').c == 3, ""); - static_assert(C('x').d == 4, ""); // expected-error {{constant}} expected-note {{read of}} + static_assert(C('x').d == 4, ""); + // expected-error@-1 {{static assertion expression is not an integral constant expression}} + // expected-note@-2 {{read of member 'd' of union with active member 'e' is not allowed in a constant expression}} static_assert(C('x').e == 5, ""); static_assert(C(1).b == 2, ""); - static_assert(C(1).c == 3, ""); // expected-error {{constant}} expected-note {{read of}} + static_assert(C(1).c == 3, ""); + // expected-error@-1 {{static assertion expression is not an integral constant expression}} + // expected-note@-2 {{read of member 'c' of union with active member 'b' is not allowed in a constant expression}} static_assert(C(1).d == 4, ""); - static_assert(C(1).e == 5, ""); // expected-error {{constant}} expected-note {{read of}} + static_assert(C(1).e == 5, ""); + // expected-error@-1 {{static assertion expression is not an integral constant expression}} + // expected-note@-2 {{read of member 'e' of union with active member 'd' is not allowed in a constant expression}} static_assert(C(1.f).b == 2, ""); - static_assert(C(1.f).c == 3, ""); // expected-error {{constant}} expected-note {{read of}} - static_assert(C(1.f).e == 5, ""); // expected-error {{constant}} expected-note {{read of}} + static_assert(C(1.f).c == 3, ""); + // expected-error@-1 {{static assertion expression is not an integral constant expression}} + // expected-note@-2 {{read of member 'c' of union with active member 'b' is not allowed in a constant expression}} + static_assert(C(1.f).e == 5, ""); + // expected-error@-1 {{static assertion expression is not an integral constant expression}} + // expected-note@-2 {{read of member 'e' of union with active member 'f' is not allowed in a constant expression}} static_assert(C(1.f).f == 6, ""); - static_assert(C("").a == 1, ""); // expected-error {{constant}} expected-note {{read of}} + static_assert(C("").a == 1, ""); + // expected-error@-1 {{static assertion expression is not an integral constant expression}} + // expected-note@-2 {{read of member 'a' of union with active member 'b' is not allowed in a constant expression}} static_assert(C("").b == 2, ""); - static_assert(C("").c == 3, ""); // expected-error {{constant}} expected-note {{read of}} - static_assert(C("").d == 4, ""); // expected-error {{constant}} expected-note {{read of}} + static_assert(C("").c == 3, ""); + // expected-error@-1 {{static assertion expression is not an integral constant expression}} + // expected-note@-2 {{read of member 'c' of union with active member 'b' is not allowed in a constant expression}} + static_assert(C("").d == 4, ""); + // expected-error@-1 {{static assertion expression is not an integral constant expression}} + // expected-note@-2 {{read of member 'd' of union with active member 'e' is not allowed in a constant expression}} static_assert(C("").e == 5, ""); - static_assert(C("").f == 6, ""); // expected-error {{constant}} expected-note {{read of}} + static_assert(C("").f == 6, ""); + // expected-error@-1 {{static assertion expression is not an integral constant expression}} + // expected-note@-2 {{read of member 'f' of union with active member 'e' is not allowed in a constant expression}} struct D; extern const D d; @@ -315,8 +372,10 @@ namespace std { const _E* end() const {return __begin_ + __size_;} }; } // std +#endif namespace dr1467 { // dr1467: 3.7 c++11 +#if __cplusplus >= 201103L // Note that the change to [over.best.ics] was partially undone by DR2076; // the resulting rule is tested with the tests for that change. @@ -382,9 +441,12 @@ namespace dr1467 { // dr1467: 3.7 c++11 X x; X x2{x}; - void f1(int); // expected-note {{candidate function}} - void f1(std::initializer_list) = delete; // expected-note {{candidate function has been explicitly deleted}} - void g1() { f1({42}); } // expected-error {{call to deleted function 'f1'}} + void f1(int); // #dr1467-f1 + void f1(std::initializer_list) = delete; // #dr1467-f1-deleted + void g1() { f1({42}); } + // since-cxx11-error@-1 {{call to deleted function 'f1'}} + // since-cxx11-note@#dr1467-f1 {{candidate function}} + // since-cxx11-note@#dr1467-f1-deleted {{candidate function has been explicitly deleted}} template struct Pair { @@ -394,9 +456,12 @@ namespace dr1467 { // dr1467: 3.7 c++11 String(const char *); }; - void f2(Pair); // expected-note {{candidate function}} - void f2(std::initializer_list) = delete; // expected-note {{candidate function has been explicitly deleted}} - void g2() { f2({"foo", "bar"}); } // expected-error {{call to deleted function 'f2'}} + void f2(Pair); // #dr1467-f2 + void f2(std::initializer_list) = delete; // #dr1467-f2-deleted + void g2() { f2({"foo", "bar"}); } + // since-cxx11-error@-1 {{call to deleted function 'f2'}} + // since-cxx11-note@#dr1467-f2 {{candidate function}} + // since-cxx11-note@#dr1467-f2-deleted {{candidate function has been explicitly deleted}} } // dr_example namespace nonaggregate { @@ -453,84 +518,151 @@ namespace dr1467 { // dr1467: 3.7 c++11 } } // namespace NonAmbiguous -#if __cplusplus >= 201103L namespace StringLiterals { // When the array size is 4 the call will attempt to bind an lvalue to an // rvalue and fail. Therefore #2 will be called. (rsmith will bring this // issue to CWG) - void f(const char(&&)[4]); // expected-note 2 {{expects an rvalue}} expected-note 3 {{no known conversion}} - void f(const char(&&)[5]) = delete; // expected-note 2 {{candidate function has been explicitly deleted}} expected-note 3 {{no known conversion}} - void f(const wchar_t(&&)[4]); // expected-note {{expects an rvalue}} expected-note 4 {{no known conversion}} - void f(const wchar_t(&&)[5]) = delete; // expected-note {{candidate function has been explicitly deleted}} expected-note 4 {{no known conversion}} + void f(const char(&&)[4]); // #dr1467-f-char-4 + void f(const char(&&)[5]) = delete; // #dr1467-f-char-5 + void f(const wchar_t(&&)[4]); // #dr1467-f-wchar-4 + void f(const wchar_t(&&)[5]) = delete; // #dr1467-f-wchar-5 #if __cplusplus >= 202002L - void f2(const char8_t(&&)[4]); // expected-note {{expects an rvalue}} - void f2(const char8_t(&&)[5]) = delete; // expected-note {{candidate function has been explicitly deleted}} + void f2(const char8_t(&&)[4]); // #dr1467-f2-char8-4 + void f2(const char8_t(&&)[5]) = delete; // #dr1467-f2-char8-5 #endif - void f(const char16_t(&&)[4]); // expected-note {{expects an rvalue}} expected-note 4 {{no known conversion}} - void f(const char16_t(&&)[5]) = delete; // expected-note {{candidate function has been explicitly deleted}} expected-note 4 {{no known conversion}} - void f(const char32_t(&&)[4]); // expected-note {{expects an rvalue}} expected-note 4 {{no known conversion}} - void f(const char32_t(&&)[5]) = delete; // expected-note {{candidate function has been explicitly deleted}} expected-note 4 {{no known conversion}} + void f(const char16_t(&&)[4]); // #dr1467-f-char16-4 + void f(const char16_t(&&)[5]) = delete; // #dr1467-f-char16-5 + void f(const char32_t(&&)[4]); // #dr1467-f-char32-4 + void f(const char32_t(&&)[5]) = delete; // #dr1467-f-char32-5 void g() { - f({"abc"}); // expected-error {{call to deleted function 'f'}} - f({((("abc")))}); // expected-error {{call to deleted function 'f'}} - f({L"abc"}); // expected-error {{call to deleted function 'f'}} + f({"abc"}); + // since-cxx11-error@-1 {{call to deleted function 'f'}} + // since-cxx11-note@#dr1467-f-char-5 {{candidate function has been explicitly deleted}} + // since-cxx11-note@#dr1467-f-char-4 {{candidate function not viable: expects an rvalue for 1st argument}} + // since-cxx11-note@#dr1467-f-wchar-4 {{candidate function not viable: no known conversion from 'const char[4]' to 'const wchar_t' for 1st argument}} + // since-cxx11-note@#dr1467-f-wchar-5 {{candidate function not viable: no known conversion from 'const char[4]' to 'const wchar_t' for 1st argument}} + // since-cxx11-note@#dr1467-f-char16-4 {{candidate function not viable: no known conversion from 'const char[4]' to 'const char16_t' for 1st argument}} + // since-cxx11-note@#dr1467-f-char16-5 {{candidate function not viable: no known conversion from 'const char[4]' to 'const char16_t' for 1st argument}} + // since-cxx11-note@#dr1467-f-char32-4 {{candidate function not viable: no known conversion from 'const char[4]' to 'const char32_t' for 1st argument}} + // since-cxx11-note@#dr1467-f-char32-5 {{candidate function not viable: no known conversion from 'const char[4]' to 'const char32_t' for 1st argument}} + f({((("abc")))}); + // since-cxx11-error@-1 {{call to deleted function 'f'}} + // since-cxx11-note@#dr1467-f-char-5 {{candidate function has been explicitly deleted}} + // since-cxx11-note@#dr1467-f-char-4 {{candidate function not viable: expects an rvalue for 1st argument}} + // since-cxx11-note@#dr1467-f-wchar-4 {{candidate function not viable: no known conversion from 'const char[4]' to 'const wchar_t' for 1st argument}} + // since-cxx11-note@#dr1467-f-wchar-5 {{candidate function not viable: no known conversion from 'const char[4]' to 'const wchar_t' for 1st argument}} + // since-cxx11-note@#dr1467-f-char16-4 {{candidate function not viable: no known conversion from 'const char[4]' to 'const char16_t' for 1st argument}} + // since-cxx11-note@#dr1467-f-char16-5 {{candidate function not viable: no known conversion from 'const char[4]' to 'const char16_t' for 1st argument}} + // since-cxx11-note@#dr1467-f-char32-4 {{candidate function not viable: no known conversion from 'const char[4]' to 'const char32_t' for 1st argument}} + // since-cxx11-note@#dr1467-f-char32-5 {{candidate function not viable: no known conversion from 'const char[4]' to 'const char32_t' for 1st argument}} + f({L"abc"}); + // since-cxx11-error@-1 {{call to deleted function 'f'}} + // since-cxx11-note@#dr1467-f-wchar-5 {{candidate function has been explicitly deleted}} + // since-cxx11-note@#dr1467-f-char-4 {{candidate function not viable: no known conversion from 'const wchar_t[4]' to 'const char' for 1st argument}} + // since-cxx11-note@#dr1467-f-char-5 {{candidate function not viable: no known conversion from 'const wchar_t[4]' to 'const char' for 1st argument}} + // since-cxx11-note@#dr1467-f-wchar-4 {{candidate function not viable: expects an rvalue for 1st argument}} + // since-cxx11-note@#dr1467-f-char16-4 {{candidate function not viable: no known conversion from 'const wchar_t[4]' to 'const char16_t' for 1st argument}} + // since-cxx11-note@#dr1467-f-char16-5 {{candidate function not viable: no known conversion from 'const wchar_t[4]' to 'const char16_t' for 1st argument}} + // since-cxx11-note@#dr1467-f-char32-4 {{candidate function not viable: no known conversion from 'const wchar_t[4]' to 'const char32_t' for 1st argument}} + // since-cxx11-note@#dr1467-f-char32-5 {{candidate function not viable: no known conversion from 'const wchar_t[4]' to 'const char32_t' for 1st argument}} #if __cplusplus >= 202002L - f2({u8"abc"}); // expected-error {{call to deleted function 'f2'}} + f2({u8"abc"}); + // since-cxx20-error@-1 {{call to deleted function 'f2'}} + // since-cxx20-note@#dr1467-f2-char8-5 {{candidate function has been explicitly deleted}} + // since-cxx20-note@#dr1467-f2-char8-4 {{candidate function not viable: expects an rvalue for 1st argument}} #endif - f({uR"(abc)"}); // expected-error {{call to deleted function 'f'}} - f({(UR"(abc)")}); // expected-error {{call to deleted function 'f'}} + f({uR"(abc)"}); + // since-cxx11-error@-1 {{call to deleted function 'f'}} + // since-cxx11-note@#dr1467-f-char16-5 {{candidate function has been explicitly deleted}} + // since-cxx11-note@#dr1467-f-char-4 {{candidate function not viable: no known conversion from 'const char16_t[4]' to 'const char' for 1st argument}} + // since-cxx11-note@#dr1467-f-char-5 {{candidate function not viable: no known conversion from 'const char16_t[4]' to 'const char' for 1st argument}} + // since-cxx11-note@#dr1467-f-wchar-4 {{candidate function not viable: no known conversion from 'const char16_t[4]' to 'const wchar_t' for 1st argument}} + // since-cxx11-note@#dr1467-f-wchar-5 {{candidate function not viable: no known conversion from 'const char16_t[4]' to 'const wchar_t' for 1st argument}} + // since-cxx11-note@#dr1467-f-char16-4 {{candidate function not viable: expects an rvalue for 1st argument}} + // since-cxx11-note@#dr1467-f-char32-4 {{candidate function not viable: no known conversion from 'const char16_t[4]' to 'const char32_t' for 1st argument}} + // since-cxx11-note@#dr1467-f-char32-5 {{candidate function not viable: no known conversion from 'const char16_t[4]' to 'const char32_t' for 1st argument}} + f({(UR"(abc)")}); + // since-cxx11-error@-1 {{call to deleted function 'f'}} + // since-cxx11-note@#dr1467-f-char32-5 {{candidate function has been explicitly deleted}} + // since-cxx11-note@#dr1467-f-char-4 {{candidate function not viable: no known conversion from 'const char32_t[4]' to 'const char' for 1st argument}} + // since-cxx11-note@#dr1467-f-char-5 {{candidate function not viable: no known conversion from 'const char32_t[4]' to 'const char' for 1st argument}} + // since-cxx11-note@#dr1467-f-wchar-4 {{candidate function not viable: no known conversion from 'const char32_t[4]' to 'const wchar_t' for 1st argument}} + // since-cxx11-note@#dr1467-f-wchar-5 {{candidate function not viable: no known conversion from 'const char32_t[4]' to 'const wchar_t' for 1st argument}} + // since-cxx11-note@#dr1467-f-char16-4 {{candidate function not viable: no known conversion from 'const char32_t[4]' to 'const char16_t' for 1st argument}} + // since-cxx11-note@#dr1467-f-char16-5 {{candidate function not viable: no known conversion from 'const char32_t[4]' to 'const char16_t' for 1st argument}} + // since-cxx11-note@#dr1467-f-char32-4 {{candidate function not viable: expects an rvalue for 1st argument}} } } // namespace StringLiterals #endif } // dr1467 -namespace dr1479 { // dr1479: yes - int operator"" _a(const char*, std::size_t = 0); // expected-error {{literal operator cannot have a default argument}} +namespace dr1479 { // dr1479: 3.1 +#if __cplusplus >= 201103L + int operator"" _a(const char*, std::size_t = 0); + // since-cxx11-error@-1 {{literal operator cannot have a default argument}} +#endif } -namespace dr1482 { // dr1482: yes +namespace dr1482 { // dr1482: 3.0 // NB: sup 2516, test reused there #if __cplusplus >= 201103L template struct S { typedef char I; }; enum E2 : S::I { e }; -// expected-error@-1 {{use of undeclared identifier 'E2'}} +// since-cxx11-error@-1 {{use of undeclared identifier 'E2'}} #endif } // namespace dr1482 namespace dr1490 { // dr1490: 3.7 c++11 +#if __cplusplus >= 201103L // List-initialization from a string literal - char s[4]{"abc"}; // Ok - std::initializer_list{"abc"}; // expected-error {{expected unqualified-id}}} + char s[4]{"abc"}; // Ok + std::initializer_list{"abc"}; + // since-cxx11-error@-1 {{expected unqualified-id}}} +#endif } // dr1490 namespace dr1495 { // dr1495: 4 +#if __cplusplus >= 201103L // Deduction succeeds in both directions. - template struct A {}; // expected-note {{template is declared here}} - template struct A {}; // expected-error {{class template partial specialization is not more specialized}} + template struct A {}; // #dr1495-A + template struct A {}; + // since-cxx11-error@-1 {{class template partial specialization is not more specialized than the primary template}} + // since-cxx11-note@#dr1495-A {{template is declared here}} // Primary template is more specialized. - template struct B {}; // expected-note {{template is declared here}} - template struct B {}; // expected-error {{not more specialized}} + template struct B {}; // #dr1495-B + template struct B {}; + // since-cxx11-error@-1 {{class template partial specialization is not more specialized than the primary template}} + // since-cxx11-note@#dr1495-B {{template is declared here}} // Deduction fails in both directions. - template struct C {}; // expected-note {{template is declared here}} - template struct C<0, Ts...> {}; // expected-error {{not more specialized}} + template struct C {}; // #dr1495-C + template struct C<0, Ts...> {}; + // since-cxx11-error@-1 {{class template partial specialization is not more specialized than the primary template}} + // since-cxx11-note@#dr1495-C {{template is declared here}} #if __cplusplus >= 201402L // Deduction succeeds in both directions. - template int a; // expected-note {{template is declared here}} - template int a; // expected-error {{variable template partial specialization is not more specialized}} + template int a; // #dr1495-a + template int a; + // since-cxx14-error@-1 {{variable template partial specialization is not more specialized than the primary template}} + // since-cxx14-note@#dr1495-a {{template is declared here}} // Primary template is more specialized. - template int b; // expected-note {{template is declared here}} - template int b; // expected-error {{not more specialized}} + template int b; // #dr1495-b + template int b; + // since-cxx14-error@-1 {{variable template partial specialization is not more specialized than the primary template}} + // since-cxx14-note@#dr1495-b {{template is declared here}} // Deduction fails in both directions. - template int c; // expected-note {{template is declared here}} - template int c<0, Ts...>; // expected-error {{not more specialized}} + template int c; // #dr1495-c + template int c<0, Ts...>; + // since-cxx14-error@-1 {{variable template partial specialization is not more specialized than the primary template}} + // since-cxx14-note@#dr1495-c {{template is declared here}} +#endif #endif } @@ -544,5 +676,3 @@ struct A { static_assert(__is_trivial(A), ""); #endif } - -#endif diff --git a/clang/test/CXX/drs/dr15xx.cpp b/clang/test/CXX/drs/dr15xx.cpp index c588891a75d6a88f27461a5dfca5edeb7081001f..007b42c74affb140788e38d0ddae1bd09548ba21 100644 --- a/clang/test/CXX/drs/dr15xx.cpp +++ b/clang/test/CXX/drs/dr15xx.cpp @@ -1,13 +1,18 @@ // RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -verify=expected -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -verify=expected -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -verify=expected,cxx14_17 -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -verify=expected,cxx17 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11,cxx11-14 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11,cxx11-14,cxx14-17 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11,since-cxx17 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx20,since-cxx11,since-cxx17 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx20,since-cxx11,since-cxx17 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -verify=expected,since-cxx20,since-cxx11,since-cxx17 -fexceptions -fcxx-exceptions -pedantic-errors namespace dr1512 { // dr1512: 4 void f(char *p) { - if (p > 0) {} // expected-error {{ordered comparison between pointer and zero}} + if (p > 0) {} + // expected-error@-1 {{ordered comparison between pointer and zero ('char *' and 'int')}} #if __cplusplus >= 201103L - if (p > nullptr) {} // expected-error {{invalid operands}} + if (p > nullptr) {} + // since-cxx11-error@-1 {{invalid operands to binary expression ('char *' and 'std::nullptr_t')}} #endif } bool g(int **x, const int **y) { @@ -28,10 +33,20 @@ namespace dr1512 { // dr1512: 4 template void composite_pointer_type_is_ord() { composite_pointer_type_is_base(); - typedef __typeof(val() < val()) cmp; // cxx17-warning 2 {{ordered comparison of function pointers}} - typedef __typeof(val() <= val()) cmp; // cxx17-warning 2 {{ordered comparison of function pointers}} - typedef __typeof(val() > val()) cmp; // cxx17-warning 2 {{ordered comparison of function pointers}} - typedef __typeof(val() >= val()) cmp; // cxx17-warning 2 {{ordered comparison of function pointers}} + typedef __typeof(val() < val()) cmp; // #dr1512-lt + // since-cxx17-warning@#dr1512-lt {{ordered comparison of function pointers ('int (*)() noexcept' and 'int (*)()')}} + // since-cxx17-note@#dr1512-noexcept-1st {{in instantiation of function template specialization 'dr1512::composite_pointer_type_is_ord' requested here}} + // since-cxx17-warning@#dr1512-lt {{ordered comparison of function pointers ('int (*)()' and 'int (*)() noexcept')}} + // since-cxx17-note@#dr1512-noexcept-2nd {{in instantiation of function template specialization 'dr1512::composite_pointer_type_is_ord' requested here}} + typedef __typeof(val() <= val()) cmp; + // since-cxx17-warning@-1 {{ordered comparison of function pointers ('int (*)() noexcept' and 'int (*)()')}} + // since-cxx17-warning@-2 {{ordered comparison of function pointers ('int (*)()' and 'int (*)() noexcept')}} + typedef __typeof(val() > val()) cmp; + // since-cxx17-warning@-1 {{ordered comparison of function pointers ('int (*)() noexcept' and 'int (*)()')}} + // since-cxx17-warning@-2 {{ordered comparison of function pointers ('int (*)()' and 'int (*)() noexcept')}} + typedef __typeof(val() >= val()) cmp; + // since-cxx17-warning@-1 {{ordered comparison of function pointers ('int (*)() noexcept' and 'int (*)()')}} + // since-cxx17-warning@-2 {{ordered comparison of function pointers ('int (*)()' and 'int (*)() noexcept')}} typedef bool cmp; } @@ -77,10 +92,11 @@ namespace dr1512 { // dr1512: 4 composite_pointer_type_is_unord(); no_composite_pointer_type(); no_composite_pointer_type(); + // since-cxx20-warning@-1 {{volatile-qualified return type 'volatile int' is deprecated}} -#if __cplusplus > 201402 - composite_pointer_type_is_ord(); // expected-note {{requested here}} - composite_pointer_type_is_ord(); // expected-note {{requested here}} +#if __cplusplus >= 201703L + composite_pointer_type_is_ord(); // #dr1512-noexcept-1st + composite_pointer_type_is_ord(); // #dr1512-noexcept-2nd composite_pointer_type_is_unord(); composite_pointer_type_is_unord(); // FIXME: This looks like a standard defect; these should probably all have type 'int (B::*)()'. @@ -113,24 +129,40 @@ namespace dr1512 { // dr1512: 4 } #if __cplusplus >= 201103L - template struct Wrap { operator T(); }; // expected-note 4{{converted to type 'std::nullptr_t'}} expected-note 4{{converted to type 'int *'}} + template struct Wrap { operator T(); }; // #dr1512-Wrap void test_overload() { using nullptr_t = decltype(nullptr); void(Wrap() == Wrap()); void(Wrap() != Wrap()); - void(Wrap() < Wrap()); // expected-error {{invalid operands}} - void(Wrap() > Wrap()); // expected-error {{invalid operands}} - void(Wrap() <= Wrap()); // expected-error {{invalid operands}} - void(Wrap() >= Wrap()); // expected-error {{invalid operands}} + void(Wrap() < Wrap()); + // since-cxx11-error@-1 {{invalid operands to binary expression ('Wrap' (aka 'Wrap') and 'Wrap' (aka 'Wrap'))}} + void(Wrap() > Wrap()); + // since-cxx11-error@-1 {{invalid operands to binary expression ('Wrap' (aka 'Wrap') and 'Wrap' (aka 'Wrap'))}} + void(Wrap() <= Wrap()); + // since-cxx11-error@-1 {{invalid operands to binary expression ('Wrap' (aka 'Wrap') and 'Wrap' (aka 'Wrap'))}} + void(Wrap() >= Wrap()); + // since-cxx11-error@-1 {{invalid operands to binary expression ('Wrap' (aka 'Wrap') and 'Wrap' (aka 'Wrap'))}} // Under dr1213, this is ill-formed: we select the builtin operator<(int*, int*) // but then only convert as far as 'nullptr_t', which we then can't convert to 'int*'. void(Wrap() == Wrap()); void(Wrap() != Wrap()); - void(Wrap() < Wrap()); // expected-error {{invalid operands to binary expression ('Wrap' (aka 'Wrap') and 'Wrap')}} - void(Wrap() > Wrap()); // expected-error {{invalid operands}} - void(Wrap() <= Wrap()); // expected-error {{invalid operands}} - void(Wrap() >= Wrap()); // expected-error {{invalid operands}} + void(Wrap() < Wrap()); + // since-cxx11-error@-1 {{invalid operands to binary expression ('Wrap' (aka 'Wrap') and 'Wrap')}} + // since-cxx11-note@#dr1512-Wrap {{first operand was implicitly converted to type 'std::nullptr_t'}} + // since-cxx11-note@#dr1512-Wrap {{second operand was implicitly converted to type 'int *'}} + void(Wrap() > Wrap()); + // since-cxx11-error@-1 {{invalid operands}} + // since-cxx11-note@#dr1512-Wrap {{first operand was implicitly converted to type 'std::nullptr_t'}} + // since-cxx11-note@#dr1512-Wrap{{second operand was implicitly converted to type 'int *'}} + void(Wrap() <= Wrap()); + // since-cxx11-error@-1 {{invalid operands}} + // since-cxx11-note@#dr1512-Wrap {{first operand was implicitly converted to type 'std::nullptr_t'}} + // since-cxx11-note@#dr1512-Wrap {{second operand was implicitly converted to type 'int *'}} + void(Wrap() >= Wrap()); + // since-cxx11-error@-1 {{invalid operands}} + // since-cxx11-note@#dr1512-Wrap {{first operand was implicitly converted to type 'std::nullptr_t'}} + // since-cxx11-note@#dr1512-Wrap {{second operand was implicitly converted to type 'int *'}} } #endif } @@ -138,8 +170,10 @@ namespace dr1512 { // dr1512: 4 namespace dr1514 { // dr1514: 11 #if __cplusplus >= 201103L struct S { - enum E : int {}; // expected-note {{previous}} - enum E : int {}; // expected-error {{redefinition}} + enum E : int {}; // #dr1514-E + enum E : int {}; + // since-cxx11-error@-1 {{redefinition of 'E'}} + // since-cxx11-note@#dr1514-E {{previous definition is here}} }; S::E se; // OK, complete type, not zero-width bitfield. @@ -149,91 +183,142 @@ namespace dr1514 { // dr1514: 11 namespace dr1518 { // dr1518: 4 #if __cplusplus >= 201103L -struct Z0 { // expected-note 0+ {{candidate}} - explicit Z0() = default; // expected-note 0+ {{here}} +struct Z0 { // #dr1518-Z0 + explicit Z0() = default; // #dr1518-Z0-ctor }; -struct Z { // expected-note 0+ {{candidate}} - explicit Z(); // expected-note 0+ {{here}} - explicit Z(int); // expected-note {{not a candidate}} - explicit Z(int, int); // expected-note 0+ {{here}} +struct Z { // #dr1518-Z + explicit Z(); // #dr1518-Z-ctor + explicit Z(int); // #dr1518-Z-int + explicit Z(int, int); // #dr1518-Z-int-int }; -template int Eat(T); // expected-note 0+ {{candidate}} +template int Eat(T); // #dr1518-Eat Z0 a; Z0 b{}; -Z0 c = {}; // expected-error {{explicit in copy-initialization}} -int i = Eat({}); // expected-error {{no matching function for call to 'Eat'}} - -Z c2 = {}; // expected-error {{explicit in copy-initialization}} -int i2 = Eat({}); // expected-error {{no matching function for call to 'Eat'}} -Z a1 = 1; // expected-error {{no viable conversion}} +Z0 c = {}; +// since-cxx11-error@-1 {{chosen constructor is explicit in copy-initialization}} +// since-cxx11-note@#dr1518-Z0-ctor {{explicit constructor declared here}} +int i = Eat({}); +// since-cxx11-error@-1 {{no matching function for call to 'Eat'}} +// since-cxx11-note@#dr1518-Eat {{candidate function template not viable: cannot convert initializer list argument to 'Z0'}} + +Z c2 = {}; +// since-cxx11-error@-1 {{chosen constructor is explicit in copy-initialization}} +// since-cxx11-note@#dr1518-Z-ctor {{explicit constructor declared here}} +int i2 = Eat({}); +// since-cxx11-error@-1 {{no matching function for call to 'Eat'}} +// since-cxx11-note@#dr1518-Eat {{candidate function template not viable: cannot convert initializer list argument to 'Z'}} +Z a1 = 1; +// since-cxx11-error@-1 {{no viable conversion from 'int' to 'Z'}} +// since-cxx11-note@#dr1518-Z {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'int' to 'const Z &' for 1st argument}} +// since-cxx11-note@#dr1518-Z {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'int' to 'Z &&' for 1st argument}} +// since-cxx11-note@#dr1518-Z-int {{explicit constructor is not a candidate}} Z a3 = Z(1); Z a2(1); Z *p = new Z(1); Z a4 = (Z)1; Z a5 = static_cast(1); -Z a6 = {4, 3}; // expected-error {{explicit in copy-initialization}} +Z a6 = {4, 3}; +// since-cxx11-error@-1 {{chosen constructor is explicit in copy-initialization}} +// since-cxx11-note@#dr1518-Z-int-int {{explicit constructor declared here}} -struct UserProvidedBaseCtor { // expected-note 0+ {{candidate}} +struct UserProvidedBaseCtor { // #dr1518-U UserProvidedBaseCtor() {} }; -struct DoesntInheritCtor : UserProvidedBaseCtor { // expected-note 0+ {{candidate}} +struct DoesntInheritCtor : UserProvidedBaseCtor { // #dr1518-D-U int x; }; DoesntInheritCtor I{{}, 42}; -#if __cplusplus <= 201402L -// expected-error@-2 {{no matching constructor}} -#endif - -struct BaseCtor { BaseCtor() = default; }; // expected-note 0+ {{candidate}} -struct InheritsCtor : BaseCtor { // expected-note 1+ {{candidate}} - using BaseCtor::BaseCtor; // expected-note 2 {{inherited here}} +// cxx11-14-error@-1 {{no matching constructor for initialization of 'DoesntInheritCtor'}} +// cxx11-14-note@#dr1518-D-U {{candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 2 were provided}} +// cxx11-14-note@#dr1518-D-U {{candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 2 were provided}} +// cxx11-14-note@#dr1518-D-U {{candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 2 were provided}} + +struct BaseCtor { BaseCtor() = default; }; // #dr1518-BC +struct InheritsCtor : BaseCtor { // #dr1518-I + using BaseCtor::BaseCtor; // #dr1518-I-using int x; }; -InheritsCtor II = {{}, 42}; // expected-error {{no matching constructor}} +InheritsCtor II = {{}, 42}; +// since-cxx11-error@-1 {{no matching constructor for initialization of 'InheritsCtor'}} +// since-cxx11-note@#dr1518-BC {{candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 2 were provided}} +// since-cxx11-note@#dr1518-I-using {{constructor from base class 'BaseCtor' inherited here}} +// since-cxx11-note@#dr1518-BC {{candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 2 were provided}} +// since-cxx11-note@#dr1518-I-using {{constructor from base class 'BaseCtor' inherited here}} +// since-cxx11-note@#dr1518-I {{candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 2 were provided}} +// since-cxx11-note@#dr1518-I {{candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 2 were provided}} +// since-cxx11-note@#dr1518-I {{candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 2 were provided}} namespace std_example { struct A { - explicit A() = default; // expected-note 2{{declared here}} + explicit A() = default; // #dr1518-A }; struct B : A { - explicit B() = default; // expected-note 2{{declared here}} + explicit B() = default; // #dr1518-B }; struct C { - explicit C(); // expected-note 2{{declared here}} + explicit C(); // #dr1518-C }; struct D : A { C c; - explicit D() = default; // expected-note 2{{declared here}} + explicit D() = default; // #dr1518-D }; template void f() { T t; // ok T u{}; // ok - T v = {}; // expected-error 4{{explicit}} + T v = {}; // #dr1518-v + // since-cxx11-error@#dr1518-v {{chosen constructor is explicit in copy-initialization}} + // since-cxx11-note@#dr1518-f-A {{in instantiation of function template specialization 'dr1518::std_example::f' requested here}} + // since-cxx11-note@#dr1518-A {{explicit constructor declared here}} + // since-cxx11-error@#dr1518-v {{chosen constructor is explicit in copy-initialization}} + // since-cxx11-note@#dr1518-f-B {{in instantiation of function template specialization 'dr1518::std_example::f' requested here}} + // since-cxx11-note@#dr1518-B {{explicit constructor declared here}} + // since-cxx11-error@#dr1518-v {{chosen constructor is explicit in copy-initialization}} + // since-cxx11-note@#dr1518-f-C {{in instantiation of function template specialization 'dr1518::std_example::f' requested here}} + // since-cxx11-note@#dr1518-C {{explicit constructor declared here}} + // since-cxx11-error@#dr1518-v {{chosen constructor is explicit in copy-initialization}} + // since-cxx11-note@#dr1518-f-D {{in instantiation of function template specialization 'dr1518::std_example::f' requested here}} + // since-cxx11-note@#dr1518-D {{explicit constructor declared here}} } template void g() { - void x(T t); // expected-note 4{{parameter}} - x({}); // expected-error 4{{explicit}} + void x(T t); // #dr1518-x + x({}); // #dr1518-x-call + // since-cxx11-error@#dr1518-x-call {{chosen constructor is explicit in copy-initialization}} + // since-cxx11-note@#dr1518-g-A {{in instantiation of function template specialization 'dr1518::std_example::g' requested here}} + // since-cxx11-note@#dr1518-A {{explicit constructor declared here}} + // since-cxx11-note@#dr1518-x {{passing argument to parameter 't' here}} + // since-cxx11-error@#dr1518-x-call {{chosen constructor is explicit in copy-initialization}} + // since-cxx11-note@#dr1518-g-B {{in instantiation of function template specialization 'dr1518::std_example::g' requested here}} + // since-cxx11-note@#dr1518-B {{explicit constructor declared here}} + // since-cxx11-note@#dr1518-x {{passing argument to parameter 't' here}} + // since-cxx11-error@#dr1518-x-call {{chosen constructor is explicit in copy-initialization}} + // since-cxx11-note@#dr1518-g-C {{in instantiation of function template specialization 'dr1518::std_example::g' requested here}} + // since-cxx11-note@#dr1518-C {{explicit constructor declared here}} + // since-cxx11-note@#dr1518-x {{passing argument to parameter 't' here}} + // since-cxx11-error@#dr1518-x-call {{chosen constructor is explicit in copy-initialization}} + // since-cxx11-note@#dr1518-g-D {{in instantiation of function template specialization 'dr1518::std_example::g' requested here}} + // since-cxx11-note@#dr1518-D {{explicit constructor declared here}} + // since-cxx11-note@#dr1518-x {{passing argument to parameter 't' here}} } void test() { - f(); // expected-note {{instantiation of}} - f(); // expected-note {{instantiation of}} - f(); // expected-note {{instantiation of}} - f(); // expected-note {{instantiation of}} - g(); // expected-note {{instantiation of}} - g(); // expected-note {{instantiation of}} - g(); // expected-note {{instantiation of}} - g(); // expected-note {{instantiation of}} + f(); // #dr1518-f-A + f(); // #dr1518-f-B + f(); // #dr1518-f-C + f(); // #dr1518-f-D + g(); // #dr1518-g-A + g(); // #dr1518-g-B + g(); // #dr1518-g-C + g(); // #dr1518-g-D } } -#endif // __cplusplus >= 201103L +#endif // __cplusplus >= 201103L } -namespace dr1550 { // dr1550: yes +namespace dr1550 { // dr1550: 3.4 int f(bool b, int n) { return (b ? (throw 0) : n) + (b ? n : (throw 0)); } @@ -242,13 +327,16 @@ namespace dr1550 { // dr1550: yes namespace dr1558 { // dr1558: 12 #if __cplusplus >= 201103L template using first_of = T; - template first_of f(int); // expected-note {{'int' cannot be used prior to '::'}} - template void f(...) = delete; // expected-note {{deleted}} + template first_of f(int); // #dr1558-f + template void f(...) = delete; // #dr1558-f-deleted struct X { typedef void type; }; void test() { f(0); - f(0); // expected-error {{deleted}} + f(0); + // since-cxx11-error@-1 {{call to deleted function 'f'}} + // since-cxx11-note@#dr1558-f-deleted {{candidate function [with T = int] has been explicitly deleted}} + // since-cxx11-note@#dr1558-f {{candidate template ignored: substitution failure [with T = int]: type 'int' cannot be used prior to '::' because it has no members}} } #endif } @@ -283,17 +371,25 @@ namespace dr1573 { // dr1573: 3.9 struct C { C(); constexpr C(int) {} }; struct D : C { using C::C; }; constexpr D d = D(0); // ok - struct E : C { using C::C; A a; }; // expected-note {{non-literal type}} - constexpr E e = E(0); // expected-error {{non-literal type}} + struct E : C { using C::C; A a; }; // #dr1573-E + constexpr E e = E(0); + // since-cxx11-error@-1 {{constexpr variable cannot have non-literal type 'const E'}} + // since-cxx11-note@#dr1573-E {{'E' is not literal because it has data member 'a' of non-literal type 'A'}} + // FIXME: This diagnostic is pretty bad; we should explain that the problem // is that F::c would be initialized by a non-constexpr constructor. - struct F : C { using C::C; C c; }; // expected-note {{here}} - constexpr F f = F(0); // expected-error {{constant expression}} expected-note {{constructor inherited from base class 'C'}} + struct F : C { using C::C; C c; }; // #dr1573-F + constexpr F f = F(0); + // since-cxx11-error@-1 {{constexpr variable 'f' must be initialized by a constant expression}} + // since-cxx11-note@-2 {{constructor inherited from base class 'C' cannot be used in a constant expression; derived class cannot be implicitly initialized}} + // since-cxx11-note@#dr1573-F {{declared here}} // inherited constructor is effectively deleted if the user-written constructor would be struct G { G(int); }; - struct H : G { using G::G; G g; }; // expected-note {{constructor inherited by 'H' is implicitly deleted because field 'g' has no default constructor}} - H h(0); // expected-error {{constructor inherited by 'H' from base class 'G' is implicitly deleted}} + struct H : G { using G::G; G g; }; // #dr1573-H + H h(0); + // since-cxx11-error@-1 {{constructor inherited by 'H' from base class 'G' is implicitly deleted}} + // since-cxx11-note@#dr1573-H {{constructor inherited by 'H' is implicitly deleted because field 'g' has no default constructor}} #endif } @@ -336,13 +432,15 @@ namespace std { typedef basic_string string; } // std +#endif namespace dr1579 { // dr1579: 3.9 +#if __cplusplus >= 201103L template struct GenericMoveOnly { GenericMoveOnly(); - template GenericMoveOnly(const GenericMoveOnly &) = delete; // expected-note 5 {{marked deleted here}} - GenericMoveOnly(const int &) = delete; // expected-note 2 {{marked deleted here}} + template GenericMoveOnly(const GenericMoveOnly &) = delete; // #dr1579-deleted-U + GenericMoveOnly(const int &) = delete; // #dr1579-deleted-int template GenericMoveOnly(GenericMoveOnly &&); GenericMoveOnly(int &&); }; @@ -369,17 +467,29 @@ GenericMoveOnly DR1579_Ineligible(int &AnInt, extern GenericMoveOnly ExternMove; if (0) - return AnInt; // expected-error{{invokes a deleted function}} + return AnInt; + // since-cxx11-error@-1 {{conversion function from 'int' to 'GenericMoveOnly' invokes a deleted function}} + // since-cxx11-note@#dr1579-deleted-int {{'GenericMoveOnly' has been explicitly marked deleted here}} else if (0) - return GlobalMO; // expected-error{{invokes a deleted function}} + return GlobalMO; + // since-cxx11-error@-1 {{conversion function from 'GenericMoveOnly' to 'GenericMoveOnly' invokes a deleted function}} + // since-cxx11-note@#dr1579-deleted-U {{'GenericMoveOnly' has been explicitly marked deleted here}} else if (0) - return StaticMove; // expected-error{{invokes a deleted function}} + return StaticMove; + // since-cxx11-error@-1 {{conversion function from 'GenericMoveOnly' to 'GenericMoveOnly' invokes a deleted function}} + // since-cxx11-note@#dr1579-deleted-U {{'GenericMoveOnly' has been explicitly marked deleted here}} else if (0) - return ExternMove; // expected-error{{invokes a deleted function}} + return ExternMove; + // since-cxx11-error@-1 {{conversion function from 'GenericMoveOnly' to 'GenericMoveOnly' invokes a deleted function}} + // since-cxx11-note@#dr1579-deleted-U {{'GenericMoveOnly' has been explicitly marked deleted here}} else if (0) - return AnInt; // expected-error{{invokes a deleted function}} + return AnInt; + // since-cxx11-error@-1 {{conversion function from 'int' to 'GenericMoveOnly' invokes a deleted function}} + // since-cxx11-note@#dr1579-deleted-int {{'GenericMoveOnly' has been explicitly marked deleted here}} else - return CharMO; // expected-error{{invokes a deleted function}} + return CharMO; + // since-cxx11-error@-1 {{conversion function from 'GenericMoveOnly' to 'GenericMoveOnly' invokes a deleted function}} + // since-cxx11-note@#dr1579-deleted-U {{'GenericMoveOnly' has been explicitly marked deleted here}} } auto DR1579_lambda_valid = [](GenericMoveOnly mo) -> @@ -389,24 +499,34 @@ auto DR1579_lambda_valid = [](GenericMoveOnly mo) -> auto DR1579_lambda_invalid = []() -> GenericMoveOnly { static GenericMoveOnly mo; - return mo; // expected-error{{invokes a deleted function}} + return mo; + // since-cxx11-error@-1 {{conversion function from 'GenericMoveOnly' to 'GenericMoveOnly' invokes a deleted function}} + // since-cxx11-note@#dr1579-deleted-U {{'GenericMoveOnly' has been explicitly marked deleted here}} }; +#endif } // end namespace dr1579 namespace dr1584 { +#if __cplusplus >= 201103L // Deducing function types from cv-qualified types - template void f(const T *); // expected-note {{candidate template ignored}} + template void f(const T *); // #dr1584-f template void g(T *, const T * = 0); - template void h(T *) { T::error; } // expected-error {{no members}} + template void h(T *) { T::error; } + // since-cxx11-error@-1 {{type 'void ()' cannot be used prior to '::' because it has no members}} + // since-cxx11-note@#dr1584-h {{in instantiation of function template specialization 'dr1584::h' requested here}} template void h(const T *); void i() { - f(&i); // expected-error {{no matching function}} + f(&i); + // since-cxx11-error@-1 {{no matching function for call to 'f'}} + // since-cxx11-note@#dr1584-f {{candidate template ignored: could not match 'const T *' against 'void (*)()'}} g(&i); - h(&i); // expected-note {{here}} + h(&i); // #dr1584-h } +#endif } namespace dr1589 { // dr1589: 3.7 c++11 +#if __cplusplus >= 201103L // Ambiguous ranking of list-initialization sequences void f0(long, int=0); // Would makes selection of #0 ambiguous @@ -425,25 +545,35 @@ namespace dr1589 { // dr1589: 3.7 c++11 void g2() { f2({"foo","bar"}); } // chooses #4 namespace with_error { - void f0(long); // #0 - void f0(std::initializer_list); // #00 expected-note {{candidate function}} - void f0(std::initializer_list, int = 0); // expected-note {{candidate function}} - void g0() { f0({1L}); } // expected-error{{call to 'f0' is ambiguous}} - - void f1(int); // #1 - void f1(std::initializer_list); // #2 expected-note {{candidate function}} - void f1(std::initializer_list, int = 0); // expected-note {{candidate function}} - void g1() { f1({42}); } // expected-error{{call to 'f1' is ambiguous}} - - void f2(std::pair); // #3 - void f2(std::initializer_list); // #4 expected-note {{candidate function}} - void f2(std::initializer_list, int = 0); // expected-note {{candidate function}} - void g2() { f2({"foo","bar"}); } // expected-error{{call to 'f2' is ambiguous}} + void f0(long); + void f0(std::initializer_list); // #dr1589-f0-ilist + void f0(std::initializer_list, int = 0); // #dr1589-f0-ilist-int + void g0() { f0({1L}); } + // since-cxx11-error@-1 {{call to 'f0' is ambiguous}} + // since-cxx11-note@#dr1589-f0-ilist {{candidate function}} + // since-cxx11-note@#dr1589-f0-ilist-int {{candidate function}} + + void f1(int); + void f1(std::initializer_list); // #dr1589-f1-ilist + void f1(std::initializer_list, int = 0); // #dr1589-f1-ilist-long + void g1() { f1({42}); } + // since-cxx11-error@-1 {{call to 'f1' is ambiguous}} + // since-cxx11-note@#dr1589-f1-ilist {{candidate function}} + // since-cxx11-note@#dr1589-f1-ilist-long {{candidate function}} + + void f2(std::pair); + void f2(std::initializer_list); // #dr1589-f2-ilist + void f2(std::initializer_list, int = 0); // #dr1589-f2-ilist-int + void g2() { f2({"foo","bar"}); } + // since-cxx11-error@-1 {{call to 'f2' is ambiguous}} + // since-cxx11-note@#dr1589-f2-ilist {{candidate function}} + // since-cxx11-note@#dr1589-f2-ilist-int {{candidate function}} } - +#endif } // dr1589 -namespace dr1591 { //dr1591. Deducing array bound and element type from initializer list +namespace dr1591 { //dr1591. Deducing array bound and element type from initializer list +#if __cplusplus >= 201103L template int h(T const(&)[N]); int X = h({1,2,3}); // T deduced to int, N deduced to 3 @@ -451,8 +581,10 @@ namespace dr1591 { //dr1591. Deducing array bound and element type from initial int Y = j({42}); // T deduced to int, array bound not considered struct Aggr { int i; int j; }; - template int k(Aggr const(&)[N]); //expected-note{{not viable}} - int Y0 = k({1,2,3}); //expected-error{{no matching function}} + template int k(Aggr const(&)[N]); // #dr1591-k + int Y0 = k({1,2,3}); + // since-cxx11-error@-1 {{no matching function for call to 'k'}} + // since-cxx11-note@#dr1591-k {{candidate function [with N = 3] not viable: no known conversion from 'int' to 'const Aggr' for 1st argument}} int Z = k({{1},{2},{3}}); // OK, N deduced to 3 template int m(int const(&)[M][N]); @@ -463,54 +595,64 @@ namespace dr1591 { //dr1591. Deducing array bound and element type from initial namespace check_multi_dim_arrays { - template int ***f(const T (&a)[N][M][O]); //expected-note{{deduced conflicting values}} - template int **f(const T (&a)[N][M]); //expected-note{{couldn't infer}} + template int ***f(const T (&a)[N][M][O]); // #dr1591-f-3 + template int **f(const T (&a)[N][M]); // #dr1591-f-2 - template int *f(const T (&a)[N]); //expected-note{{couldn't infer}} + template int *f(const T (&a)[N]); // #dr1591-f-1 int ***p3 = f({ { {1,2}, {3, 4} }, { {5,6}, {7, 8} }, { {9,10}, {11, 12} } }); - int ***p33 = f({ { {1,2}, {3, 4} }, { {5,6}, {7, 8} }, { {9,10}, {11, 12, 13} } }); //expected-error{{no matching}} + int ***p33 = f({ { {1,2}, {3, 4} }, { {5,6}, {7, 8} }, { {9,10}, {11, 12, 13} } }); + // since-cxx11-error@-1 {{no matching function for call to 'f'}} + // since-cxx11-note@#dr1591-f-2 {{candidate template ignored: couldn't infer template argument 'T'}} + // since-cxx11-note@#dr1591-f-1 {{candidate template ignored: couldn't infer template argument 'T'}} + // since-cxx11-note@#dr1591-f-3 {{candidate template ignored: deduced conflicting values for parameter 'O' (2 vs. 3)}} int **p2 = f({ {1,2,3}, {3, 4, 5} }); int **p22 = f({ {1,2}, {3, 4} }); int *p1 = f({1, 2, 3}); } namespace check_multi_dim_arrays_rref { - template int ***f(T (&&a)[N][M][O]); //expected-note{{deduced conflicting values}} - template int **f(T (&&a)[N][M]); //expected-note{{couldn't infer}} + template int ***g(T (&&a)[N][M][O]); // #dr1591-g-3 + template int **g(T (&&a)[N][M]); // #dr1591-g-2 - template int *f(T (&&a)[N]); //expected-note{{couldn't infer}} - int ***p3 = f({ { {1,2}, {3, 4} }, { {5,6}, {7, 8} }, { {9,10}, {11, 12} } }); - int ***p33 = f({ { {1,2}, {3, 4} }, { {5,6}, {7, 8} }, { {9,10}, {11, 12, 13} } }); //expected-error{{no matching}} - int **p2 = f({ {1,2,3}, {3, 4, 5} }); - int **p22 = f({ {1,2}, {3, 4} }); - int *p1 = f({1, 2, 3}); + template int *g(T (&&a)[N]); // #dr1591-g-1 + int ***p3 = g({ { {1,2}, {3, 4} }, { {5,6}, {7, 8} }, { {9,10}, {11, 12} } }); + int ***p33 = g({ { {1,2}, {3, 4} }, { {5,6}, {7, 8} }, { {9,10}, {11, 12, 13} } }); + // since-cxx11-error@-1 {{no matching function for call to 'g'}} + // since-cxx11-note@#dr1591-g-2 {{candidate template ignored: couldn't infer template argument 'T'}} + // since-cxx11-note@#dr1591-g-1 {{candidate template ignored: couldn't infer template argument 'T'}} + // since-cxx11-note@#dr1591-g-3 {{candidate template ignored: deduced conflicting values for parameter 'O' (2 vs. 3)}} + int **p2 = g({ {1,2,3}, {3, 4, 5} }); + int **p22 = g({ {1,2}, {3, 4} }); + int *p1 = g({1, 2, 3}); } namespace check_arrays_of_init_list { - template float *f(const std::initializer_list (&)[N]); - template double *f(const T(&)[N]); - double *p = f({1, 2, 3}); - float *fp = f({{1}, {1, 2}, {1, 2, 3}}); + template float *h(const std::initializer_list (&)[N]); + template double *h(const T(&)[N]); + double *p = h({1, 2, 3}); + float *fp = h({{1}, {1, 2}, {1, 2, 3}}); } namespace core_reflector_28543 { - template int *f(T (&&)[N]); // #1 - template char *f(std::initializer_list &&); //#2 - template int **f(T (&&)[N][M]); //#3 expected-note{{candidate}} - template char **f(std::initializer_list (&&)[N]); //#4 expected-note{{candidate}} + template int *i(T (&&)[N]); // #1 + template char *i(std::initializer_list &&); // #2 + template int **i(T (&&)[N][M]); // #3 #dr1591-i-2 + template char **i(std::initializer_list (&&)[N]); // #4 #dr1591-i-1 - template short *f(T (&&)[2]); //#5 + template short *i(T (&&)[2]); // #5 template using Arr = T[]; - char *pc = f({1, 2, 3}); // OK prefer #2 via 13.3.3.2 [over.ics.rank] - char *pc2 = f({1, 2}); // #2 also - int *pi = f(Arr{1, 2, 3}); // OK prefer #1 + char *pc = i({1, 2, 3}); // OK prefer #2 via 13.3.3.2 [over.ics.rank] + char *pc2 = i({1, 2}); // #2 also + int *pi = i(Arr{1, 2, 3}); // OK prefer #1 - void *pv1 = f({ {1, 2, 3}, {4, 5, 6} }); // expected-error{{ambiguous}} btw 3 & 4 - char **pcc = f({ {1}, {2, 3} }); // OK #4 + void *pv1 = i({ {1, 2, 3}, {4, 5, 6} }); // ambiguous btw 3 & 4 + // since-cxx11-error@-1 {{call to 'i' is ambiguous}} + // since-cxx11-note@#dr1591-i-2 {{candidate function [with T = int, N = 2, M = 3]}} + // since-cxx11-note@#dr1591-i-1 {{candidate function [with T = int, N = 2]}} + char **pcc = i({ {1}, {2, 3} }); // OK #4 - short *ps = f(Arr{1, 2}); // OK #5 + short *ps = i(Arr{1, 2}); // OK #5 } -} // dr1591 - #endif +} // dr1591 diff --git a/clang/test/CXX/drs/dr16xx.cpp b/clang/test/CXX/drs/dr16xx.cpp index 463353dab3b1604f09e9c6712aba55647c6c61e9..3f074c4d57354acbeaa20c8b00b56a84e93a1733 100644 --- a/clang/test/CXX/drs/dr16xx.cpp +++ b/clang/test/CXX/drs/dr16xx.cpp @@ -1,12 +1,14 @@ -// RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++2a -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors - -#if __cplusplus < 201103L -// expected-error@+1 {{variadic macro}} +// RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -verify=expected,cxx98-14,cxx98 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -verify=expected,cxx98-14,since-cxx11,cxx11 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx14,cxx98-14,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx14,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx14,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx14,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -verify=expected,since-cxx14,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors + +#if __cplusplus == 199711L #define static_assert(...) __extension__ _Static_assert(__VA_ARGS__) +// cxx98-error@-1 {{variadic macros are a C99 feature}} #endif #if __cplusplus >= 201103L @@ -25,9 +27,7 @@ namespace std { namespace dr1601 { // dr1601: 10 enum E : char { e }; -#if __cplusplus < 201103L - // expected-error@-2 {{enumeration types with a fixed underlying type are a C++11 extension}} -#endif +// cxx98-error@-1 {{enumeration types with a fixed underlying type are a C++11 extension}} void f(char); void f(int); void g() { @@ -53,26 +53,30 @@ namespace dr1631 { // dr1631: 3.7 void f(int, A); void test() { - f({0}, {{1}}); // expected-warning {{braces around scalar init}} + f({0}, {{1}}); + // since-cxx11-warning@-1 {{braces around scalar initializer}} } namespace with_error { void f(B, int); // TODO: expected- note {{candidate function}} - void f(int, A); // expected-note {{candidate function}} - void f(int, A, int = 0); // expected-note {{candidate function}} + void f(int, A); // #dr1631-f + void f(int, A, int = 0); // #dr1631-f-int void test() { - f({0}, {{1}}); // expected-error{{call to 'f' is ambiguous}} + f({0}, {{1}}); + // since-cxx11-error@-1 {{call to 'f' is ambiguous}} + // since-cxx11-note@#dr1631-f {{candidate function}} + // since-cxx11-note@#dr1631-f-int {{candidate function}} } } #endif } -namespace dr1638 { // dr1638: yes +namespace dr1638 { // dr1638: 3.1 #if __cplusplus >= 201103L template struct A { - enum class E; // expected-note {{previous}} - enum class F : T; // expected-note 2{{previous}} + enum class E; // #dr1638-E + enum class F : T; // #dr1638-F }; template<> enum class A::E; @@ -83,16 +87,27 @@ namespace dr1638 { // dr1638: yes template<> enum class A::E : int; template<> enum class A::E : int {}; - template<> enum class A::F; // expected-error {{different underlying type}} - template<> enum class A::E : char; // expected-error {{different underlying type}} - template<> enum class A::F : int; // expected-error {{different underlying type}} - - enum class A::E; // expected-error {{template specialization requires 'template<>'}} expected-error {{nested name specifier}} - template enum class A::E; // expected-error {{enumerations cannot be explicitly instantiated}} - enum class A::E *e; // expected-error {{must use 'enum' not 'enum class'}} + template<> enum class A::F; + // since-cxx11-error@-1 {{enumeration redeclared with different underlying type 'int' (was 'short')}} + // since-cxx11-note@#dr1638-F {{previous declaration is here}} + template<> enum class A::E : char; + // since-cxx11-error@-1 {{enumeration redeclared with different underlying type 'char' (was 'int')}} + // since-cxx11-note@#dr1638-E {{previous declaration is here}} + template<> enum class A::F : int; + // since-cxx11-error@-1 {{enumeration redeclared with different underlying type 'int' (was 'char')}} + // since-cxx11-note@#dr1638-F {{previous declaration is here}} + + enum class A::E; + // since-cxx11-error@-1 {{template specialization requires 'template<>'}} + // since-cxx11-error@-2 {{forward declaration of enum class cannot have a nested name specifier}} + template enum class A::E; + // since-cxx11-error@-1 {{enumerations cannot be explicitly instantiated}} + enum class A::E *e; + // since-cxx11-error@-1 {{reference to enumeration must use 'enum' not 'enum class'}} struct B { - friend enum class A::E; // expected-error {{must use 'enum' not 'enum class'}} + friend enum class A::E; + // since-cxx11-error@-1 {{reference to enumeration must use 'enum' not 'enum class'}} }; #endif } @@ -100,37 +115,50 @@ namespace dr1638 { // dr1638: yes namespace dr1645 { // dr1645: 3.9 #if __cplusplus >= 201103L struct A { - constexpr A(int, float = 0); // expected-note {{candidate}} - explicit A(int, int = 0); // expected-note 2{{candidate}} - A(int, int, int = 0) = delete; // expected-note {{candidate}} + constexpr A(int, float = 0); // #dr1645-int-float + explicit A(int, int = 0); // #dr1645-int-int + A(int, int, int = 0) = delete; // #dr1645-int-int-int }; struct B : A { - using A::A; // expected-note 4{{inherited here}} + using A::A; // #dr1645-using }; - constexpr B a(0); // expected-error {{ambiguous}} - constexpr B b(0, 0); // expected-error {{ambiguous}} + constexpr B a(0); + // since-cxx11-error@-1 {{call to constructor of 'const B' is ambiguous}} + // since-cxx11-note@#dr1645-int-float {{candidate inherited constructor}} + // since-cxx11-note@#dr1645-using {{constructor from base class 'A' inherited here}} + // since-cxx11-note@#dr1645-int-int {{candidate inherited constructor}} + // since-cxx11-note@#dr1645-using {{constructor from base class 'A' inherited here}} + constexpr B b(0, 0); + // since-cxx11-error@-1 {{call to constructor of 'const B' is ambiguous}} + // since-cxx11-note@#dr1645-int-int {{candidate inherited constructor}} + // since-cxx11-note@#dr1645-using {{constructor from base class 'A' inherited here}} + // since-cxx11-note@#dr1645-int-int-int {{candidate inherited constructor has been explicitly deleted}} + // since-cxx11-note@#dr1645-using {{constructor from base class 'A' inherited here}} #endif } namespace dr1652 { // dr1652: 3.6 int a, b; - int arr[&a + 1 == &b ? 1 : 2]; // expected-error 2{{variable length array}} - // expected-note@-1 {{points past the end}} + int arr[&a + 1 == &b ? 1 : 2]; + // expected-error@-1 {{variable length arrays in C++ are a Clang extension}} + // expected-note@-2 {{comparison against pointer '&a + 1' that points past the end of a complete object has unspecified value}} + // expected-error@-3 {{variable length array declaration not allowed at file scope}} } namespace dr1653 { // dr1653: 4 c++17 void f(bool b) { ++b; + // cxx98-14-warning@-1 {{incrementing expression of type bool is deprecated and incompatible with C++17}} + // since-cxx17-error@-2 {{SO C++17 does not allow incrementing expression of type bool}} b++; -#if __cplusplus <= 201402L - // expected-warning@-3 {{deprecated}} expected-warning@-2 {{deprecated}} -#else - // expected-error@-5 {{incrementing expression of type bool}} expected-error@-4 {{incrementing expression of type bool}} -#endif - --b; // expected-error {{cannot decrement expression of type bool}} - b--; // expected-error {{cannot decrement expression of type bool}} + // cxx98-14-warning@-1 {{incrementing expression of type bool is deprecated and incompatible with C++17}} + // since-cxx17-error@-2 {{SO C++17 does not allow incrementing expression of type bool}} + --b; + // expected-error@-1 {{cannot decrement expression of type bool}} + b--; + // expected-error@-1 {{cannot decrement expression of type bool}} b += 1; // ok b -= 1; // ok } @@ -138,71 +166,88 @@ namespace dr1653 { // dr1653: 4 c++17 namespace dr1658 { // dr1658: 5 namespace DefCtor { - class A { A(); }; // expected-note 0-2{{here}} - class B { ~B(); }; // expected-note 0-2{{here}} + class A { A(); }; // #dr1658-A1 + class B { ~B(); }; // #dr1658-B1 // The stars align! An abstract class does not construct its virtual bases. struct C : virtual A { C(); virtual void foo() = 0; }; - C::C() = default; // ok, not deleted, expected-error 0-1{{extension}} + C::C() = default; // ok, not deleted + // cxx98-error@-1 {{defaulted function definitions are a C++11 extension}} struct D : virtual B { D(); virtual void foo() = 0; }; - D::D() = default; // ok, not deleted, expected-error 0-1{{extension}} + D::D() = default; // ok, not deleted + // cxx98-error@-1 {{defaulted function definitions are a C++11 extension}} // In all other cases, we are not so lucky. - struct E : A { E(); virtual void foo() = 0; }; -#if __cplusplus < 201103L - E::E() = default; // expected-error {{private default constructor}} expected-error {{extension}} expected-note {{here}} -#else - E::E() = default; // expected-error {{would delete}} expected-note@-4{{inaccessible default constructor}} -#endif - struct F : virtual A { F(); }; -#if __cplusplus < 201103L - F::F() = default; // expected-error {{private default constructor}} expected-error {{extension}} expected-note {{here}} -#else - F::F() = default; // expected-error {{would delete}} expected-note@-4{{inaccessible default constructor}} -#endif - - struct G : B { G(); virtual void foo() = 0; }; -#if __cplusplus < 201103L - G::G() = default; // expected-error@-2 {{private destructor}} expected-error {{extension}} expected-note {{here}} -#else - G::G() = default; // expected-error {{would delete}} expected-note@-4{{inaccessible destructor}} -#endif - struct H : virtual B { H(); }; -#if __cplusplus < 201103L - H::H() = default; // expected-error@-2 {{private destructor}} expected-error {{extension}} expected-note {{here}} -#else - H::H() = default; // expected-error {{would delete}} expected-note@-4{{inaccessible destructor}} -#endif + struct E : A { E(); virtual void foo() = 0; }; // #dr1658-E1 + E::E() = default; // #dr1658-E1-ctor + // cxx98-error@-1 {{defaulted function definitions are a C++11 extension}} + // cxx98-error@-2 {{base class 'A' has private default constructor}} + // cxx98-note@-3 {{in defaulted default constructor for 'dr1658::DefCtor::E' first required here}} + // cxx98-note@#dr1658-A1 {{implicitly declared private here}} + // since-cxx11-error@#dr1658-E1-ctor {{defaulting this default constructor would delete it after its first declaration}} + // since-cxx11-note@#dr1658-E1 {{default constructor of 'E' is implicitly deleted because base class 'A' has an inaccessible default constructor}} + struct F : virtual A { F(); }; // #dr1658-F1 + F::F() = default; // #dr1658-F1-ctor + // cxx98-error@-1 {{defaulted function definitions are a C++11 extension}} + // cxx98-error@-2 {{inherited virtual base class 'A' has private default constructor}} + // cxx98-note@-3 {{in defaulted default constructor for 'dr1658::DefCtor::F' first required here}} + // cxx98-note@#dr1658-A1 {{implicitly declared private here}} + // since-cxx11-error@#dr1658-F1-ctor {{defaulting this default constructor would delete it after its first declaration}} + // since-cxx11-note@#dr1658-F1 {{default constructor of 'F' is implicitly deleted because base class 'A' has an inaccessible default constructor}} + + struct G : B { G(); virtual void foo() = 0; }; // #dr1658-G1 + G::G() = default; // #dr1658-G1-ctor + // cxx98-error@-1 {{defaulted function definitions are a C++11 extension}} + // cxx98-error@#dr1658-G1 {{base class 'B' has private destructor}} + // cxx98-note@#dr1658-G1-ctor {{in defaulted default constructor for 'dr1658::DefCtor::G' first required here}} + // cxx98-note@#dr1658-B1 {{implicitly declared private here}} + // since-cxx11-error@#dr1658-G1-ctor {{defaulting this default constructor would delete it after its first declaration}} + // since-cxx11-note@#dr1658-G1 {{default constructor of 'G' is implicitly deleted because base class 'B' has an inaccessible destructor}} + struct H : virtual B { H(); }; // #dr1658-H1 + H::H() = default; // #dr1658-H1-ctor + // cxx98-error@-1 {{defaulted function definitions are a C++11 extension}} + // cxx98-error@#dr1658-H1 {{base class 'B' has private destructor}} + // cxx98-note@#dr1658-H1-ctor {{in defaulted default constructor for 'dr1658::DefCtor::H' first required here}} + // cxx98-note@#dr1658-B1 {{implicitly declared private here}} + // since-cxx11-error@#dr1658-H1-ctor {{defaulting this default constructor would delete it after its first declaration}} + // since-cxx11-note@#dr1658-H1 {{default constructor of 'H' is implicitly deleted because base class 'B' has an inaccessible destructor}} } namespace Dtor { - class B { ~B(); }; // expected-note 0-2{{here}} + class B { ~B(); }; // #dr1658-B2 struct D : virtual B { ~D(); virtual void foo() = 0; }; - D::~D() = default; // ok, not deleted, expected-error 0-1{{extension}} - - struct G : B { ~G(); virtual void foo() = 0; }; -#if __cplusplus < 201103L - G::~G() = default; // expected-error@-2 {{private destructor}} expected-error {{extension}} expected-note {{here}} -#else - G::~G() = default; // expected-error {{would delete}} expected-note@-4{{inaccessible destructor}} -#endif - struct H : virtual B { ~H(); }; -#if __cplusplus < 201103L - H::~H() = default; // expected-error@-2 {{private destructor}} expected-error {{extension}} expected-note {{here}} -#else - H::~H() = default; // expected-error {{would delete}} expected-note@-4{{inaccessible destructor}} -#endif + D::~D() = default; // ok, not deleted + // cxx98-error@-1 {{defaulted function definitions are a C++11 extension}} + + struct G : B { ~G(); virtual void foo() = 0; }; // #dr1658-G2 + G::~G() = default; // #dr1658-G2-dtor + // cxx98-error@-1 {{defaulted function definitions are a C++11 extension}} + // cxx98-error@#dr1658-G2 {{base class 'B' has private destructor}} + // cxx98-note@#dr1658-G2-dtor {{in defaulted destructor for 'dr1658::Dtor::G' first required here}} + // cxx98-note@#dr1658-B2 {{implicitly declared private here}} + // since-cxx11-error@#dr1658-G2-dtor {{defaulting this destructor would delete it after its first declaration}} + // since-cxx11-note@#dr1658-G2 {{destructor of 'G' is implicitly deleted because base class 'B' has an inaccessible destructor}} + struct H : virtual B { ~H(); }; // #dr1658-H2 + H::~H() = default; // #dr1658-H2-dtor + // cxx98-error@-1 {{defaulted function definitions are a C++11 extension}} + // cxx98-error@#dr1658-H2 {{base class 'B' has private destructor}} + // cxx98-note@#dr1658-H2-dtor {{in defaulted destructor for 'dr1658::Dtor::H' first required here}} + // cxx98-note@#dr1658-B2 {{implicitly declared private here}} + // since-cxx11-error@#dr1658-H2-dtor {{defaulting this destructor would delete it after its first declaration}} + // since-cxx11-note@#dr1658-H2 {{destructor of 'H' is implicitly deleted because base class 'B' has an inaccessible destructor}} } namespace MemInit { - struct A { A(int); }; // expected-note {{here}} + struct A { A(int); }; // #dr1658-A3 struct B : virtual A { B() {} virtual void f() = 0; }; struct C : virtual A { - C() {} // expected-error {{must explicitly initialize}} + C() {} + // expected-error@-1 {{constructor for 'dr1658::MemInit::C' must explicitly initialize the base class 'A' which does not have a default constructor}} + // expected-note@#dr1658-A3 {{'dr1658::MemInit::A' declared here}} }; } @@ -220,28 +265,51 @@ namespace dr1658 { // dr1658: 5 } namespace CopyCtor { - class A { A(const A&); A(A&&); }; // expected-note 0-4{{here}} expected-error 0-1{{extension}} - - struct C : virtual A { C(const C&); C(C&&); virtual void foo() = 0; }; // expected-error 0-1{{extension}} - C::C(const C&) = default; // expected-error 0-1{{extension}} - C::C(C&&) = default; // expected-error 0-2{{extension}} - - struct E : A { E(const E&); E(E&&); virtual void foo() = 0; }; // expected-error 0-1{{extension}} -#if __cplusplus < 201103L - E::E(const E&) = default; // expected-error {{private copy constructor}} expected-error {{extension}} expected-note {{here}} - E::E(E&&) = default; // expected-error {{private move constructor}} expected-error 2{{extension}} expected-note {{here}} -#else - E::E(const E&) = default; // expected-error {{would delete}} expected-note@-5{{inaccessible copy constructor}} - E::E(E&&) = default; // expected-error {{would delete}} expected-note@-6{{inaccessible move constructor}} -#endif - struct F : virtual A { F(const F&); F(F&&); }; // expected-error 0-1{{extension}} -#if __cplusplus < 201103L - F::F(const F&) = default; // expected-error {{private copy constructor}} expected-error {{extension}} expected-note {{here}} - F::F(F&&) = default; // expected-error {{private move constructor}} expected-error 2{{extension}} expected-note {{here}} -#else - F::F(const F&) = default; // expected-error {{would delete}} expected-note@-5{{inaccessible copy constructor}} - F::F(F&&) = default; // expected-error {{would delete}} expected-note@-6{{inaccessible move constructor}} -#endif + class A { A(const A&); A(A&&); }; // #dr1658-A5 + // cxx98-error@-1 {{rvalue references are a C++11 extension}} + + struct C : virtual A { C(const C&); C(C&&); virtual void foo() = 0; }; + // cxx98-error@-1 {{rvalue references are a C++11 extension}} + C::C(const C&) = default; + // cxx98-error@-1 {{defaulted function definitions are a C++11 extension}} + C::C(C&&) = default; + // cxx98-error@-1 {{rvalue references are a C++11 extension}} + // cxx98-error@-2 {{defaulted function definitions are a C++11 extension}} + + struct E : A { E(const E&); E(E&&); virtual void foo() = 0; }; // #dr1658-E5 + // cxx98-error@-1 {{rvalue references are a C++11 extension}} + E::E(const E&) = default; // #dr1658-E5-copy-ctor + // cxx98-error@-1 {{defaulted function definitions are a C++11 extension}} + // cxx98-error@-2 {{base class 'A' has private copy constructor}} + // cxx98-note@-3 {{in defaulted copy constructor for 'dr1658::CopyCtor::E' first required here}} + // cxx98-note@#dr1658-A5 {{implicitly declared private here}} + // since-cxx11-error@#dr1658-E5-copy-ctor {{defaulting this copy constructor would delete it after its first declaration}} + // since-cxx11-note@#dr1658-E5 {{copy constructor of 'E' is implicitly deleted because base class 'A' has an inaccessible copy constructor}} + E::E(E&&) = default; // #dr1658-E5-move-ctor + // cxx98-error@-1 {{rvalue references are a C++11 extension}} + // cxx98-error@-2 {{defaulted function definitions are a C++11 extension}} + // cxx98-error@-3 {{base class 'A' has private move constructor}} + // cxx98-note@-4 {{in defaulted move constructor for 'dr1658::CopyCtor::E' first required here}} + // cxx98-note@#dr1658-A5 {{implicitly declared private here}} + // since-cxx11-error@#dr1658-E5-move-ctor {{defaulting this move constructor would delete it after its first declaration}} + // since-cxx11-note@#dr1658-E5 {{move constructor of 'E' is implicitly deleted because base class 'A' has an inaccessible move constructor}} + struct F : virtual A { F(const F&); F(F&&); }; // #dr1658-F5 + // cxx98-error@-1 {{rvalue references are a C++11 extension}} + F::F(const F&) = default; // #dr1658-F5-copy-ctor + // cxx98-error@-1 {{defaulted function definitions are a C++11 extension}} + // cxx98-error@-2 {{inherited virtual base class 'A' has private copy constructor}} + // cxx98-note@-3 {{in defaulted copy constructor for 'dr1658::CopyCtor::F' first required here}} + // cxx98-note@#dr1658-A5 {{implicitly declared private here}} + // since-cxx11-error@#dr1658-F5-copy-ctor {{defaulting this copy constructor would delete it after its first declaration}} + // since-cxx11-note@#dr1658-F5 {{copy constructor of 'F' is implicitly deleted because base class 'A' has an inaccessible copy constructor}} + F::F(F&&) = default; // #dr1658-F5-move-ctor + // cxx98-error@-1 {{rvalue references are a C++11 extension}} + // cxx98-error@-2 {{defaulted function definitions are a C++11 extension}} + // cxx98-error@-3 {{inherited virtual base class 'A' has private move constructor}} + // cxx98-note@-4 {{in defaulted move constructor for 'dr1658::CopyCtor::F' first required here}} + // cxx98-note@#dr1658-A5 {{implicitly declared private here}} + // since-cxx11-error@#dr1658-F5-move-ctor {{defaulting this move constructor would delete it after its first declaration}} + // since-cxx11-note@#dr1658-F5 {{move constructor of 'F' is implicitly deleted because base class 'A' has an inaccessible move constructor}} } // assignment case is superseded by dr2180 @@ -274,31 +342,38 @@ namespace dr1672 { // dr1672: 7 namespace dr1684 { // dr1684: 3.6 #if __cplusplus >= 201103L - struct NonLiteral { // expected-note {{because}} + struct NonLiteral { // #dr1684-struct NonLiteral(); - constexpr int f() { return 0; } // expected-warning 0-1{{will not be implicitly 'const'}} + constexpr int f() { return 0; } + // cxx11-warning@-1 {{'constexpr' non-static member function will not be implicitly 'const' in C++14; add 'const' to avoid a change in behavior}} }; constexpr int f(NonLiteral &) { return 0; } - constexpr int f(NonLiteral) { return 0; } // expected-error {{not a literal type}} + constexpr int f(NonLiteral) { return 0; } + // since-cxx11-error@-1 {{constexpr function's 1st parameter type 'NonLiteral' is not a literal type}} + // since-cxx11-note@#dr1684-struct {{'NonLiteral' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}} #endif } namespace dr1687 { // dr1687: 7 template struct To { - operator T(); // expected-note 2{{first operand was implicitly converted to type 'int *'}} - // expected-note@-1 {{second operand was implicitly converted to type 'double'}} -#if __cplusplus > 201703L - // expected-note@-3 2{{operand was implicitly converted to type 'dr1687::E}} -#endif + operator T(); // #dr1687-op-T }; - int *a = To() + 100.0; // expected-error {{invalid operands to binary expression ('To' and 'double')}} - int *b = To() + To(); // expected-error {{invalid operands to binary expression ('To' and 'To')}} + int *a = To() + 100.0; + // expected-error@-1 {{invalid operands to binary expression ('To' and 'double')}} + // expected-note@#dr1687-op-T {{first operand was implicitly converted to type 'int *'}} + // since-cxx20-note@#dr1687-op-T {{second operand was implicitly converted to type 'dr1687::E2'}} + int *b = To() + To(); + // expected-error@-1 {{invalid operands to binary expression ('To' and 'To')}} + // expected-note@#dr1687-op-T {{first operand was implicitly converted to type 'int *'}} + // expected-note@#dr1687-op-T {{second operand was implicitly converted to type 'double'}} -#if __cplusplus > 201703L +#if __cplusplus >= 202002L enum E1 {}; enum E2 {}; - auto c = To() <=> To(); // expected-error {{invalid operands to binary expression ('To' and 'To')}} + auto c = To() <=> To(); + // since-cxx20-error@-1 {{invalid operands to binary expression ('To' and 'To')}} + // since-cxx20-note@#dr1687-op-T {{operand was implicitly converted to type 'dr1687::E}} #endif } @@ -325,12 +400,14 @@ namespace dr1691 { // dr1691: 9 void f(E); } enum M::E : int {}; - void g(M::E); // expected-note {{declared here}} + void g(M::E); // #dr1691-g } void test() { N::M::E e; f(e); // ok - g(e); // expected-error {{use of undeclared}} + g(e); + // since-cxx11-error@-1 {{use of undeclared identifier 'g'; did you mean 'N::g'?}} + // since-cxx11-note@#dr1691-g {{'N::g' declared here}} } #endif } @@ -356,7 +433,9 @@ namespace dr1696 { // dr1696: 7 extern struct A a; struct A { const A &x = { A{a, a} }; - const A &y = { A{} }; // expected-error {{default member initializer for 'y' needed within definition of enclosing class 'A' outside of member functions}} expected-note {{here}} + const A &y = { A{} }; + // since-cxx14-error@-1 {{default member initializer for 'y' needed within definition of enclosing class 'A' outside of member functions}} + // since-cxx14-note@-2 {{default member initializer declared here}} }; A a{a, a}; #endif @@ -365,16 +444,20 @@ namespace dr1696 { // dr1696: 7 struct A { A(); ~A(); }; #if __cplusplus >= 201103L struct B { - A &&a; // expected-note {{declared here}} - B() : a{} {} // expected-error {{reference member 'a' binds to a temporary object whose lifetime would be shorter than the lifetime of the constructed object}} + A &&a; // #dr1696-a + B() : a{} {} + // since-cxx11-error@-1 {{reference member 'a' binds to a temporary object whose lifetime would be shorter than the lifetime of the constructed object}} + // since-cxx11-note@#dr1696-a {{reference member declared here}} } b; #endif struct C { C(); - const A &a; // expected-note {{declared here}} + const A &a; // #dr1696-C-a }; - C::C() : a(A()) {} // expected-error {{reference member 'a' binds to a temporary object whose lifetime would be shorter than the lifetime of the constructed object}} + C::C() : a(A()) {} + // expected-error@-1 {{reference member 'a' binds to a temporary object whose lifetime would be shorter than the lifetime of the constructed object}} + // expected-note@#dr1696-C-a {{reference member declared here}} #if __cplusplus >= 201103L // This is OK in C++14 onwards, per DR1815, though we don't support that yet: @@ -383,51 +466,62 @@ namespace dr1696 { // dr1696: 7 // D1 d1 = {A()}; // ... which lifetime-extends the A temporary. struct D1 { -#if __cplusplus < 201402L - // expected-error@-2 {{binds to a temporary}} -#endif - const A &a = A(); // expected-note {{default member init}} + // cxx11-error@-1 {{reference member 'a' binds to a temporary object whose lifetime would be shorter than the lifetime of the constructed object}} + // cxx11-note@#dr1696-d1 {{in implicit default constructor for 'dr1696::D1' first required here}} + // cxx11-note@#dr1696-D1-a {{initializing field 'a' with default member initializer}} + const A &a = A(); // #dr1696-D1-a }; - D1 d1 = {}; -#if __cplusplus < 201402L - // expected-note@-2 {{first required here}} -#else - // expected-warning-re@-4 {{sorry, lifetime extension {{.*}} not supported}} -#endif + D1 d1 = {}; // #dr1696-d1 + // since-cxx14-warning@-1 {{sorry, lifetime extension of temporary created by aggregate initialization using default member initializer is not supported; lifetime of temporary will end at the end of the full-expression}} + // since-cxx14-note@#dr1696-D1-a {{initializing field 'a' with default member initializer}} struct D2 { - const A &a = A(); // expected-note {{default member init}} - D2() {} // expected-error {{binds to a temporary}} + const A &a = A(); // #dr1696-D2-a + D2() {} + // since-cxx11-error@-1 {{reference member 'a' binds to a temporary object whose lifetime would be shorter than the lifetime of the constructed object}} + // since-cxx11-note@#dr1696-D2-a {{initializing field 'a' with default member initializer}} }; - struct D3 { // expected-error {{binds to a temporary}} - const A &a = A(); // expected-note {{default member init}} + struct D3 { + // since-cxx11-error@-1 {{reference member 'a' binds to a temporary object whose lifetime would be shorter than the lifetime of the constructed object}} + // since-cxx11-note@#dr1696-d3 {{in implicit default constructor for 'dr1696::D3' first required here}} + // since-cxx11-note@#dr1696-D3-a {{initializing field 'a' with default member initializer}} + const A &a = A(); // #dr1696-D3-a }; - D3 d3; // expected-note {{first required here}} + D3 d3; // #dr1696-d3 struct haslist1 { - std::initializer_list il; // expected-note {{'std::initializer_list' member}} - haslist1(int i) : il{i, 2, 3} {} // expected-error {{backing array for 'std::initializer_list' member 'il' is a temporary object}} + std::initializer_list il; // #dr1696-il-1 + haslist1(int i) : il{i, 2, 3} {} + // since-cxx11-error@-1 {{backing array for 'std::initializer_list' member 'il' is a temporary object whose lifetime would be shorter than the lifetime of the constructed object}} + // since-cxx11-note@#dr1696-il-1 {{'std::initializer_list' member declared here}} }; struct haslist2 { - std::initializer_list il; // expected-note {{'std::initializer_list' member}} + std::initializer_list il; // #dr1696-il-2 haslist2(); }; - haslist2::haslist2() : il{1, 2} {} // expected-error {{backing array for 'std::initializer_list' member 'il' is a temporary object}} + haslist2::haslist2() : il{1, 2} {} + // since-cxx11-error@-1 {{backing array for 'std::initializer_list' member 'il' is a temporary object whose lifetime would be shorter than the lifetime of the constructed object}} + // since-cxx11-note@#dr1696-il-2 {{'std::initializer_list' member declared here}} struct haslist3 { std::initializer_list il = {1, 2, 3}; }; - struct haslist4 { // expected-error {{backing array for 'std::initializer_list' member 'il' is a temporary object}} - std::initializer_list il = {1, 2, 3}; // expected-note {{default member initializer}} + struct haslist4 { + // since-cxx11-error@-1 {{backing array for 'std::initializer_list' member 'il' is a temporary object whose lifetime would be shorter than the lifetime of the constructed object}} + // since-cxx11-note@#dr1696-hl4 {{in implicit default constructor for 'dr1696::haslist4' first required here}} + // since-cxx11-note@#dr1696-il-4 {{initializing field 'il' with default member initializer}} + std::initializer_list il = {1, 2, 3}; // #dr1696-il-4 }; - haslist4 hl4; // expected-note {{in implicit default constructor}} + haslist4 hl4; // #dr1696-hl4 struct haslist5 { - std::initializer_list il = {1, 2, 3}; // expected-note {{default member initializer}} - haslist5() {} // expected-error {{backing array for 'std::initializer_list' member 'il' is a temporary object}} + std::initializer_list il = {1, 2, 3}; // #dr1696-il-5 + haslist5() {} + // since-cxx11-error@-1 {{backing array for 'std::initializer_list' member 'il' is a temporary object whose lifetime would be shorter than the lifetime of the constructed object}} + // since-cxx11-note@#dr1696-il-5 {{nitializing field 'il' with default member initializer}} }; #endif } diff --git a/clang/test/CXX/drs/dr17xx.cpp b/clang/test/CXX/drs/dr17xx.cpp index 219119d1a4cd087368e4dad08e395257e50e991d..0c44fb231ce51a7d6b5f1634f3451c8b4ebef60a 100644 --- a/clang/test/CXX/drs/dr17xx.cpp +++ b/clang/test/CXX/drs/dr17xx.cpp @@ -1,10 +1,10 @@ -// RUN: %clang_cc1 -std=c++98 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++11 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++14 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++17 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++20 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++23 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++2c %s -verify -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++98 %s -verify=expected -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++11 %s -verify=expected,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++14 %s -verify=expected,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++17 %s -verify=expected,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++20 %s -verify=expected,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++23 %s -verify=expected,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++2c %s -verify=expected,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors namespace dr1710 { // dr1710: no // FIXME: all of the following is well-formed @@ -32,13 +32,17 @@ namespace dr1715 { // dr1715: 3.9 struct D : B { using B::B; }; - struct E : B { // expected-note 2{{candidate}} - template E(T t, typename T::Q q) : B(t, q) {} // expected-note {{'Q' is a private member}} + struct E : B { // #dr1715-E + template E(T t, typename T::Q q) : B(t, q) {} // #dr1715-E-ctor }; B b(S(), 1); D d(S(), 2); - E e(S(), 3); // expected-error {{no match}} + E e(S(), 3); + // since-cxx11-error@-1 {{no matching constructor for initialization of 'E'}} + // since-cxx11-note@#dr1715-E-ctor {{candidate template ignored: substitution failure [with T = S]: 'Q' is a private member of 'dr1715::S'}} + // since-cxx11-note@#dr1715-E {{candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 2 were provided}} + // since-cxx11-note@#dr1715-E {{candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 2 were provided}} #endif } @@ -73,12 +77,15 @@ struct S { struct L : S { using S::S; }; - typename T::type value; // expected-error {{no member}} - L l(value); // expected-note {{instantiation of}} + typename T::type value; + // since-cxx11-error@-1 {{type 'int' cannot be used prior to '::' because it has no members}} + // since-cxx11-note@#dr1736-l {{in instantiation of function template specialization 'dr1736::S::S' requested here}} + // since-cxx11-note@#dr1736-s {{in instantiation of function template specialization 'dr1736::S::S' requested here}} + L l(value); // #dr1736-l } }; struct Q { typedef int type; } q; -S s(q); // expected-note {{instantiation of}} +S s(q); // #dr1736-s #endif } @@ -91,18 +98,23 @@ namespace dr1753 { // dr1753: 11 n.~T(); n.T::~T(); - n.dr1753::~T(); // expected-error {{'dr1753' does not refer to a type name in pseudo-destructor}} + n.dr1753::~T(); + // expected-error@-1 {{'dr1753' does not refer to a type name in pseudo-destructor expression; expected the name of type 'T' (aka 'int')}} n.dr1753::T::~T(); - n.A::~T(); // expected-error {{the type of object expression ('T' (aka 'int')) does not match the type being destroyed ('A') in pseudo-destructor expression}} + n.A::~T(); + // expected-error@-1 {{the type of object expression ('T' (aka 'int')) does not match the type being destroyed ('A') in pseudo-destructor expression}} n.A::T::~T(); - n.B::~T(); // expected-error {{'B' does not refer to a type name in pseudo-destructor expression}} + n.B::~T(); + // expected-error@-1 {{'B' does not refer to a type name in pseudo-destructor expression; expected the name of type 'T' (aka 'int')}} n.B::T::~T(); #if __cplusplus >= 201103L - n.decltype(n)::~T(); // expected-error {{not a class, namespace, or enumeration}} - n.T::~decltype(n)(); // expected-error {{expected a class name after '~'}} + n.decltype(n)::~T(); + // since-cxx11-error@-1 {{'decltype(n)' (aka 'int') is not a class, namespace, or enumeration}} + n.T::~decltype(n)(); + // since-cxx11-error@-1 {{expected a class name after '~' to name a destructor}} n.~decltype(n)(); // OK #endif } @@ -141,9 +153,9 @@ namespace dr1758 { // dr1758: 3.7 namespace dr1762 { // dr1762: 14 #if __cplusplus >= 201103L float operator ""_E(const char *); - // expected-error@+2 {{invalid suffix on literal; C++11 requires a space between literal and identifier}} - // expected-warning@+1 {{user-defined literal suffixes not starting with '_' are reserved; no literal will invoke this operator}} float operator ""E(const char *); + // since-cxx11-error@-1 {{invalid suffix on literal; C++11 requires a space between literal and identifier}} + // since-cxx11-warning@-2 {{user-defined literal suffixes not starting with '_' are reserved; no literal will invoke this operator}} #endif } diff --git a/clang/test/CXX/drs/dr18xx.cpp b/clang/test/CXX/drs/dr18xx.cpp index 7ac26737382281e28225ddd271b13d433bb52c0c..fbe67bd0c2f6dbbd79b26e8df4c249a0c23a74a7 100644 --- a/clang/test/CXX/drs/dr18xx.cpp +++ b/clang/test/CXX/drs/dr18xx.cpp @@ -1,14 +1,14 @@ -// RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -verify -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -verify -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -verify -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -verify -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -verify -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -verify -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -verify -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors - -#if __cplusplus < 201103L -// expected-error@+1 {{variadic macro}} +// RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -verify=expected,cxx98 -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -verify=expected,cxx11-17,since-cxx11 -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -verify=expected,cxx11-17,since-cxx11,since-cxx14 -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -verify=expected,cxx11-17,since-cxx11,since-cxx14 -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx20,since-cxx11,since-cxx14 -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx20,since-cxx11,since-cxx14 -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -verify=expected,since-cxx20,since-cxx11,since-cxx14 -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors + +#if __cplusplus == 199711L #define static_assert(...) __extension__ _Static_assert(__VA_ARGS__) +// cxx98-error@-1 {{variadic macros are a C99 feature}} #endif namespace dr1812 { // dr1812: no @@ -16,7 +16,7 @@ namespace dr1812 { // dr1812: no #if __cplusplus >= 201103L template struct A { using B = typename T::C; - // expected-error@-1 {{use 'template' keyword to treat 'C' as a dependent template name}} + // since-cxx11-error@-1 {{use 'template' keyword to treat 'C' as a dependent template name}} }; #endif } // namespace dr1812 @@ -54,15 +54,20 @@ namespace dr1814 { // dr1814: yes namespace dr1815 { // dr1815: no #if __cplusplus >= 201402L // FIXME: needs codegen test - struct A { int &&r = 0; }; // expected-note {{default member init}} - A a = {}; // FIXME expected-warning {{not supported}} - - struct B { int &&r = 0; }; // expected-error {{binds to a temporary}} expected-note {{default member init}} - B b; // expected-note {{here}} + struct A { int &&r = 0; }; // #dr1815-A + A a = {}; + // since-cxx14-warning@-1 {{sorry, lifetime extension of temporary created by aggregate initialization using default member initializer is not supported; lifetime of temporary will end at the end of the full-expression}} FIXME + // since-cxx14-note@#dr1815-A {{initializing field 'r' with default member initializer}} + + struct B { int &&r = 0; }; // #dr1815-B + // since-cxx14-error@-1 {{reference member 'r' binds to a temporary object whose lifetime would be shorter than the lifetime of the constructed object}} + // since-cxx14-note@#dr1815-B {{initializing field 'r' with default member initializer}} + // since-cxx14-note@#dr1815-b {{in implicit default constructor for 'dr1815::B' first required here}} + B b; // #dr1815-b #endif } -namespace dr1821 { // dr1821: yes +namespace dr1821 { // dr1821: 2.9 struct A { template struct B { void f(); @@ -80,9 +85,9 @@ struct A { namespace dr1822 { // dr1822: yes #if __cplusplus >= 201103L - int a; + double a; auto x = [] (int a) { -#pragma clang __debug dump a // CHECK: ParmVarDecl + static_assert(__is_same(decltype(a), int), "should be resolved to lambda parameter"); }; #endif } @@ -98,16 +103,22 @@ namespace dr1837 { // dr1837: 3.3 }; class Outer { - friend auto Other::q() -> decltype(this->p()) *; // expected-error {{invalid use of 'this'}} + friend auto Other::q() -> decltype(this->p()) *; + // since-cxx11-error@-1 {{invalid use of 'this' outside of a non-static member function}} int g(); int f() { extern void f(decltype(this->g()) *); struct Inner { - static_assert(Fishg())>::value, ""); // expected-error {{invalid use of 'this'}} - enum { X = Fishf())>::value }; // expected-error {{invalid use of 'this'}} - struct Inner2 : Fishg())> { }; // expected-error {{invalid use of 'this'}} - friend void f(decltype(this->g()) *); // expected-error {{invalid use of 'this'}} - friend auto Other::q() -> decltype(this->p()) *; // expected-error {{invalid use of 'this'}} + static_assert(Fishg())>::value, ""); + // since-cxx11-error@-1 {{invalid use of 'this' outside of a non-static member function}} + enum { X = Fishf())>::value }; + // since-cxx11-error@-1 {{invalid use of 'this' outside of a non-static member function}} + struct Inner2 : Fishg())> { }; + // since-cxx11-error@-1 {{invalid use of 'this' outside of a non-static member function}} + friend void f(decltype(this->g()) *); + // since-cxx11-error@-1 {{invalid use of 'this' outside of a non-static member function}} + friend auto Other::q() -> decltype(this->p()) *; + // since-cxx11-error@-1 {{invalid use of 'this' outside of a non-static member function}} }; return 0; } @@ -135,19 +146,21 @@ namespace dr1872 { // dr1872: 9 constexpr int x = A().f(); constexpr int y = A().f(); -#if __cplusplus <= 201703L - // expected-error@-2 {{constant expression}} expected-note@-2 {{call to virtual function}} -#else + // cxx11-17-error@-1 {{constexpr variable 'y' must be initialized by a constant expression}} + // cxx11-17-note@-2 {{cannot evaluate call to virtual function in a constant expression in C++ standards before C++20}} +#if __cplusplus >= 202002L static_assert(y == 0); #endif // Note, this is invalid even though it would not use virtual dispatch. constexpr int y2 = A().A::f(); -#if __cplusplus <= 201703L - // expected-error@-2 {{constant expression}} expected-note@-2 {{call to virtual function}} -#else + // cxx11-17-error@-1 {{constexpr variable 'y2' must be initialized by a constant expression}} + // cxx11-17-note@-2 {{cannot evaluate call to virtual function in a constant expression in C++ standards before C++20}} +#if __cplusplus >= 202002L static_assert(y == 0); #endif - constexpr int z = A().f(); // expected-error {{constant expression}} expected-note {{non-literal type}} + constexpr int z = A().f(); + // since-cxx11-error@-1 {{constexpr variable 'z' must be initialized by a constant expression}} + // since-cxx11-note@-2 {{non-literal type 'A' cannot be used in a constant expression}} #endif } @@ -166,33 +179,38 @@ namespace dr1881 { // dr1881: 7 void dr1891() { // dr1891: 4 #if __cplusplus >= 201103L int n; - auto a = []{}; // expected-note 0-4{{}} - auto b = [=]{ return n; }; // expected-note 0-4{{}} + auto a = []{}; // #dr1891-a + auto b = [=]{ return n; }; // #dr1891-b typedef decltype(a) A; typedef decltype(b) B; static_assert(!__has_trivial_constructor(A), ""); -#if __cplusplus > 201703L - // expected-error@-2 {{failed}} -#endif + // since-cxx20-error@-1 {{failed}} static_assert(!__has_trivial_constructor(B), ""); // C++20 allows default construction for non-capturing lambdas (P0624R2). A x; -#if __cplusplus <= 201703L - // expected-error@-2 {{no matching constructor}} -#endif - B y; // expected-error {{no matching constructor}} + // cxx11-17-error@-1 {{no matching constructor for initialization of 'A' (aka '(lambda at}} + // cxx11-17-note@#dr1891-a {{candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 0 were provided}} + // cxx11-17-note@#dr1891-a {{candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 0 were provided}} + B y; + // since-cxx11-error@-1 {{no matching constructor for initialization of 'B' (aka '(lambda at}} + // since-cxx11-note@#dr1891-b {{candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 0 were provided}} + // since-cxx11-note@#dr1891-b {{candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 0 were provided}} // C++20 allows assignment for non-capturing lambdas (P0624R2). a = a; + // cxx11-17-error-re@-1 {{{{object of type '\(lambda at .+\)' cannot be assigned because its copy assignment operator is implicitly deleted}}}} + // cxx11-17-note@#dr1891-a {{lambda expression begins here}} a = static_cast(a); -#if __cplusplus <= 201703L - // expected-error@-3 {{copy assignment operator is implicitly deleted}} - // expected-error@-3 {{copy assignment operator is implicitly deleted}} -#endif - b = b; // expected-error {{copy assignment operator is implicitly deleted}} - b = static_cast(b); // expected-error {{copy assignment operator is implicitly deleted}} + // cxx11-17-error-re@-1 {{{{object of type '\(lambda at .+\)' cannot be assigned because its copy assignment operator is implicitly deleted}}}} + // cxx11-17-note@#dr1891-a {{lambda expression begins here}} + b = b; + // since-cxx11-error-re@-1 {{{{object of type '\(lambda at .+\)' cannot be assigned because its copy assignment operator is implicitly deleted}}}} + // since-cxx11-note@#dr1891-b {{lambda expression begins here}} + b = static_cast(b); + // since-cxx11-error-re@-1 {{{{object of type '\(lambda at .+\)' cannot be assigned because its copy assignment operator is implicitly deleted}}}} + // since-cxx11-note@#dr1891-b {{lambda expression begins here}} #endif } diff --git a/clang/test/CXX/drs/dr19xx.cpp b/clang/test/CXX/drs/dr19xx.cpp index b15be762ecd1099b5b2b1eb7b3a309895a9db7b6..716b1476831ed96c37a7255eedcf6faafb1e5e33 100644 --- a/clang/test/CXX/drs/dr19xx.cpp +++ b/clang/test/CXX/drs/dr19xx.cpp @@ -1,41 +1,36 @@ -// RUN: %clang_cc1 -std=c++98 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++11 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++14 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++1z %s -verify -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++98 %s -verify=expected,cxx98-11,cxx98 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++11 %s -verify=expected,cxx98-11,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++14 %s -verify=expected,since-cxx14,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++17 %s -verify=expected,since-cxx14,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++20 %s -verify=expected,since-cxx14,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++23 %s -verify=expected,since-cxx14,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++2c %s -verify=expected,since-cxx14,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors namespace std { struct type_info; } namespace dr1902 { // dr1902: 3.7 struct A {}; struct B { - B(A); -#if __cplusplus >= 201103L - // expected-note@-2 {{candidate}} -#endif - - B() = delete; -#if __cplusplus < 201103L - // expected-error@-2 {{extension}} -#endif - - B(const B&) // expected-note {{deleted here}} -#if __cplusplus >= 201103L - // expected-note@-2 {{candidate}} -#else - // expected-error@+2 {{extension}} -#endif - = delete; - + B(A); // #dr1902-B-A + B() = delete; // #dr1902-B-ctor + // cxx98-error@-1 {{deleted function definitions are a C++11 extension}} + B(const B&) = delete; // #dr1902-B-copy-ctor + // cxx98-error@-1 {{deleted function definitions are a C++11 extension}} operator A(); }; extern B b1; - B b2(b1); // expected-error {{call to deleted}} + B b2(b1); + // expected-error@-1 {{call to deleted constructor of 'B'}} + // expected-note@#dr1902-B-copy-ctor {{'B' has been explicitly marked deleted here}} #if __cplusplus >= 201103L // This is ambiguous, even though calling the B(const B&) constructor would // both directly and indirectly call a deleted function. - B b({}); // expected-error {{ambiguous}} + B b({}); + // since-cxx11-error@-1 {{call to constructor of 'B' is ambiguous}} + // since-cxx11-note@#dr1902-B-A {{candidate constructor}} + // since-cxx11-note@#dr1902-B-copy-ctor {{candidate constructor has been explicitly deleted}} #endif } @@ -64,26 +59,33 @@ namespace dr1903 { } } -namespace dr1909 { // dr1909: yes +namespace dr1909 { // dr1909: 3.7 struct A { - template struct A {}; // expected-error {{member 'A' has the same name as its class}} + template struct A {}; + // expected-error@-1 {{member 'A' has the same name as its class}} }; struct B { - template void B() {} // expected-error {{constructor cannot have a return type}} + template void B() {} + // expected-error@-1 {{constructor cannot have a return type}} }; struct C { - template static int C; // expected-error {{member 'C' has the same name as its class}} expected-error 0-1{{extension}} + template static int C; + // expected-error@-1 {{member 'C' has the same name as its class}} + // cxx98-11-error@-2 {{variable templates are a C++14 extension}} }; struct D { - template using D = int; // expected-error {{member 'D' has the same name as its class}} expected-error 0-1{{extension}} + template using D = int; + // cxx98-error@-1 {{alias declarations are a C++11 extension}} + // expected-error@-2 {{member 'D' has the same name as its class}} }; } -namespace dr1940 { // dr1940: yes +namespace dr1940 { // dr1940: 3.5 #if __cplusplus >= 201103L static union { static_assert(true, ""); // ok - static_assert(false, ""); // expected-error {{static assertion failed}} + static_assert(false, ""); + // since-cxx11-error@-1 {{static assertion failed}} int not_empty; }; #endif @@ -119,18 +121,21 @@ derived d2(42, 9); #endif } -namespace dr1947 { // dr1947: yes +namespace dr1947 { // dr1947: 3.5 #if __cplusplus >= 201402L unsigned o = 0'01; // ok -unsigned b = 0b'01; // expected-error {{invalid digit 'b' in octal constant}} -unsigned x = 0x'01; // expected-error {{invalid suffix 'x'01' on integer constant}} +unsigned b = 0b'01; +// since-cxx14-error@-1 {{invalid digit 'b' in octal constant}} +unsigned x = 0x'01; +// since-cxx14-error@-1 {{invalid suffix 'x'01' on integer constant}} #endif } #if __cplusplus >= 201103L -// dr1948: yes +// dr1948: 3.5 // FIXME: This diagnostic could be improved. -void *operator new(__SIZE_TYPE__) noexcept { return nullptr; } // expected-error{{exception specification in declaration does not match previous declaration}} +void *operator new(__SIZE_TYPE__) noexcept { return nullptr; } +// since-cxx11-error@-1 {{exception specification in declaration does not match previous declaration}} #endif namespace dr1959 { // dr1959: 3.9 @@ -139,22 +144,31 @@ namespace dr1959 { // dr1959: 3.9 struct c; struct a { a() = default; - a(const a &) = delete; // expected-note {{deleted}} + a(const a &) = delete; // #dr1959-copy-ctor a(const b &) = delete; // not inherited - a(c &&) = delete; // expected-note {{not viable}} - template a(T) = delete; // expected-note {{would take its own class type by value}} + a(c &&) = delete; // #dr1959-move-ctor + template a(T) = delete; // #dr1959-temp-ctor }; - struct b : a { // expected-note {{cannot bind}} expected-note {{deleted because}} - using a::a; // expected-note 2{{inherited here}} + struct b : a { // #dr1959-b + using a::a; // #dr1959-using-a }; a x; // FIXME: As a resolution to an open DR against P0136R0, we disallow // use of inherited constructors to construct from a single argument // where the base class is reference-related to the argument type. - b y = x; // expected-error {{no viable conversion}} - b z = z; // expected-error {{deleted}} + b y = x; + // since-cxx11-error@-1 {{no viable conversion from 'a' to 'b'}} + // since-cxx11-note@#dr1959-move-ctor {{candidate inherited constructor not viable: no known conversion from 'a' to 'c &&' for 1st argument}} + // since-cxx11-note@#dr1959-using-a {{constructor from base class 'a' inherited here}} + // since-cxx11-note@#dr1959-b {{candidate constructor (the implicit copy constructor) not viable: cannot bind base class object of type 'a' to derived class reference 'const b &' for 1st argument}} + // since-cxx11-note@#dr1959-temp-ctor {{candidate template ignored: instantiation would take its own class type by value}} + // since-cxx11-note@#dr1959-using-a {{constructor from base class 'a' inherited here}} + b z = z; + // since-cxx11-error@-1 {{call to implicitly-deleted copy constructor of 'b'}} + // since-cxx11-note@#dr1959-b {{copy constructor of 'b' is implicitly deleted because base class 'a' has a deleted copy constructor}} + // since-cxx11-note@#dr1959-copy-ctor {{'a' has been explicitly marked deleted here}} struct c : a { using a::a; @@ -191,16 +205,28 @@ using A::g; namespace dr1966 { // dr1966: 11 #if __cplusplus >= 201103L struct A { - enum E : int {1}; // expected-error {{expected identifier}} (not bit-field) + enum E : int {1}; + // since-cxx11-error@-1 {{expected identifier}} (not bit-field) }; - auto *p1 = new enum E : int; // expected-error {{only permitted as a standalone declaration}} - auto *p2 = new enum F : int {}; // expected-error {{only permitted as a standalone declaration}} - auto *p3 = true ? new enum G : int {}; // expected-error {{forward reference}} expected-error {{incomplete}} expected-note {{declaration}} - auto h() -> enum E : int {}; // expected-error {{only permitted as a standalone declaration}} - - enum X : enum Y : int {} {}; // expected-error {{cannot be defined in a type specifier}} + auto *p1 = new enum E : int; + // since-cxx11-error@-1 {{non-defining declaration of enumeration with a fixed underlying type is only permitted as a standalone declaration}} + auto *p2 = new enum F : int {}; + // since-cxx11-error@-1 {{non-defining declaration of enumeration with a fixed underlying type is only permitted as a standalone declaration}} + auto *p3 = true ? new enum G : int {}; + // since-cxx11-error@-1 {{ISO C++ forbids forward references to 'enum' types}} + // since-cxx11-error@-2 {{allocation of incomplete type 'enum G'}} + // since-cxx11-note@-3 {{forward declaration of 'dr1966::G'}} + auto h() -> enum E : int {}; + // since-cxx11-error@-1 {{non-defining declaration of enumeration with a fixed underlying type is only permitted as a standalone declaration}} + + enum X : enum Y : int {} {}; + // since-cxx11-error@-1 {{'dr1966::Y' cannot be defined in a type specifier}} struct Q { - enum X : enum Y : int {} {}; // expected-error +{{}} + // FIXME: can we emit something nicer than that? + enum X : enum Y : int {} {}; + // since-cxx11-error@-1 {{non-defining declaration of enumeration with a fixed underlying type is only permitted as a standalone declaration; missing list of enumerators?}} + // since-cxx11-error@-2 {{non-integral type 'enum Y' is an invalid underlying type}} + // since-cxx11-error@-3 {{anonymous bit-field cannot have a default member initializer}} }; #endif } diff --git a/clang/test/CXX/drs/dr20xx.cpp b/clang/test/CXX/drs/dr20xx.cpp index 4f81b0b413d4bd7aebc16d08a1794112c24b7e15..60ee7684440f54810be19e7010538a37e80a3892 100644 --- a/clang/test/CXX/drs/dr20xx.cpp +++ b/clang/test/CXX/drs/dr20xx.cpp @@ -1,13 +1,14 @@ -// RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors \ -// RUN: -Wno-variadic-macros -Wno-c11-extensions -// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors - -#if __cplusplus < 201103L -#define static_assert(...) _Static_assert(__VA_ARGS__) +// RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -verify=expected,cxx98 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11,cxx11 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11,since-cxx14 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11,since-cxx14 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11,since-cxx14,since-cxx20 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11,since-cxx14,since-cxx20 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11,since-cxx14,since-cxx20 -fexceptions -fcxx-exceptions -pedantic-errors + +#if __cplusplus == 199711L +#define static_assert(...) __extension__ _Static_assert(__VA_ARGS__) +// cxx98-error@-1 {{variadic macros are a C99 feature}} #endif namespace dr2007 { // dr2007: 3.4 @@ -15,8 +16,12 @@ template struct A { typename T::error e; }; template struct B { }; B > b1; B > b2 = b1; -int a = b2[0]; // expected-error {{does not provide a subscript operator}} -int b = __builtin_addressof(b2)->foo; // expected-error {{no member}} +int a = b2[0]; +// cxx98-error@-1 {{type 'B >' does not provide a subscript operator}} +// since-cxx11-error@-2 {{type 'B>' does not provide a subscript operator}} +int b = __builtin_addressof(b2)->foo; +// cxx98-error@-1 {{no member named 'foo' in 'dr2007::B >'}} +// since-cxx11-error@-2 {{no member named 'foo' in 'dr2007::B>'}} } // dr2009: na @@ -24,45 +29,69 @@ int b = __builtin_addressof(b2)->foo; // expected-error {{no member}} namespace dr2026 { // dr2026: 11 template struct X {}; - const int a = a + 1; // expected-warning {{uninitialized}} expected-note {{here}} expected-note 0-1{{outside its lifetime}} - X xa; // expected-error {{constant expression}} expected-note {{initializer of 'a'}} + const int a = a + 1; // #dr2026-a + // expected-warning@-1 {{variable 'a' is uninitialized when used within its own initialization}} + X xa; // #dr2026-xa + // cxx98-error@-1 {{non-type template argument of type 'int' is not an integral constant expression}} + // cxx98-note@-2 {{initializer of 'a' is not a constant expression}} + // cxx98-note@#dr2026-a {{declared here}} + // since-cxx11-error@#dr2026-xa {{non-type template argument is not a constant expression}} + // since-cxx11-note@#dr2026-xa {{initializer of 'a' is not a constant expression}} + // since-cxx11-note@#dr2026-a {{declared here}} #if __cplusplus >= 201103L - constexpr int b = b; // expected-error {{constant expression}} expected-note {{outside its lifetime}} - [[clang::require_constant_initialization]] int c = c; // expected-error {{constant initializer}} expected-note {{attribute}} -#if __cplusplus == 201103L - // expected-note@-2 {{read of non-const variable}} expected-note@-2 {{declared here}} -#else - // expected-note@-4 {{outside its lifetime}} -#endif + constexpr int b = b; + // since-cxx11-error@-1 {{constexpr variable 'b' must be initialized by a constant expression}} + // since-cxx11-note@-2 {{read of object outside its lifetime is not allowed in a constant expression}} + [[clang::require_constant_initialization]] int c = c; + // since-cxx11-error@-1 {{variable does not have a constant initializer}} + // since-cxx11-note@-2 {{required by 'require_constant_initialization' attribute here}} + // cxx11-note@-3 {{read of non-const variable 'c' is not allowed in a constant expression}} + // cxx11-note@-4 {{declared here}} + // since-cxx14-note@-5 {{read of object outside its lifetime is not allowed in a constant expression}} #endif -#if __cplusplus > 201703L - constinit int d = d; // expected-error {{constant initializer}} expected-note {{outside its lifetime}} expected-note {{'constinit'}} +#if __cplusplus >= 202002L + constinit int d = d; + // since-cxx20-error@-1 {{variable does not have a constant initializer}} + // since-cxx20-note@-2 {{required by 'constinit' specifier here}} + // since-cxx20-note@-3 {{read of object outside its lifetime is not allowed in a constant expression}} #endif void f() { - static const int e = e + 1; // expected-warning {{suspicious}} expected-note {{here}} expected-note 0-1{{outside its lifetime}} - X xe; // expected-error {{constant expression}} expected-note {{initializer of 'e'}} + static const int e = e + 1; // #dr2026-e + // expected-warning@-1 {{static variable 'e' is suspiciously used within its own initialization}} + X xe; // #dr2026-xe + // cxx98-error@-1 {{non-type template argument of type 'int' is not an integral constant expression}} + // cxx98-note@-2 {{initializer of 'e' is not a constant expression}} + // cxx98-note@#dr2026-e {{declared here}} + // since-cxx11-error@#dr2026-xe {{non-type template argument is not a constant expression}} + // since-cxx11-note@#dr2026-xe {{initializer of 'e' is not a constant expression}} + // since-cxx11-note@#dr2026-e {{declared here}} #if __cplusplus >= 201103L - static constexpr int f = f; // expected-error {{constant expression}} expected-note {{outside its lifetime}} - [[clang::require_constant_initialization]] static int g = g; // expected-error {{constant initializer}} expected-note {{attribute}} -#if __cplusplus == 201103L - // expected-note@-2 {{read of non-const variable}} expected-note@-2 {{declared here}} -#else - // expected-note@-4 {{outside its lifetime}} -#endif + static constexpr int f = f; + // since-cxx11-error@-1 {{constexpr variable 'f' must be initialized by a constant expression}} + // since-cxx11-note@-2 {{read of object outside its lifetime is not allowed in a constant expression}} + [[clang::require_constant_initialization]] static int g = g; + // since-cxx11-error@-1 {{variable does not have a constant initializer}} + // since-cxx11-note@-2 {{required by 'require_constant_initialization' attribute here}} + // cxx11-note@-3 {{read of non-const variable 'g' is not allowed in a constant expression}} + // cxx11-note@-4 {{declared here}} + // since-cxx14-note@-5 {{read of object outside its lifetime is not allowed in a constant expression}} #endif -#if __cplusplus > 201703L - static constinit int h = h; // expected-error {{constant initializer}} expected-note {{outside its lifetime}} expected-note {{'constinit'}} +#if __cplusplus >= 202002L + static constinit int h = h; + // since-cxx20-error@-1 {{variable does not have a constant initializer}} + // since-cxx20-note@-2 {{required by 'constinit' specifier here}} + // since-cxx20-note@-3 {{read of object outside its lifetime is not allowed in a constant expression}} #endif } } namespace dr2049 { // dr2049: 18 drafting -#if __cplusplus > 202002L +#if __cplusplus >= 202302L template struct X {}; X<> a; X b; @@ -120,8 +149,8 @@ namespace dr2076 { // dr2076: 13 operator string_view() const; }; - void foo(const string &); // expected-note {{cannot convert initializer list}} - void bar(string_view); // expected-note 2{{cannot convert initializer list}} + void foo(const string &); // #dr2076-foo + void bar(string_view); // #dr2076-bar void func(const string &arg) { // An argument in one set of braces is subject to user-defined conversions; @@ -130,11 +159,17 @@ namespace dr2076 { // dr2076: 13 foo(arg); foo({arg}); foo({{arg}}); - foo({{{arg}}}); // expected-error {{no matching function}} + foo({{{arg}}}); + // since-cxx11-error@-1 {{no matching function}} + // since-cxx11-note@#dr2076-foo {{cannot convert initializer list}} bar(arg); bar({arg}); - bar({{arg}}); // expected-error {{no matching function}} - bar({{{arg}}}); // expected-error {{no matching function}} + bar({{arg}}); + // since-cxx11-error@-1 {{no matching function}} + // since-cxx11-note@#dr2076-bar {{cannot convert initializer list}} + bar({{{arg}}}); + // since-cxx11-error@-1 {{no matching function}} + // since-cxx11-note@#dr2076-bar {{cannot convert initializer list}} } #endif } @@ -172,18 +207,20 @@ namespace dr2083 { // dr2083: partial // treatment in C++11 onwards. We continue to apply that even after DR2083. void ref_to_non_const() { int c; - const int &ra = a; // expected-note 0-1{{here}} - int &rb = b; // expected-note 0-1{{here}} - int &rc = c; // expected-note {{here}} + const int &ra = a; // #dr2083-ra + int &rb = b; // #dr2083-rb + int &rc = c; // #dr2083-rc struct A { int f() { int a = ra; + // cxx98-error@-1 {{reference to local variable 'ra' declared in enclosing function 'dr2083::ref_to_non_const'}} + // cxx98-note@#dr2083-ra {{'ra' declared here}} int b = rb; -#if __cplusplus < 201103L - // expected-error@-3 {{in enclosing function}} - // expected-error@-3 {{in enclosing function}} -#endif - int c = rc; // expected-error {{in enclosing function}} + // cxx98-error@-1 {{reference to local variable 'rb' declared in enclosing function 'dr2083::ref_to_non_const'}} + // cxx98-note@#dr2083-rb {{'rb' declared here}} + int c = rc; + // expected-error@-1 {{reference to local variable 'rc' declared in enclosing function 'dr2083::ref_to_non_const'}} + // expected-note@#dr2083-rc {{'rc' declared here}} return a + b + c; } }; @@ -207,18 +244,24 @@ namespace dr2083 { // dr2083: partial constexpr NoMut1 nm1 = {1, 2}; constexpr NoMut2 nm2 = {1, 2}; constexpr NoMut3 nm3 = {1, 2}; - constexpr Mut1 m1 = {1, 2}; // expected-note {{declared here}} - constexpr Mut2 m2 = {1, 2}; // expected-note {{declared here}} - constexpr Mut3 m3 = {1, 2}; // expected-note {{declared here}} + constexpr Mut1 m1 = {1, 2}; // #dr2083-m1 + constexpr Mut2 m2 = {1, 2}; // #dr2083-m2 + constexpr Mut3 m3 = {1, 2}; // #dr2083-m3 struct A { void f() { static_assert(nm1.a == 1, ""); static_assert(nm2.m.a == 1, ""); static_assert(nm3.a == 1, ""); // Can't even access a non-mutable member of a variable containing mutable fields. - static_assert(m1.a == 1, ""); // expected-error {{enclosing function}} - static_assert(m2.m.a == 1, ""); // expected-error {{enclosing function}} - static_assert(m3.a == 1, ""); // expected-error {{enclosing function}} + static_assert(m1.a == 1, ""); + // since-cxx11-error@-1 {{reference to local variable 'm1' declared in enclosing function 'dr2083::mutable_subobjects'}} + // since-cxx11-note@#dr2083-m1 {{'m1' declared here}} + static_assert(m2.m.a == 1, ""); + // since-cxx11-error@-1 {{reference to local variable 'm2' declared in enclosing function 'dr2083::mutable_subobjects'}} + // since-cxx11-note@#dr2083-m2 {{'m2' declared here}} + static_assert(m3.a == 1, ""); + // since-cxx11-error@-1 {{reference to local variable 'm3' declared in enclosing function 'dr2083::mutable_subobjects'}} + // since-cxx11-note@#dr2083-m3 {{'m3' declared here}} } }; } @@ -231,14 +274,16 @@ namespace dr2083 { // dr2083: partial #if __cplusplus >= 201103L constexpr #endif - A a = {}; // expected-note {{here}} + A a = {}; // #dr2083-a struct B { void f() { ellipsis(n); // Even though this is technically modelled as an lvalue-to-rvalue // conversion, it calls a constructor and binds 'a' to a reference, so // it results in an odr-use. - ellipsis(a); // expected-error {{enclosing function}} + ellipsis(a); + // expected-error@-1 {{reference to local variable 'a' declared in enclosing function 'dr2083::ellipsis'}} + // expected-note@#dr2083-a {{'a' declared here}} } }; } @@ -246,7 +291,7 @@ namespace dr2083 { // dr2083: partial #if __cplusplus >= 201103L void volatile_lval() { struct A { int n; }; - constexpr A a = {0}; // expected-note {{here}} + constexpr A a = {0}; // #dr2083-a2 struct B { void f() { // An lvalue-to-rvalue conversion of a volatile lvalue always results @@ -254,7 +299,9 @@ namespace dr2083 { // dr2083: partial int A::*p = &A::n; int x = a.*p; volatile int A::*q = p; - int y = a.*q; // expected-error {{enclosing function}} + int y = a.*q; + // since-cxx11-error@-1 {{reference to local variable 'a' declared in enclosing function 'dr2083::volatile_lval'}} + // since-cxx11-note@#dr2083-a2 {{'a' declared here}} } }; } @@ -262,32 +309,45 @@ namespace dr2083 { // dr2083: partial void discarded_lval() { struct A { int x; mutable int y; volatile int z; }; - A a; // expected-note 1+{{here}} - int &r = a.x; // expected-note {{here}} + A a; // #dr2083-a-3 + int &r = a.x; // #dr2083-r struct B { void f() { - a.x; // expected-warning {{unused}} - a.*&A::x; // expected-warning {{unused}} - true ? a.x : a.y; // expected-warning {{unused}} + // FIXME: We emit more errors than we should be. They are explictly marked below. + a.x; + // expected-warning@-1 {{expression result unused}} + // expected-error@-2 {{reference to local variable 'a' declared in enclosing function 'dr2083::discarded_lval'}} FIXME + // expected-note@#dr2083-a-3 {{'a' declared here}} + a.*&A::x; + // expected-warning@-1 {{expression result unused}} + // expected-error@-2 {{reference to local variable 'a' declared in enclosing function 'dr2083::discarded_lval'}} FIXME + // expected-note@#dr2083-a-3 {{'a' declared here}} + true ? a.x : a.y; // #dr2083-ternary + // expected-warning@-1 {{expression result unused}} + // expected-error@#dr2083-ternary {{reference to local variable 'a' declared in enclosing function 'dr2083::discarded_lval'}} FIXME + // expected-note@#dr2083-a-3 {{'a' declared here}} + // expected-error@#dr2083-ternary {{reference to local variable 'a' declared in enclosing function 'dr2083::discarded_lval'}} FIXME + // expected-note@#dr2083-a-3 {{'a' declared here}} (void)a.x; - a.x, discarded_lval(); // expected-warning {{left operand of comma operator has no effect}} -#if 1 // FIXME: These errors are all incorrect; the above code is valid. - // expected-error@-6 {{enclosing function}} - // expected-error@-6 {{enclosing function}} - // expected-error@-6 2{{enclosing function}} - // expected-error@-6 {{enclosing function}} - // expected-error@-6 {{enclosing function}} -#endif + // expected-error@-1 {{reference to local variable 'a' declared in enclosing function 'dr2083::discarded_lval'}} FIXME + // expected-note@#dr2083-a-3 {{'a' declared here}} + a.x, discarded_lval(); + // expected-warning@-1 {{left operand of comma operator has no effect}} + // expected-error@-2 {{reference to local variable 'a' declared in enclosing function 'dr2083::discarded_lval'}} FIXME + // expected-note@#dr2083-a-3 {{'a' declared here}} // 'volatile' qualifier triggers an lvalue-to-rvalue conversion. - a.z; // expected-error {{enclosing function}} -#if __cplusplus < 201103L - // expected-warning@-2 {{assign into a variable}} -#endif + a.z; + // cxx98-warning@-1 {{expression result unused; assign into a variable to force a volatile load}} + // expected-error@-2 {{reference to local variable 'a' declared in enclosing function 'dr2083::discarded_lval'}} + // expected-note@#dr2083-a-3 {{'a' declared here}} // References always get "loaded" to determine what they reference, // even if the result is discarded. - r; // expected-error {{enclosing function}} expected-warning {{unused}} + r; + // expected-warning@-1 {{expression result unused}} + // expected-error@-2 {{reference to local variable 'r' declared in enclosing function 'dr2083::discarded_lval'}} + // expected-note@#dr2083-r {{'r' declared here}} } }; } @@ -295,12 +355,11 @@ namespace dr2083 { // dr2083: partial namespace dr_example_1 { extern int globx; int main() { - const int &x = globx; + const int &x = globx; // #dr2083-x struct A { -#if __cplusplus < 201103L - // expected-error@+2 {{enclosing function}} expected-note@-3 {{here}} -#endif const int *foo() { return &x; } + // cxx98-error@-1 {{reference to local variable 'x' declared in enclosing function 'dr2083::dr_example_1::main'}} + // cxx98-note@#dr2083-x {{'x' declared here}} } a; return *a.foo(); } diff --git a/clang/test/CXX/drs/dr21xx.cpp b/clang/test/CXX/drs/dr21xx.cpp index a1b8fe3f2a9be953cfbf9c1d7b92f284d474c108..a7e50df3f374be9a3a9915212e50131c60060ef1 100644 --- a/clang/test/CXX/drs/dr21xx.cpp +++ b/clang/test/CXX/drs/dr21xx.cpp @@ -1,13 +1,14 @@ -// RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -verify -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -verify -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -verify -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -verify -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -verify -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -verify -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors - -#if __cplusplus < 201103L -// expected-error@+1 {{variadic macro}} +// RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -verify=expected,cxx98-14,cxx98 -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -verify=expected,cxx98-14,since-cxx11 -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -verify=expected,cxx98-14,since-cxx11 -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11 -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11 -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11 -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11 -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors + +#if __cplusplus == 199711L #define static_assert(...) __extension__ _Static_assert(__VA_ARGS__) +// cxx98-error@-1 {{variadic macros are a C99 feature}} #endif namespace dr2100 { // dr2100: 12 @@ -18,15 +19,14 @@ namespace dr2100 { // dr2100: 12 return X<&n>::n; // ok, value-dependent } int g() { - static const int n = 2; + static const int n = 2; // #dr2100-n return X<&n>::n; // ok, value-dependent -#if __cplusplus < 201702L - // expected-error@-2 {{does not have linkage}} expected-note@-3 {{here}} -#endif + // cxx98-14-error@-1 {{non-type template argument refers to object 'n' that does not have linkage}} + // cxx98-14-note@#dr2100-n {{non-type template argument refers to object here}} } }; template struct X