diff --git a/.github/workflows/libcxx-build-and-test.yaml b/.github/workflows/libcxx-build-and-test.yaml index 268e1033387dcbfa7dd468fb89bacc44a080797f..370cf830a60cf8f0a0558503422e4f14c441fdd4 100644 --- a/.github/workflows/libcxx-build-and-test.yaml +++ b/.github/workflows/libcxx-build-and-test.yaml @@ -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 6751bde4a11a9f6a294b07463ae262af275a6bdb..02b1ab75e960eced4a74e9604bf11b0e01e06d04 100644 --- a/.github/workflows/llvm-project-tests.yml +++ b/.github/workflows/llvm-project-tests.yml @@ -96,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 ${{ inputs.extra_cmake_args }}' + 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 18caa408df57b605e73a951c51660ca16cfc8631..23fab598fc77db7a210874a6d55feb96cd1fa1a6 100644 --- a/.github/workflows/new-prs.yml +++ b/.github/workflows/new-prs.yml @@ -20,12 +20,19 @@ jobs: 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. + # 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 == 'FIRST_TIME_CONTRIBUTOR' || - github.event.pull_request.author_association == 'FIRST_TIMER') + (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: | 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/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/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/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/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/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/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/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/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/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/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst index d34e867f5e6151cf1bb93d9f71571c5b6433ee68..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 diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 28f9393e28437d129750b67c788249fdda74e1b6..066e4ac5b9e54b83965d0cbc64740f12a06aaa0f 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -238,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``. @@ -262,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 ------------------------- @@ -389,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: `_). @@ -511,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 ---------------------------------- @@ -860,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 ------------------------ @@ -960,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 ^^^^^^^^^^^ @@ -999,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 ------------ @@ -1053,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/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 e25b40e11b308a7f44bfdc84a88a3f07e7d8a58d..26c318dd511cbb6bea98d7c8c446ca452eeca1ed 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -3649,6 +3649,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]>; @@ -4253,7 +4261,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 466784673bf9b996fb525d427ac71548338777f1..a8de566db1a7d301edacf1352361c646ada95a3b 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -3657,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/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/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/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index ea08fa84d022cd6f585cbb9f549df9da682ed34d..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< @@ -11998,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 df1eff8cbcc9f015909bb48dbed80809678943ee..7473e00a7bd86bae6f92d4882070f2337a169c65 100644 --- a/clang/include/clang/Basic/Features.def +++ b/clang/include/clang/Basic/Features.def @@ -104,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 6351aeae92e2c457c1b196c095b27d9c291c37d2..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); } 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/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/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h index 1fe2a18cd5dc9ccc23a2ac211603901717b35c45..aa0f5023104a1a9468c017ce92fa850e8c0378e4 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/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_sve.td b/clang/include/clang/Basic/arm_sve.td index 85656c00c5b3ebb7ec977ad85d6e3c3b34a37524..aa9b105364a51a1004873c95e4dda5ac811268df 100644 --- a/clang/include/clang/Basic/arm_sve.td +++ b/clang/include/clang/Basic/arm_sve.td @@ -1935,16 +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", [], []>; +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>]>; @@ -2045,11 +2054,6 @@ 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">; @@ -2258,3 +2262,14 @@ let TargetGuard = "sme2" in { 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/Driver/Options.td b/clang/include/clang/Driver/Options.td index b959fd20fe413d3aa00f83ade021a6f1b110b503..25c76cf2ad2c84ad15c2ac6a39390043477afd91 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -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]>, @@ -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/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/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/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 06634982351647b53cf11a636dbdf94769dc1151..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(); diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index f45e0a7d3d52d43b0ddb3285964c85268ae5f15a..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); @@ -11023,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); 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/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/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/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 4384ace6b6be5e43d8a270c80164a42c2213ed2d..b55b1569a259835f1a8f2b0a910ebd359d7f6f9f 100644 --- a/clang/lib/AST/Interp/InterpBuiltin.cpp +++ b/clang/lib/AST/Interp/InterpBuiltin.cpp @@ -579,6 +579,40 @@ static bool interp__builtin_expect(InterpState &S, CodePtr OpPC, 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; @@ -754,6 +788,39 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F, 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/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/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/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/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 7cf661994a29c770c39d460a6224e57eeae7e92e..37d7a6755d3908c051440edb25f38a4f1c02d216 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -554,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; 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/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/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/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 e241706b9082ee74bc7a1219ac38d67c89d3741c..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 = 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 eb26bfade47b7a450d786f6a2fe1deeba7bd9cdd..f95f3227aba7d03bb4956b62f39569ce6ee49768 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -2660,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, @@ -2706,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"); @@ -2718,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; @@ -2772,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) { @@ -2971,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; @@ -2985,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; @@ -3139,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 51b336216c5653ff04796e101d612da4c9b98979..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; + } } } } 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 9b21fe952af7a8293bf92e41758a290563c3c2d1..502b9f17a06c52ff06434f206489f817f81dfcc4 100644 --- a/clang/lib/Driver/ToolChains/Flang.cpp +++ b/clang/lib/Driver/ToolChains/Flang.cpp @@ -231,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"))); @@ -248,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; @@ -256,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; @@ -264,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; @@ -273,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/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/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/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/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/Sema/HLSLExternalSemaSource.cpp b/clang/lib/Sema/HLSLExternalSemaSource.cpp index 8ed6480a9f5c9c8e878c79ff87c054abf03d9d0a..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; } @@ -478,12 +478,12 @@ void HLSLExternalSemaSource::defineTrivialHLSLTypes() { /// Set up common members and attributes for buffer types static BuiltinTypeDeclBuilder setupBufferType(CXXRecordDecl *Decl, Sema &S, - ResourceClass RC, - ResourceKind RK) { + ResourceClass RC, ResourceKind RK, + bool IsROV) { return BuiltinTypeDeclBuilder(Decl) .addHandleMember() .addDefaultHandleConstructor(S, RC) - .annotateResourceClass(RC, RK); + .annotateResourceClass(RC, RK, IsROV); } void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() { @@ -493,7 +493,18 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() { .Record; onCompletion(Decl, [this](CXXRecordDecl *Decl) { setupBufferType(Decl, *SemaPtr, ResourceClass::UAV, - ResourceKind::TypedBuffer) + 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(); }); diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index 2c7ecf4610de0f064127eface82bb132377c034c..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,7 +2076,7 @@ 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. 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 a729cff53fc11b48d037fedaf4197d91836b784e..cdb6e9584e9554104e3b4921f15d4752440661fe 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -5082,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 @@ -5215,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; } @@ -5983,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(); 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 e3c122de39dfe62571404fecd7ced261b9f2e7a3..19d972ed8ab2d830ec9b099d3a820ff00561bc03 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -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 a345978bb8701ce151b8ecf97c0e686c235cf08d..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) { @@ -9477,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 c6218a491aececec442a08fbd0d64431bfc774eb..36e53c684ac4dc3b012764202dfcd4c3e914ea54 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -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/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp index 4cc87c9fa765c4e544e1b06914a135d443ccc23c..e7b6443c984c912f5bfaf5c7e51daf621d1fd9b5 100644 --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/lib/Sema/SemaLambda.cpp @@ -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/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/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/EnumCastOutOfRangeChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp index 14433d06c2d04eb2dc6e9e2f4d13b56b36f51f17..7c51673422a0a2b2ddbbdc8303e3bda09b56ed36 100644 --- a/clang/lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp @@ -159,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/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/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 35a1f9a75092a05076ebd817986839355b39884b..ce7c8bd357908b2b0862cccdf77bc279526a8359 100644 --- a/clang/test/AST/Interp/builtin-functions.cpp +++ b/clang/test/AST/Interp/builtin-functions.cpp @@ -339,3 +339,27 @@ namespace expect { 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 09835d420672bd2b7801c7c329ff5d2e34504d20..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}} @@ -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/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/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

{ -#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 0204ecaf636180caf6058c80c3a56ba6c8399558..8c34b03c22d5b1af7c1340fc1d819f5ca1c748b7 100644 --- a/clang/test/CXX/drs/dr25xx.cpp +++ b/clang/test/CXX/drs/dr25xx.cpp @@ -1,12 +1,12 @@ -// 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 @@ -17,7 +17,7 @@ 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/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/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/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-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_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/attr-cpuspecific.c b/clang/test/CodeGen/attr-cpuspecific.c index 5baa271b5240f0a2b04f9667f9197ba634cfbda2..2c3e6931800cd883f19b168a2a23327bec4c3e34 100644 --- a/clang/test/CodeGen/attr-cpuspecific.c +++ b/clang/test/CodeGen/attr-cpuspecific.c @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,LINUX -// RUN: %clang_cc1 -triple x86_64-apple-macosx -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,LINUX +// RUN: %clang_cc1 -triple x86_64-apple-macos -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,LINUX // RUN: %clang_cc1 -triple x86_64-windows-pc -fms-compatibility -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,WINDOWS #ifdef _WIN64 diff --git a/clang/test/CodeGen/attr-target-clones.c b/clang/test/CodeGen/attr-target-clones.c index 4a6c35421b243e848d7097f206dbcfda81223dca..3256db061f9a22b18439d0884e32a9c36aea2ae8 100644 --- a/clang/test/CodeGen/attr-target-clones.c +++ b/clang/test/CodeGen/attr-target-clones.c @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefixes=LINUX,CHECK -// RUN: %clang_cc1 -triple x86_64-apple-macosx -emit-llvm %s -o - | FileCheck %s --check-prefixes=DARWIN,CHECK +// RUN: %clang_cc1 -triple x86_64-apple-macos -emit-llvm %s -o - | FileCheck %s --check-prefixes=DARWIN,CHECK // RUN: %clang_cc1 -triple x86_64-windows-pc -emit-llvm %s -o - | FileCheck %s --check-prefixes=WINDOWS,CHECK // LINUX: $foo.resolver = comdat any diff --git a/clang/test/CodeGen/attr-target-mv-func-ptrs.c b/clang/test/CodeGen/attr-target-mv-func-ptrs.c index 7792ca53a4f65ee0f1fffb116b4e819df5117406..e07ad6a7c1067d74c1f3beebc3b59fb0826ef404 100644 --- a/clang/test/CodeGen/attr-target-mv-func-ptrs.c +++ b/clang/test/CodeGen/attr-target-mv-func-ptrs.c @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix=LINUX -// RUN: %clang_cc1 -triple x86_64-apple-macosx -emit-llvm %s -o - | FileCheck %s --check-prefix=LINUX +// RUN: %clang_cc1 -triple x86_64-apple-macos -emit-llvm %s -o - | FileCheck %s --check-prefix=LINUX // RUN: %clang_cc1 -triple x86_64-windows-pc -emit-llvm %s -o - | FileCheck %s --check-prefix=WINDOWS int __attribute__((target("sse4.2"))) foo(int i) { return 0; } int __attribute__((target("arch=sandybridge"))) foo(int); diff --git a/clang/test/CodeGen/attr-target-mv.c b/clang/test/CodeGen/attr-target-mv.c index 67d57b7f277e094a96700826ac16b2b7a8fab584..2c4b95ca04370a02fbc8be6f12833b77418fa7c1 100644 --- a/clang/test/CodeGen/attr-target-mv.c +++ b/clang/test/CodeGen/attr-target-mv.c @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefixes=ITANIUM,LINUX -// RUN: %clang_cc1 -triple x86_64-apple-macosx -emit-llvm %s -o - | FileCheck %s --check-prefixes=ITANIUM,DARWIN +// RUN: %clang_cc1 -triple x86_64-apple-macos -emit-llvm %s -o - | FileCheck %s --check-prefixes=ITANIUM,DARWIN // RUN: %clang_cc1 -triple x86_64-windows-pc -emit-llvm %s -o - | FileCheck %s --check-prefix=WINDOWS int __attribute__((target("sse4.2"))) foo(void) { return 0; } 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/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/CodeGenCXX/attr-cpuspecific.cpp b/clang/test/CodeGenCXX/attr-cpuspecific.cpp index 2294ee4b4c153f89f4dd03a29f323f9b1fd5a7ba..225c6a5c742a5f4df3df346603b8545243a3ecc6 100644 --- a/clang/test/CodeGenCXX/attr-cpuspecific.cpp +++ b/clang/test/CodeGenCXX/attr-cpuspecific.cpp @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck %s --check-prefix=LINUX -// RUN: %clang_cc1 -triple x86_64-apple-macosx -emit-llvm -o - %s | FileCheck %s --check-prefix=LINUX +// RUN: %clang_cc1 -triple x86_64-apple-macos -emit-llvm -o - %s | FileCheck %s --check-prefix=LINUX // RUN: %clang_cc1 -triple x86_64-windows-pc -fms-compatibility -emit-llvm -o - %s | FileCheck %s --check-prefix=WINDOWS struct S { diff --git a/clang/test/CodeGenCXX/attr-target-clones.cpp b/clang/test/CodeGenCXX/attr-target-clones.cpp index 9b20cf9863bcaf4fc77bb69dad841f0c19d33b1d..0814df312f4d8d2089ef61473ebd605316946c7c 100644 --- a/clang/test/CodeGenCXX/attr-target-clones.cpp +++ b/clang/test/CodeGenCXX/attr-target-clones.cpp @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -std=c++11 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefixes=ITANIUM,LINUX -// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-macosx -emit-llvm %s -o - | FileCheck %s --check-prefixes=ITANIUM,DARWIN +// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-macos -emit-llvm %s -o - | FileCheck %s --check-prefixes=ITANIUM,DARWIN // RUN: %clang_cc1 -std=c++11 -triple x86_64-windows-pc -emit-llvm %s -o - | FileCheck %s --check-prefix=WINDOWS // DARWIN-NOT: comdat diff --git a/clang/test/CodeGenCXX/attr-target-mv-diff-ns.cpp b/clang/test/CodeGenCXX/attr-target-mv-diff-ns.cpp index a6ec608240c767a1c7e84c2209ef786ad3dd8bdd..8f2fb5ef0df7e057c1d74258abec999ee67fce75 100644 --- a/clang/test/CodeGenCXX/attr-target-mv-diff-ns.cpp +++ b/clang/test/CodeGenCXX/attr-target-mv-diff-ns.cpp @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -std=c++11 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefixes=ITANIUM,LINUX -// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-macosx -emit-llvm %s -o - | FileCheck %s --check-prefixes=ITANIUM,DARWIN +// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-macos -emit-llvm %s -o - | FileCheck %s --check-prefixes=ITANIUM,DARWIN // RUN: %clang_cc1 -std=c++11 -triple x86_64-windows-pc -emit-llvm %s -o - | FileCheck %s --check-prefix=WINDOWS // Test ensures that this properly differentiates between types in different // namespaces. diff --git a/clang/test/CodeGenCXX/attr-target-mv-func-ptrs.cpp b/clang/test/CodeGenCXX/attr-target-mv-func-ptrs.cpp index 111f6828c43597f7202fc6d2f1d30eb21feee842..f03d5f4914be5343e4a46664b45ec2c2840ea393 100644 --- a/clang/test/CodeGenCXX/attr-target-mv-func-ptrs.cpp +++ b/clang/test/CodeGenCXX/attr-target-mv-func-ptrs.cpp @@ -1,5 +1,5 @@ // 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-apple-macosx -emit-llvm %s -o - | FileCheck %s --check-prefix=LINUX +// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-macos -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 void temp(); void temp(int); diff --git a/clang/test/CodeGenCXX/attr-target-mv-inalloca.cpp b/clang/test/CodeGenCXX/attr-target-mv-inalloca.cpp index f11ac76ca771d3436af35f6eb3b1b265dfeb812c..70c8671c73c93048516dc989dec9e0c20ca80751 100644 --- a/clang/test/CodeGenCXX/attr-target-mv-inalloca.cpp +++ b/clang/test/CodeGenCXX/attr-target-mv-inalloca.cpp @@ -1,7 +1,7 @@ // RUN: %clang_cc1 -std=c++11 -triple i686-windows-msvc -emit-llvm %s -o - | FileCheck %s --check-prefix=WINDOWS // RUN: %clang_cc1 -std=c++11 -triple x86_64-windows-msvc -emit-llvm %s -o - | FileCheck %s --check-prefix=WINDOWS64 // RUN: %clang_cc1 -std=c++11 -triple x86_64-pc-linux -emit-llvm %s -o - | FileCheck %s --check-prefix=LINUX -// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-macosx -emit-llvm %s -o - | FileCheck %s --check-prefix=DARWIN +// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-macos -emit-llvm %s -o - | FileCheck %s --check-prefix=DARWIN struct Foo { Foo(); diff --git a/clang/test/CodeGenCXX/attr-target-mv-member-funcs.cpp b/clang/test/CodeGenCXX/attr-target-mv-member-funcs.cpp index 35a62ee7e773c7032d634252842178f03d7271fa..f956890cf706e321662de83a5f801de3097de786 100644 --- a/clang/test/CodeGenCXX/attr-target-mv-member-funcs.cpp +++ b/clang/test/CodeGenCXX/attr-target-mv-member-funcs.cpp @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -std=c++11 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefixes=ITANIUM,LINUX -// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-macosx -emit-llvm %s -o - | FileCheck %s --check-prefixes=ITANIUM,DARWIN +// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-macos -emit-llvm %s -o - | FileCheck %s --check-prefixes=ITANIUM,DARWIN // RUN: %clang_cc1 -std=c++11 -triple x86_64-windows-pc -emit-llvm %s -o - | FileCheck %s --check-prefix=WINDOWS struct S { diff --git a/clang/test/CodeGenCXX/attr-target-mv-modules.cpp b/clang/test/CodeGenCXX/attr-target-mv-modules.cpp index 3a70e270e9a38fb58fbcb13fbbaf523ed9c2c31e..ac3cf7c4b611c52fc65d368f6266dbc7e1d9a832 100644 --- a/clang/test/CodeGenCXX/attr-target-mv-modules.cpp +++ b/clang/test/CodeGenCXX/attr-target-mv-modules.cpp @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -std=c++11 -triple x86_64-linux-gnu -fmodules -emit-llvm %s -o - | FileCheck %s -// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-macosx -fmodules -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-macos -fmodules -emit-llvm %s -o - | FileCheck %s #pragma clang module build A module A {} #pragma clang module contents diff --git a/clang/test/CodeGenCXX/attr-target-mv-out-of-line-defs.cpp b/clang/test/CodeGenCXX/attr-target-mv-out-of-line-defs.cpp index b81897afb90b82ddf4926e3eca5b564bdf9778e4..3c56cad3af914a7d90e93c0198386014f39db741 100644 --- a/clang/test/CodeGenCXX/attr-target-mv-out-of-line-defs.cpp +++ b/clang/test/CodeGenCXX/attr-target-mv-out-of-line-defs.cpp @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -std=c++11 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefixes=ITANIUM,LINUX -// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-macosx -emit-llvm %s -o - | FileCheck %s --check-prefixes=ITANIUM,DARWIN +// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-macos -emit-llvm %s -o - | FileCheck %s --check-prefixes=ITANIUM,DARWIN // RUN: %clang_cc1 -std=c++11 -triple x86_64-windows-pc -emit-llvm %s -o - | FileCheck %s --check-prefix=WINDOWS struct S { int __attribute__((target("sse4.2"))) foo(int); diff --git a/clang/test/CodeGenCXX/attr-target-mv-overloads.cpp b/clang/test/CodeGenCXX/attr-target-mv-overloads.cpp index dddd8981954e3cbb99e8c54620ff7b24e807be93..e30fbf4ef5027d733400b18abdd8deb42fa27077 100644 --- a/clang/test/CodeGenCXX/attr-target-mv-overloads.cpp +++ b/clang/test/CodeGenCXX/attr-target-mv-overloads.cpp @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -std=c++11 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefixes=ITANIUM,LINUX -// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-macosx -emit-llvm %s -o - | FileCheck %s --check-prefixes=ITANIUM,DARWIN +// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-macos -emit-llvm %s -o - | FileCheck %s --check-prefixes=ITANIUM,DARWIN // RUN: %clang_cc1 -std=c++11 -triple x86_64-windows-pc -emit-llvm %s -o - | FileCheck %s --check-prefix=WINDOWS int __attribute__((target("sse4.2"))) foo_overload(int) { return 0; } 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/arm-cortex-cpus-2.c b/clang/test/Driver/arm-cortex-cpus-2.c index 4bf2b3a50412d0a067f3fae0331b736ee1a16fc7..c322303d22786681c25d11b271f273624d5cc2d7 100644 --- a/clang/test/Driver/arm-cortex-cpus-2.c +++ b/clang/test/Driver/arm-cortex-cpus-2.c @@ -566,7 +566,7 @@ // 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/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/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 707fc8875089f7e483d82b406e656478181f19c4..bdfda430eea86c5ae5f4ff5a193ce225a29dabdf 100644 --- a/clang/test/Misc/pragma-attribute-supported-attributes-list.test +++ b/clang/test/Misc/pragma-attribute-supported-attributes-list.test @@ -90,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 e8c5ecbcb53634e8d941f3cda33344aed8e9ac29..e840a9208f5a4507f988618008bd1d1abd275709 100644 --- a/clang/test/Misc/target-invalid-cpu-note.c +++ b/clang/test/Misc/target-invalid-cpu-note.c @@ -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: 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/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-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/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-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/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/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/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) { } -

- - -