diff --git a/.ci/monolithic-linux.sh b/.ci/monolithic-linux.sh index f0577d1069d5dec5e89950b72a5fd8908a5bcb1b..1e7b2d2a36c2453d8dce7bc08ee53a152b9f2cfc 100755 --- a/.ci/monolithic-linux.sh +++ b/.ci/monolithic-linux.sh @@ -45,7 +45,7 @@ cmake -S ${MONOREPO_ROOT}/llvm -B ${BUILD_DIR} \ -D LLVM_ENABLE_ASSERTIONS=ON \ -D LLVM_BUILD_EXAMPLES=ON \ -D COMPILER_RT_BUILD_LIBFUZZER=OFF \ - -D LLVM_LIT_ARGS="-v --xunit-xml-output ${BUILD_DIR}/test-results.xml" \ + -D LLVM_LIT_ARGS="-v --xunit-xml-output ${BUILD_DIR}/test-results.xml --timeout=1200 --time-tests" \ -D LLVM_ENABLE_LLD=ON \ -D CMAKE_CXX_FLAGS=-gmlt \ -D BOLT_CLANG_EXE=/usr/bin/clang \ diff --git a/.ci/monolithic-windows.sh b/.ci/monolithic-windows.sh index 7ac806a0b399ad54dce56033bd3e2fa8aecedcdc..a704e855f011cb1de8b23c2d0004512c365614b4 100755 --- a/.ci/monolithic-windows.sh +++ b/.ci/monolithic-windows.sh @@ -45,7 +45,7 @@ cmake -S ${MONOREPO_ROOT}/llvm -B ${BUILD_DIR} \ -D LLVM_ENABLE_ASSERTIONS=ON \ -D LLVM_BUILD_EXAMPLES=ON \ -D COMPILER_RT_BUILD_LIBFUZZER=OFF \ - -D LLVM_LIT_ARGS="-v --xunit-xml-output ${BUILD_DIR}/test-results.xml" \ + -D LLVM_LIT_ARGS="-v --xunit-xml-output ${BUILD_DIR}/test-results.xml --timeout=1200 --time-tests" \ -D COMPILER_RT_BUILD_ORC=OFF \ -D CMAKE_C_COMPILER_LAUNCHER=sccache \ -D CMAKE_CXX_COMPILER_LAUNCHER=sccache \ diff --git a/.github/workflows/libcxx-build-and-test.yaml b/.github/workflows/libcxx-build-and-test.yaml index 3fd49541fd7cb2d684db2b93e099ad35b84a0d6c..1666a687aa5d047db680c312ab9228933a4956f3 100644 --- a/.github/workflows/libcxx-build-and-test.yaml +++ b/.github/workflows/libcxx-build-and-test.yaml @@ -161,8 +161,8 @@ jobs: 'generic-no-unicode', 'generic-no-wide-characters', 'generic-no-rtti', + 'generic-optimized-speed', 'generic-static', - 'generic-with_llvm_unwinder', # TODO Find a better place for the benchmark and bootstrapping builds to live. They're either very expensive # or don't provide much value since the benchmark run results are too noise on the bots. 'benchmarks', diff --git a/.github/workflows/llvm-project-tests.yml b/.github/workflows/llvm-project-tests.yml index 594831ee6b5f520bbc30b425e996d43c9ad2d738..fadaea129e5088ea53a7e992fdabdf44f0a4783d 100644 --- a/.github/workflows/llvm-project-tests.yml +++ b/.github/workflows/llvm-project-tests.yml @@ -14,7 +14,7 @@ on: required: false os_list: required: false - default: '["ubuntu-latest", "windows-2019", "macOS-12"]' + default: '["ubuntu-latest", "windows-2019", "macOS-11"]' workflow_call: inputs: build_target: @@ -34,7 +34,9 @@ on: type: string # Use windows-2019 due to: # https://developercommunity.visualstudio.com/t/Prev-Issue---with-__assume-isnan-/1597317 - default: '["ubuntu-latest", "windows-2019", "macOS-12"]' + # We're using a specific version of macOS due to: + # https://github.com/actions/virtual-environments/issues/5900 + default: '["ubuntu-latest", "windows-2019", "macOS-11"]' concurrency: # Skip intermediate builds: always. @@ -89,6 +91,10 @@ jobs: variant: sccache - name: Build and Test uses: llvm/actions/build-test-llvm-project@main + env: + # Workaround for https://github.com/actions/virtual-environments/issues/5900. + # 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 -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 }}' diff --git a/README.md b/README.md index 4ae7eaf9b083a570df38fe2f5a82b8963bf38267..8202ff61d42fb962815f0ae71e03460c69a806b6 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # The LLVM Compiler Infrastructure [![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/llvm/llvm-project/badge)](https://securityscorecards.dev/viewer/?uri=github.com/llvm/llvm-project) +[![libc++](https://github.com/llvm/llvm-project/actions/workflows/libcxx-build-and-test.yaml/badge.svg?branch=main&event=schedule)](https://github.com/llvm/llvm-project/actions/workflows/libcxx-build-and-test.yaml?query=event%3Aschedule) Welcome to the LLVM project! diff --git a/bolt/docs/BAT.md b/bolt/docs/BAT.md new file mode 100644 index 0000000000000000000000000000000000000000..96a9a187e0acf12ccfff601d7b424b0d314b95c7 --- /dev/null +++ b/bolt/docs/BAT.md @@ -0,0 +1,93 @@ +# BOLT Address Translation (BAT) +# Purpose +A regular profile collection for BOLT involves collecting samples from +unoptimized binary. BOLT Address Translation allows collecting profile +from BOLT-optimized binary and using it for optimizing the input (pre-BOLT) +binary. + +# Overview +BOLT Address Translation is an extra section (`.note.bolt_bat`) inserted by BOLT +into the output binary containing translation tables and split functions linkage +information. This information enables mapping the profile back from optimized +binary onto the original binary. + +# Usage +`--enable-bat` flag controls the generation of BAT section. Sampled profile +needs to be passed along with the optimized binary containing BAT section to +`perf2bolt` which reads BAT section and produces fdata profile for the original +binary. Note that YAML profile generation is not supported since BAT doesn't +contain the metadata for input functions. + +# Internals +## Section contents +The section is organized as follows: +- Hot functions table + - Address translation tables +- Cold functions table + +## Construction and parsing +BAT section is created from `BoltAddressTranslation` class which captures +address translation information provided by BOLT linker. It is then encoded as a +note section in the output binary. + +During profile conversion when BAT-enabled binary is passed to perf2bolt, +`BoltAddressTranslation` class is populated from BAT section. The class is then +queried by `DataAggregator` during sample processing to reconstruct addresses/ +offsets in the input binary. + +## Encoding format +The encoding is specified in +[BoltAddressTranslation.h](/bolt/include/bolt/Profile/BoltAddressTranslation.h) +and [BoltAddressTranslation.cpp](/bolt/lib/Profile/BoltAddressTranslation.cpp). + +### Layout +The general layout is as follows: +``` +Hot functions table header +|------------------| +| Function entry | +| |--------------| | +| | OutOff InOff | | +| |--------------| | +~~~~~~~~~~~~~~~~~~~~ + +Cold functions table header +|------------------| +| Function entry | +| |--------------| | +| | OutOff InOff | | +| |--------------| | +~~~~~~~~~~~~~~~~~~~~ +``` + +### Functions table +Hot and cold functions tables share the encoding except difference marked below. +Header: +| Entry | Encoding | Description | +| ------ | ----- | ----------- | +| `NumFuncs` | ULEB128 | Number of functions in the functions table | + +The header is followed by Functions table with `NumFuncs` entries. +Output binary addresses are delta encoded, meaning that only the difference with +the previous output address is stored. Addresses implicitly start at zero. +Hot indices are delta encoded, implicitly starting at zero. +| Entry | Encoding | Description | +| ------ | ------| ----------- | +| `Address` | Delta, ULEB128 | Function address in the output binary | +| `HotIndex` | Delta, ULEB128 | Cold functions only: index of corresponding hot function in hot functions table | +| `NumEntries` | ULEB128 | Number of address translation entries for a function | + +Function header is followed by `NumEntries` pairs of offsets for current +function. + +### Address translation table +Delta encoding means that only the difference with the previous corresponding +entry is encoded. Offsets implicitly start at zero. +| Entry | Encoding | Description | +| ------ | ------| ----------- | +| `OutputOffset` | Delta, ULEB128 | Function offset in output binary | +| `InputOffset` | Delta, SLEB128 | Function offset in input binary with `BRANCHENTRY` LSB bit | + +`BRANCHENTRY` bit denotes whether a given offset pair is a control flow source +(branch or call instruction). If not set, it signifies a control flow target +(basic block offset). diff --git a/bolt/include/bolt/Profile/BoltAddressTranslation.h b/bolt/include/bolt/Profile/BoltAddressTranslation.h index 07e4b283211c698108067913738e0716c5bd3952..01d3be4ee59be340334a3756bb92b49c8b3821ec 100644 --- a/bolt/include/bolt/Profile/BoltAddressTranslation.h +++ b/bolt/include/bolt/Profile/BoltAddressTranslation.h @@ -11,6 +11,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Support/DataExtractor.h" #include #include #include @@ -118,6 +119,16 @@ private: void writeEntriesForBB(MapTy &Map, const BinaryBasicBlock &BB, uint64_t FuncAddress); + /// Write the serialized address translation table for a function. + template + void writeMaps(std::map &Maps, raw_ostream &OS); + + /// Read the serialized address translation table for a function. + /// Return a parse error if failed. + template + void parseMaps(std::vector &HotFuncs, DataExtractor &DE, + uint64_t &Offset, Error &Err); + std::map Maps; /// Links outlined cold bocks to their original function @@ -125,7 +136,7 @@ private: /// Identifies the address of a control-flow changing instructions in a /// translation map entry - const static uint32_t BRANCHENTRY = 0x80000000; + const static uint32_t BRANCHENTRY = 0x1; }; } // namespace bolt diff --git a/bolt/lib/Passes/CacheMetrics.cpp b/bolt/lib/Passes/CacheMetrics.cpp index ba3a2a5f685f38ed10e8e75411a3464bda3c7b94..f6708997a43350d0d005fa3ed0d9132a69fac586 100644 --- a/bolt/lib/Passes/CacheMetrics.cpp +++ b/bolt/lib/Passes/CacheMetrics.cpp @@ -14,23 +14,20 @@ #include "bolt/Passes/CacheMetrics.h" #include "bolt/Core/BinaryBasicBlock.h" #include "bolt/Core/BinaryFunction.h" -#include "llvm/Support/CommandLine.h" #include using namespace llvm; using namespace bolt; -namespace opts { - -extern cl::OptionCategory BoltOptCategory; - -extern cl::opt ITLBPageSize; -extern cl::opt ITLBEntries; - -} // namespace opts - namespace { +/// The following constants are used to estimate the number of i-TLB cache +/// misses for a given code layout. Empirically the values result in high +/// correlations between the estimations and the perf measurements. +/// The constants do not affect the code layout algorithms. +constexpr unsigned ITLBPageSize = 4096; +constexpr unsigned ITLBEntries = 16; + /// Initialize and return a position map for binary basic blocks void extractBasicBlockInfo( const std::vector &BinaryFunctions, @@ -133,9 +130,6 @@ double expectedCacheHitRatio( const std::vector &BinaryFunctions, const std::unordered_map &BBAddr, const std::unordered_map &BBSize) { - - const double PageSize = opts::ITLBPageSize; - const uint64_t CacheEntries = opts::ITLBEntries; std::unordered_map Calls = extractFunctionCalls(BinaryFunctions); // Compute 'hotness' of the functions @@ -155,7 +149,8 @@ double expectedCacheHitRatio( for (BinaryFunction *BF : BinaryFunctions) { if (BF->getLayout().block_empty()) continue; - double Page = BBAddr.at(BF->getLayout().block_front()) / PageSize; + const uint64_t Page = + BBAddr.at(BF->getLayout().block_front()) / ITLBPageSize; PageSamples[Page] += FunctionSamples.at(BF); } @@ -166,15 +161,17 @@ double expectedCacheHitRatio( if (BF->getLayout().block_empty() || FunctionSamples.at(BF) == 0.0) continue; double Samples = FunctionSamples.at(BF); - double Page = BBAddr.at(BF->getLayout().block_front()) / PageSize; + const uint64_t Page = + BBAddr.at(BF->getLayout().block_front()) / ITLBPageSize; // The probability that the page is not present in the cache - double MissProb = pow(1.0 - PageSamples[Page] / TotalSamples, CacheEntries); + const double MissProb = + pow(1.0 - PageSamples[Page] / TotalSamples, ITLBEntries); // Processing all callers of the function for (std::pair Pair : Calls[BF]) { BinaryFunction *SrcFunction = Pair.first; - double SrcPage = - BBAddr.at(SrcFunction->getLayout().block_front()) / PageSize; + const uint64_t SrcPage = + BBAddr.at(SrcFunction->getLayout().block_front()) / ITLBPageSize; // Is this a 'long' or a 'short' call? if (Page != SrcPage) { // This is a miss diff --git a/bolt/lib/Profile/BoltAddressTranslation.cpp b/bolt/lib/Profile/BoltAddressTranslation.cpp index e004309e0e21365008774d033f25b65588f3ff24..697ff1e5dd0da41674bf01a577cf7ad064fcde61 100644 --- a/bolt/lib/Profile/BoltAddressTranslation.cpp +++ b/bolt/lib/Profile/BoltAddressTranslation.cpp @@ -8,8 +8,9 @@ #include "bolt/Profile/BoltAddressTranslation.h" #include "bolt/Core/BinaryFunction.h" -#include "llvm/Support/DataExtractor.h" #include "llvm/Support/Errc.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/LEB128.h" #define DEBUG_TYPE "bolt-bat" @@ -44,7 +45,7 @@ void BoltAddressTranslation::writeEntriesForBB(MapTy &Map, // and this deleted block will both share the same output address (the same // key), and we need to map back. We choose here to privilege the successor by // allowing it to overwrite the previously inserted key in the map. - Map[BBOutputOffset] = BBInputOffset; + Map[BBOutputOffset] = BBInputOffset << 1; const auto &IOAddressMap = BB.getFunction()->getBinaryContext().getIOAddressMap(); @@ -61,8 +62,8 @@ void BoltAddressTranslation::writeEntriesForBB(MapTy &Map, LLVM_DEBUG(dbgs() << " Key: " << Twine::utohexstr(OutputOffset) << " Val: " << Twine::utohexstr(InputOffset) << " (branch)\n"); - Map.insert( - std::pair(OutputOffset, InputOffset | BRANCHENTRY)); + Map.insert(std::pair(OutputOffset, + (InputOffset << 1) | BRANCHENTRY)); } } @@ -101,36 +102,51 @@ void BoltAddressTranslation::write(const BinaryContext &BC, raw_ostream &OS) { } } - const uint32_t NumFuncs = Maps.size(); - OS.write(reinterpret_cast(&NumFuncs), 4); - LLVM_DEBUG(dbgs() << "Writing " << NumFuncs << " functions for BAT.\n"); + writeMaps(Maps, OS); + writeMaps(Maps, OS); + + outs() << "BOLT-INFO: Wrote " << Maps.size() << " BAT maps\n"; +} + +template +void BoltAddressTranslation::writeMaps(std::map &Maps, + raw_ostream &OS) { + const uint32_t NumFuncs = + llvm::count_if(llvm::make_first_range(Maps), [&](const uint64_t Address) { + return Cold == ColdPartSource.count(Address); + }); + encodeULEB128(NumFuncs, OS); + LLVM_DEBUG(dbgs() << "Writing " << NumFuncs << (Cold ? " cold" : "") + << " functions for BAT.\n"); + size_t PrevIndex = 0; + // Output addresses are delta-encoded + uint64_t PrevAddress = 0; for (auto &MapEntry : Maps) { const uint64_t Address = MapEntry.first; + // Only process cold fragments in cold mode, and vice versa. + if (Cold != ColdPartSource.count(Address)) + continue; MapTy &Map = MapEntry.second; const uint32_t NumEntries = Map.size(); LLVM_DEBUG(dbgs() << "Writing " << NumEntries << " entries for 0x" << Twine::utohexstr(Address) << ".\n"); - OS.write(reinterpret_cast(&Address), 8); - OS.write(reinterpret_cast(&NumEntries), 4); + encodeULEB128(Address - PrevAddress, OS); + PrevAddress = Address; + if (Cold) { + size_t HotIndex = + std::distance(ColdPartSource.begin(), ColdPartSource.find(Address)); + encodeULEB128(HotIndex - PrevIndex, OS); + PrevIndex = HotIndex; + } + encodeULEB128(NumEntries, OS); + uint64_t InOffset = 0, OutOffset = 0; + // Output and Input addresses and delta-encoded for (std::pair &KeyVal : Map) { - OS.write(reinterpret_cast(&KeyVal.first), 4); - OS.write(reinterpret_cast(&KeyVal.second), 4); + encodeULEB128(KeyVal.first - OutOffset, OS); + encodeSLEB128(KeyVal.second - InOffset, OS); + std::tie(OutOffset, InOffset) = KeyVal; } } - const uint32_t NumColdEntries = ColdPartSource.size(); - LLVM_DEBUG(dbgs() << "Writing " << NumColdEntries - << " cold part mappings.\n"); - OS.write(reinterpret_cast(&NumColdEntries), 4); - for (std::pair &ColdEntry : ColdPartSource) { - OS.write(reinterpret_cast(&ColdEntry.first), 8); - OS.write(reinterpret_cast(&ColdEntry.second), 8); - LLVM_DEBUG(dbgs() << " " << Twine::utohexstr(ColdEntry.first) << " -> " - << Twine::utohexstr(ColdEntry.second) << "\n"); - } - - outs() << "BOLT-INFO: Wrote " << Maps.size() << " BAT maps\n"; - outs() << "BOLT-INFO: Wrote " << NumColdEntries - << " BAT cold-to-hot entries\n"; } std::error_code BoltAddressTranslation::parse(StringRef Buf) { @@ -152,53 +168,52 @@ std::error_code BoltAddressTranslation::parse(StringRef Buf) { if (Name.substr(0, 4) != "BOLT") return make_error_code(llvm::errc::io_error); - if (Buf.size() - Offset < 4) - return make_error_code(llvm::errc::io_error); + Error Err(Error::success()); + std::vector HotFuncs; + parseMaps(HotFuncs, DE, Offset, Err); + parseMaps(HotFuncs, DE, Offset, Err); + outs() << "BOLT-INFO: Parsed " << Maps.size() << " BAT entries\n"; + return errorToErrorCode(std::move(Err)); +} - const uint32_t NumFunctions = DE.getU32(&Offset); - LLVM_DEBUG(dbgs() << "Parsing " << NumFunctions << " functions\n"); +template +void BoltAddressTranslation::parseMaps(std::vector &HotFuncs, + DataExtractor &DE, uint64_t &Offset, + Error &Err) { + const uint32_t NumFunctions = DE.getULEB128(&Offset, &Err); + LLVM_DEBUG(dbgs() << "Parsing " << NumFunctions << (Cold ? " cold" : "") + << " functions\n"); + size_t HotIndex = 0; + uint64_t PrevAddress = 0; for (uint32_t I = 0; I < NumFunctions; ++I) { - if (Buf.size() - Offset < 12) - return make_error_code(llvm::errc::io_error); - - const uint64_t Address = DE.getU64(&Offset); - const uint32_t NumEntries = DE.getU32(&Offset); + const uint64_t Address = PrevAddress + DE.getULEB128(&Offset, &Err); + PrevAddress = Address; + if (Cold) { + HotIndex += DE.getULEB128(&Offset, &Err); + ColdPartSource.emplace(Address, HotFuncs[HotIndex]); + } else { + HotFuncs.push_back(Address); + } + const uint32_t NumEntries = DE.getULEB128(&Offset, &Err); MapTy Map; LLVM_DEBUG(dbgs() << "Parsing " << NumEntries << " entries for 0x" << Twine::utohexstr(Address) << "\n"); - if (Buf.size() - Offset < 8 * NumEntries) - return make_error_code(llvm::errc::io_error); + uint64_t InputOffset = 0, OutputOffset = 0; for (uint32_t J = 0; J < NumEntries; ++J) { - const uint32_t OutputAddr = DE.getU32(&Offset); - const uint32_t InputAddr = DE.getU32(&Offset); - Map.insert(std::pair(OutputAddr, InputAddr)); - LLVM_DEBUG(dbgs() << Twine::utohexstr(OutputAddr) << " -> " - << Twine::utohexstr(InputAddr) << "\n"); + const uint64_t OutputDelta = DE.getULEB128(&Offset, &Err); + const int64_t InputDelta = DE.getSLEB128(&Offset, &Err); + OutputOffset += OutputDelta; + InputOffset += InputDelta; + Map.insert(std::pair(OutputOffset, InputOffset)); + LLVM_DEBUG(dbgs() << formatv("{0:x} -> {1:x} ({2}/{3}b -> {4}/{5}b)\n", + OutputOffset, InputOffset, OutputDelta, + encodeULEB128(OutputDelta, nulls()), + InputDelta, + encodeSLEB128(InputDelta, nulls()))); } Maps.insert(std::pair(Address, Map)); } - - if (Buf.size() - Offset < 4) - return make_error_code(llvm::errc::io_error); - - const uint32_t NumColdEntries = DE.getU32(&Offset); - LLVM_DEBUG(dbgs() << "Parsing " << NumColdEntries << " cold part mappings\n"); - for (uint32_t I = 0; I < NumColdEntries; ++I) { - if (Buf.size() - Offset < 16) - return make_error_code(llvm::errc::io_error); - const uint32_t ColdAddress = DE.getU64(&Offset); - const uint32_t HotAddress = DE.getU64(&Offset); - ColdPartSource.insert( - std::pair(ColdAddress, HotAddress)); - LLVM_DEBUG(dbgs() << Twine::utohexstr(ColdAddress) << " -> " - << Twine::utohexstr(HotAddress) << "\n"); - } - outs() << "BOLT-INFO: Parsed " << Maps.size() << " BAT entries\n"; - outs() << "BOLT-INFO: Parsed " << NumColdEntries - << " BAT cold-to-hot entries\n"; - - return std::error_code(); } void BoltAddressTranslation::dump(raw_ostream &OS) { @@ -209,7 +224,7 @@ void BoltAddressTranslation::dump(raw_ostream &OS) { OS << "BB mappings:\n"; for (const auto &Entry : MapEntry.second) { const bool IsBranch = Entry.second & BRANCHENTRY; - const uint32_t Val = Entry.second & ~BRANCHENTRY; + const uint32_t Val = Entry.second >> 1; // dropping BRANCHENTRY bit OS << "0x" << Twine::utohexstr(Entry.first) << " -> " << "0x" << Twine::utohexstr(Val); if (IsBranch) @@ -244,7 +259,7 @@ uint64_t BoltAddressTranslation::translate(uint64_t FuncAddress, --KeyVal; - const uint32_t Val = KeyVal->second & ~BRANCHENTRY; + const uint32_t Val = KeyVal->second >> 1; // dropping BRANCHENTRY bit // Branch source addresses are translated to the first instruction of the // source BB to avoid accounting for modifications BOLT may have made in the // BB regarding deletion/addition of instructions. diff --git a/bolt/lib/Rewrite/CMakeLists.txt b/bolt/lib/Rewrite/CMakeLists.txt index b0e2b7f46bef4ca4fa8c21263fd8993ee7f59e2d..6890f52e2b28bbf8a3bc4c9b569b157a4c432f68 100644 --- a/bolt/lib/Rewrite/CMakeLists.txt +++ b/bolt/lib/Rewrite/CMakeLists.txt @@ -6,6 +6,7 @@ set(LLVM_LINK_COMPONENTS Object Support DWARFLinker + DWARFLinkerClassic AsmPrinter TargetParser ) diff --git a/bolt/lib/Rewrite/DWARFRewriter.cpp b/bolt/lib/Rewrite/DWARFRewriter.cpp index 05fb3e8fafe2f7cbfd9162160ef4d9a157b7c63e..8e20306925feac3e2b49ce4061a9886968b0d6c3 100644 --- a/bolt/lib/Rewrite/DWARFRewriter.cpp +++ b/bolt/lib/Rewrite/DWARFRewriter.cpp @@ -21,7 +21,7 @@ #include "llvm/BinaryFormat/Dwarf.h" #include "llvm/CodeGen/AsmPrinter.h" #include "llvm/CodeGen/DIE.h" -#include "llvm/DWARFLinker/DWARFStreamer.h" +#include "llvm/DWARFLinker/Classic/DWARFStreamer.h" #include "llvm/DebugInfo/DWARF/DWARFContext.h" #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h" #include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h" @@ -178,6 +178,9 @@ translateInputToOutputLocationList(const BinaryFunction &BF, return MergedLL; } +using namespace dwarf_linker; +using namespace dwarf_linker::classic; + namespace llvm { namespace bolt { /// Emits debug information into .debug_info or .debug_types section. @@ -278,10 +281,10 @@ private: public: DIEStreamer(DIEBuilder *DIEBldr, DWARFRewriter &Rewriter, - DWARFLinker::OutputFileType OutFileType, + DWARFLinkerBase::OutputFileType OutFileType, raw_pwrite_stream &OutFile, std::function Translator, - DWARFLinker::messageHandler Warning) + DWARFLinkerBase::MessageHandlerTy Warning) : DwarfStreamer(OutFileType, OutFile, Translator, Warning), DIEBldr(DIEBldr), Rewriter(Rewriter){}; @@ -457,7 +460,7 @@ createDIEStreamer(const Triple &TheTriple, raw_pwrite_stream &OutFile, DWARFRewriter &Rewriter) { std::unique_ptr Streamer = std::make_unique( - &DIEBldr, Rewriter, llvm::DWARFLinker::OutputFileType::Object, OutFile, + &DIEBldr, Rewriter, DWARFLinkerBase::OutputFileType::Object, OutFile, [](StringRef Input) -> StringRef { return Input; }, [&](const Twine &Warning, StringRef Context, const DWARFDie *) {}); Error Err = Streamer->init(TheTriple, Swift5ReflectionSegmentName); diff --git a/bolt/lib/Rewrite/RewriteInstance.cpp b/bolt/lib/Rewrite/RewriteInstance.cpp index a95b1650753cfdc73584080dff0a687ecce0d175..f5a8a5b71687454fc5a433a7e6626cf18cf596ff 100644 --- a/bolt/lib/Rewrite/RewriteInstance.cpp +++ b/bolt/lib/Rewrite/RewriteInstance.cpp @@ -4112,6 +4112,7 @@ void RewriteInstance::encodeBATSection() { copyByteArray(BoltInfo), BoltInfo.size(), /*Alignment=*/1, /*IsReadOnly=*/true, ELF::SHT_NOTE); + outs() << "BOLT-INFO: BAT section size (bytes): " << BoltInfo.size() << '\n'; } template diff --git a/bolt/test/RISCV/relax.s b/bolt/test/RISCV/relax.s index bf9287e1d0d85a456e44c36f8b2e6598c88b8d14..ec390ea76b5c7291ee9d95d6b9c6b494b5a4aeef 100644 --- a/bolt/test/RISCV/relax.s +++ b/bolt/test/RISCV/relax.s @@ -6,7 +6,7 @@ // CHECK: Binary Function "_start" after building cfg { // CHECK: jal ra, near_f -// CHECK-NEXT: auipc ra, far_f@plt +// CHECK-NEXT: auipc ra, far_f // CHECK-NEXT: jalr ra, 0xc(ra) // CHECK-NEXT: j near_f diff --git a/bolt/test/X86/bolt-address-translation.test b/bolt/test/X86/bolt-address-translation.test index f68a8f7e9bcb7f69f7bbe11b1113246ddd166220..430b4cb007310fac131d36b8082a89bd9acdd292 100644 --- a/bolt/test/X86/bolt-address-translation.test +++ b/bolt/test/X86/bolt-address-translation.test @@ -36,7 +36,7 @@ # # CHECK: BOLT: 3 out of 7 functions were overwritten. # CHECK: BOLT-INFO: Wrote 6 BAT maps -# CHECK: BOLT-INFO: Wrote 3 BAT cold-to-hot entries +# CHECK: BOLT-INFO: BAT section size (bytes): 404 # # usqrt mappings (hot part). We match against any key (left side containing # the bolted binary offsets) because BOLT may change where it puts instructions diff --git a/clang-tools-extra/clang-include-fixer/tool/clang-include-fixer.el b/clang-tools-extra/clang-include-fixer/tool/clang-include-fixer.el index 272f282c47f5fc027302700c0ce2b1d6e5e05fc4..f3a949f8c1b5525072b8f27acb54c6692b55440e 100644 --- a/clang-tools-extra/clang-include-fixer/tool/clang-include-fixer.el +++ b/clang-tools-extra/clang-include-fixer/tool/clang-include-fixer.el @@ -1,5 +1,6 @@ ;;; clang-include-fixer.el --- Emacs integration of the clang include fixer -*- lexical-binding: t; -*- +;; Version: 0.1.0 ;; Keywords: tools, c ;; Package-Requires: ((cl-lib "0.5") (json "1.2") (let-alist "1.0.4")) diff --git a/clang-tools-extra/clang-query/QueryParser.cpp b/clang-tools-extra/clang-query/QueryParser.cpp index 41933625a4fa07b4a364ad9a5a3238a4d2f99ffe..162acc1a598dd58f36f5244abf70312b6e1bcd99 100644 --- a/clang-tools-extra/clang-query/QueryParser.cpp +++ b/clang-tools-extra/clang-query/QueryParser.cpp @@ -28,10 +28,8 @@ namespace query { // is found before End, return StringRef(). Begin is adjusted to exclude the // lexed region. StringRef QueryParser::lexWord() { - Line = Line.drop_while([](char c) { - // Don't trim newlines. - return StringRef(" \t\v\f\r").contains(c); - }); + // Don't trim newlines. + Line = Line.ltrim(" \t\v\f\r"); if (Line.empty()) // Even though the Line is empty, it contains a pointer and @@ -152,8 +150,7 @@ QueryRef QueryParser::parseSetTraversalKind(TraversalKind QuerySession::*Var) { QueryRef QueryParser::endQuery(QueryRef Q) { StringRef Extra = Line; - StringRef ExtraTrimmed = Extra.drop_while( - [](char c) { return StringRef(" \t\v\f\r").contains(c); }); + StringRef ExtraTrimmed = Extra.ltrim(" \t\v\f\r"); if ((!ExtraTrimmed.empty() && ExtraTrimmed[0] == '\n') || (ExtraTrimmed.size() >= 2 && ExtraTrimmed[0] == '\r' && diff --git a/clang-tools-extra/clang-tidy/misc/StaticAssertCheck.cpp b/clang-tools-extra/clang-tidy/misc/StaticAssertCheck.cpp index 77763a9f429f2b4484f247d2fc1da730e5526645..35536b47700a650751ec56bd7cc91c183e35edeb 100644 --- a/clang-tools-extra/clang-tidy/misc/StaticAssertCheck.cpp +++ b/clang-tools-extra/clang-tidy/misc/StaticAssertCheck.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "StaticAssertCheck.h" +#include "../utils/Matchers.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Expr.h" #include "clang/ASTMatchers/ASTMatchFinder.h" @@ -45,13 +46,20 @@ void StaticAssertCheck::registerMatchers(MatchFinder *Finder) { IsAlwaysFalse); auto NonConstexprFunctionCall = callExpr(hasDeclaration(functionDecl(unless(isConstexpr())))); + auto NonConstexprVariableReference = + declRefExpr(to(varDecl(unless(isConstexpr()))), + unless(hasAncestor(expr(matchers::hasUnevaluatedContext()))), + unless(hasAncestor(typeLoc()))); + + auto NonConstexprCode = + expr(anyOf(NonConstexprFunctionCall, NonConstexprVariableReference)); auto AssertCondition = expr( anyOf(expr(ignoringParenCasts(anyOf( AssertExprRoot, unaryOperator(hasUnaryOperand( ignoringParenCasts(AssertExprRoot)))))), anything()), - unless(findAll(NonConstexprFunctionCall))) + unless(NonConstexprCode), unless(hasDescendant(NonConstexprCode))) .bind("condition"); auto Condition = anyOf(ignoringParenImpCasts(callExpr( diff --git a/clang-tools-extra/clang-tidy/misc/UnusedUsingDeclsCheck.h b/clang-tools-extra/clang-tidy/misc/UnusedUsingDeclsCheck.h index fa2a8799d098c3cfc899ac13c1817b0c3051f3da..498b3ffd2678c32a943d04b5757aedc6ea40c6e1 100644 --- a/clang-tools-extra/clang-tidy/misc/UnusedUsingDeclsCheck.h +++ b/clang-tools-extra/clang-tidy/misc/UnusedUsingDeclsCheck.h @@ -26,6 +26,9 @@ public: void registerMatchers(ast_matchers::MatchFinder *Finder) override; void check(const ast_matchers::MatchFinder::MatchResult &Result) override; void onEndOfTranslationUnit() override; + bool isLanguageVersionSupported(const LangOptions &LangOpts) const override { + return LangOpts.CPlusPlus; + } private: void removeFromFoundDecls(const Decl *D); diff --git a/clang-tools-extra/clangd/AST.cpp b/clang-tools-extra/clangd/AST.cpp index ae79eb21de9470fa3a82aa24c0b147a9625b34b5..3e374cf2a89764edd25cea6e053eb212cad63c9c 100644 --- a/clang-tools-extra/clangd/AST.cpp +++ b/clang-tools-extra/clangd/AST.cpp @@ -757,7 +757,7 @@ const TemplateTypeParmType *getFunctionPackType(const FunctionDecl *Callee) { // Returns the template parameter pack type that this parameter was expanded // from (if in the Args... or Args&... or Args&&... form), if this is the case, // nullptr otherwise. -const TemplateTypeParmType *getUnderylingPackType(const ParmVarDecl *Param) { +const TemplateTypeParmType *getUnderlyingPackType(const ParmVarDecl *Param) { const auto *PlainType = Param->getType().getTypePtr(); if (auto *RT = dyn_cast(PlainType)) PlainType = RT->getPointeeTypeAsWritten().getTypePtr(); @@ -793,8 +793,8 @@ class ForwardingCallVisitor : public RecursiveASTVisitor { public: ForwardingCallVisitor(ArrayRef Parameters) - : Parameters{Parameters}, PackType{getUnderylingPackType( - Parameters.front())} {} + : Parameters{Parameters}, + PackType{getUnderlyingPackType(Parameters.front())} {} bool VisitCallExpr(CallExpr *E) { auto *Callee = getCalleeDeclOrUniqueOverload(E); @@ -859,7 +859,7 @@ private: if (const auto *TTPT = getFunctionPackType(Callee)) { // In this case: Separate the parameters into head, pack and tail auto IsExpandedPack = [&](const ParmVarDecl *P) { - return getUnderylingPackType(P) == TTPT; + return getUnderlyingPackType(P) == TTPT; }; ForwardingInfo FI; FI.Head = MatchingParams.take_until(IsExpandedPack); @@ -964,7 +964,7 @@ resolveForwardingParameters(const FunctionDecl *D, unsigned MaxDepth) { if (const auto *TTPT = getFunctionPackType(D)) { // Split the parameters into head, pack and tail auto IsExpandedPack = [TTPT](const ParmVarDecl *P) { - return getUnderylingPackType(P) == TTPT; + return getUnderlyingPackType(P) == TTPT; }; ArrayRef Head = Parameters.take_until(IsExpandedPack); ArrayRef Pack = @@ -1016,7 +1016,7 @@ resolveForwardingParameters(const FunctionDecl *D, unsigned MaxDepth) { } bool isExpandedFromParameterPack(const ParmVarDecl *D) { - return getUnderylingPackType(D) != nullptr; + return getUnderlyingPackType(D) != nullptr; } } // namespace clangd diff --git a/clang-tools-extra/clangd/CompileCommands.cpp b/clang-tools-extra/clangd/CompileCommands.cpp index f4e8e7e74a3beeee1f5f233a676f0b03d34d29fc..166f17e9b3f7125b378e13fb9777c98cee28129e 100644 --- a/clang-tools-extra/clangd/CompileCommands.cpp +++ b/clang-tools-extra/clangd/CompileCommands.cpp @@ -313,13 +313,15 @@ void CommandMangler::operator()(tooling::CompileCommand &Command, tooling::addTargetAndModeForProgramName(Cmd, Cmd.front()); - // Check whether the flag exists, either as -flag or -flag=* - auto Has = [&](llvm::StringRef Flag) { - for (llvm::StringRef Arg : Cmd) { - if (Arg.consume_front(Flag) && (Arg.empty() || Arg[0] == '=')) - return true; - } - return false; + // Check whether the flag exists in the command. + auto HasExact = [&](llvm::StringRef Flag) { + return llvm::any_of(Cmd, [&](llvm::StringRef Arg) { return Arg == Flag; }); + }; + + // Check whether the flag appears in the command as a prefix. + auto HasPrefix = [&](llvm::StringRef Flag) { + return llvm::any_of( + Cmd, [&](llvm::StringRef Arg) { return Arg.starts_with(Flag); }); }; llvm::erase_if(Cmd, [](llvm::StringRef Elem) { @@ -327,12 +329,13 @@ void CommandMangler::operator()(tooling::CompileCommand &Command, }); std::vector ToAppend; - if (ResourceDir && !Has("-resource-dir")) + if (ResourceDir && !HasExact("-resource-dir") && !HasPrefix("-resource-dir=")) ToAppend.push_back(("-resource-dir=" + *ResourceDir)); // Don't set `-isysroot` if it is already set or if `--sysroot` is set. // `--sysroot` is a superset of the `-isysroot` argument. - if (Sysroot && !Has("-isysroot") && !Has("--sysroot")) { + if (Sysroot && !HasPrefix("-isysroot") && !HasExact("--sysroot") && + !HasPrefix("--sysroot=")) { ToAppend.push_back("-isysroot"); ToAppend.push_back(*Sysroot); } @@ -343,7 +346,7 @@ void CommandMangler::operator()(tooling::CompileCommand &Command, } if (!Cmd.empty()) { - bool FollowSymlink = !Has("-no-canonical-prefixes"); + bool FollowSymlink = !HasExact("-no-canonical-prefixes"); Cmd.front() = (FollowSymlink ? ResolvedDrivers : ResolvedDriversNoFollow) .get(Cmd.front(), [&, this] { diff --git a/clang-tools-extra/clangd/Selection.cpp b/clang-tools-extra/clangd/Selection.cpp index 8c6d5750ecefdba4e970282cdcbfc34ff5920881..277cb8769a1b1257b02e5a9592ad50bf8e4c8fd2 100644 --- a/clang-tools-extra/clangd/Selection.cpp +++ b/clang-tools-extra/clangd/Selection.cpp @@ -1113,6 +1113,9 @@ const DeclContext &SelectionTree::Node::getDeclContext() const { return *DC; return *Current->getLexicalDeclContext(); } + if (const auto *LE = CurrentNode->ASTNode.get()) + if (CurrentNode != this) + return *LE->getCallOperator(); } llvm_unreachable("A tree must always be rooted at TranslationUnitDecl."); } diff --git a/clang-tools-extra/clangd/unittests/CompileCommandsTests.cpp b/clang-tools-extra/clangd/unittests/CompileCommandsTests.cpp index 772177b60b5eed4d02c4188d38976d47b569cb54..b64dd4acad4c225cdf71e9e873e18bba1d1666fd 100644 --- a/clang-tools-extra/clangd/unittests/CompileCommandsTests.cpp +++ b/clang-tools-extra/clangd/unittests/CompileCommandsTests.cpp @@ -370,9 +370,8 @@ TEST(ArgStripperTest, OrderDependent) { } TEST(PrintArgvTest, All) { - std::vector Args = { - "one", "two", "thr ee", "f\"o\"ur", "fi\\ve", "$" - }; + std::vector Args = {"one", "two", "thr ee", + "f\"o\"ur", "fi\\ve", "$"}; const char *Expected = R"(one two "thr ee" "f\"o\"ur" "fi\\ve" $)"; EXPECT_EQ(Expected, printArgv(Args)); } @@ -450,6 +449,82 @@ TEST(CommandMangler, PathsAsPositional) { Mangler(Cmd, "a.cc"); EXPECT_THAT(Cmd.CommandLine, Contains("foo")); } + +TEST(CommandMangler, RespectsOriginalResourceDir) { + auto Mangler = CommandMangler::forTests(); + Mangler.ResourceDir = testPath("fake/resources"); + + { + tooling::CompileCommand Cmd; + Cmd.CommandLine = {"clang++", "-resource-dir", testPath("true/resources"), + "foo.cc"}; + Mangler(Cmd, "foo.cc"); + EXPECT_THAT(llvm::join(Cmd.CommandLine, " "), + HasSubstr("-resource-dir " + testPath("true/resources"))); + EXPECT_THAT(llvm::join(Cmd.CommandLine, " "), + Not(HasSubstr(testPath("fake/resources")))); + } + + { + tooling::CompileCommand Cmd; + Cmd.CommandLine = {"clang++", "-resource-dir=" + testPath("true/resources"), + "foo.cc"}; + Mangler(Cmd, "foo.cc"); + EXPECT_THAT(llvm::join(Cmd.CommandLine, " "), + HasSubstr("-resource-dir=" + testPath("true/resources"))); + EXPECT_THAT(llvm::join(Cmd.CommandLine, " "), + Not(HasSubstr(testPath("fake/resources")))); + } +} + +TEST(CommandMangler, RespectsOriginalSysroot) { + auto Mangler = CommandMangler::forTests(); + Mangler.Sysroot = testPath("fake/sysroot"); + + { + tooling::CompileCommand Cmd; + Cmd.CommandLine = {"clang++", "-isysroot", testPath("true/sysroot"), + "foo.cc"}; + Mangler(Cmd, "foo.cc"); + EXPECT_THAT(llvm::join(Cmd.CommandLine, " "), + HasSubstr("-isysroot " + testPath("true/sysroot"))); + EXPECT_THAT(llvm::join(Cmd.CommandLine, " "), + Not(HasSubstr(testPath("fake/sysroot")))); + } + + { + tooling::CompileCommand Cmd; + Cmd.CommandLine = {"clang++", "-isysroot" + testPath("true/sysroot"), + "foo.cc"}; + Mangler(Cmd, "foo.cc"); + EXPECT_THAT(llvm::join(Cmd.CommandLine, " "), + HasSubstr("-isysroot" + testPath("true/sysroot"))); + EXPECT_THAT(llvm::join(Cmd.CommandLine, " "), + Not(HasSubstr(testPath("fake/sysroot")))); + } + + { + tooling::CompileCommand Cmd; + Cmd.CommandLine = {"clang++", "--sysroot", testPath("true/sysroot"), + "foo.cc"}; + Mangler(Cmd, "foo.cc"); + EXPECT_THAT(llvm::join(Cmd.CommandLine, " "), + HasSubstr("--sysroot " + testPath("true/sysroot"))); + EXPECT_THAT(llvm::join(Cmd.CommandLine, " "), + Not(HasSubstr(testPath("fake/sysroot")))); + } + + { + tooling::CompileCommand Cmd; + Cmd.CommandLine = {"clang++", "--sysroot=" + testPath("true/sysroot"), + "foo.cc"}; + Mangler(Cmd, "foo.cc"); + EXPECT_THAT(llvm::join(Cmd.CommandLine, " "), + HasSubstr("--sysroot=" + testPath("true/sysroot"))); + EXPECT_THAT(llvm::join(Cmd.CommandLine, " "), + Not(HasSubstr(testPath("fake/sysroot")))); + } +} } // namespace } // namespace clangd } // namespace clang diff --git a/clang-tools-extra/clangd/unittests/SelectionTests.cpp b/clang-tools-extra/clangd/unittests/SelectionTests.cpp index 4c019a1524f3c39c0ac340c7db08653b1a142a86..754e8c287c514869506c7efde8816f340d664466 100644 --- a/clang-tools-extra/clangd/unittests/SelectionTests.cpp +++ b/clang-tools-extra/clangd/unittests/SelectionTests.cpp @@ -880,6 +880,19 @@ TEST(SelectionTest, DeclContextIsLexical) { } } +TEST(SelectionTest, DeclContextLambda) { + llvm::Annotations Test(R"cpp( + void foo(); + auto lambda = [] { + return $1^foo(); + }; + )cpp"); + auto AST = TestTU::withCode(Test.code()).build(); + auto ST = SelectionTree::createRight(AST.getASTContext(), AST.getTokens(), + Test.point("1"), Test.point("1")); + EXPECT_TRUE(ST.commonAncestor()->getDeclContext().isFunctionOrMethod()); +} + } // namespace } // namespace clangd } // namespace clang diff --git a/clang-tools-extra/clangd/unittests/tweaks/AddUsingTests.cpp b/clang-tools-extra/clangd/unittests/tweaks/AddUsingTests.cpp index 1fd2487378d7055fa07729934d7f1c193fa43df6..c2dd8e1bb8eefaaefe8daa9987675aa2202c2f5a 100644 --- a/clang-tools-extra/clangd/unittests/tweaks/AddUsingTests.cpp +++ b/clang-tools-extra/clangd/unittests/tweaks/AddUsingTests.cpp @@ -309,6 +309,29 @@ namespace foo { void fun(); } void foo::fun() { ff(); })cpp"}, + // Inside a lambda. + { + R"cpp( +namespace NS { +void unrelated(); +void foo(); +} + +auto L = [] { + using NS::unrelated; + NS::f^oo(); +};)cpp", + R"cpp( +namespace NS { +void unrelated(); +void foo(); +} + +auto L = [] { + using NS::foo;using NS::unrelated; + foo(); +};)cpp", + }, // If all other using are fully qualified, add :: {R"cpp( #include "test.hpp" diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 1bd5a72126c10be7762cecf96e91369d5ab1992b..3437b6cf9b59e94b991883231c4c248fd85aa29c 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -119,7 +119,7 @@ Improvements to clang-tidy - Improved `--dump-config` to print check options in alphabetical order. -- Improved :program:`clang-tidy-diff.py` script. +- Improved :program:`clang-tidy-diff.py` script. * Return exit code `1` if any :program:`clang-tidy` subprocess exits with a non-zero code or if exporting fixes fails. @@ -368,7 +368,8 @@ Changes in existing checks ` check to avoid false positive when using pointer to member function. Additionally, the check no longer emits a diagnostic when a variable that is not type-dependent is an operand of a - type-dependent binary operator. + type-dependent binary operator. Improved performance of the check through + optimizations. - Improved :doc:`misc-include-cleaner ` check by adding option @@ -380,9 +381,13 @@ Changes in existing checks ` check to ignore false-positives in unevaluated context (e.g., ``decltype``). +- Improved :doc:`misc-static-assert + ` check to ignore false-positives when + referring to non-``constexpr`` variables in non-unevaluated context. + - Improved :doc:`misc-unused-using-decls ` check to avoid false positive when - using in elaborated type. + using in elaborated type and only check cpp files. - Improved :doc:`modernize-avoid-bind ` check to diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/static-assert.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/static-assert.cpp index da4ab9baa3948a581e380a8d3e92e08bd2d8a373..16c6ba60c1925f954fb180dcfe6f0b130b149ff1 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/misc/static-assert.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/misc/static-assert.cpp @@ -20,6 +20,48 @@ void print(...); #define my_macro() assert(0 == 1) // CHECK-FIXES: #define my_macro() assert(0 == 1) +namespace PR24066 { + +void referenceMember() { + struct { + int A; + int B; + } S; + assert(&S.B - &S.A == 1); +} + +const int X = 1; +void referenceVariable() { + assert(X > 0); +} + + +constexpr int Y = 1; +void referenceConstexprVariable() { + assert(Y > 0); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: found assert() that could be replaced by static_assert() [misc-static-assert] + // CHECK-FIXES-CXX11: {{^ }}static_assert(Y > 0, ""); + // CHECK-FIXES-CXX17: {{^ }}static_assert(Y > 0); +} + +void useInSizeOf() { + char a = 0; + assert(sizeof(a) == 1U); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: found assert() that could be replaced by static_assert() [misc-static-assert] + // CHECK-FIXES-CXX11: {{^ }}static_assert(sizeof(a) == 1U, ""); + // CHECK-FIXES-CXX17: {{^ }}static_assert(sizeof(a) == 1U); +} + +void useInDecltype() { + char a = 0; + assert(static_cast(256) == 0); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: found assert() that could be replaced by static_assert() [misc-static-assert] + // CHECK-FIXES-CXX11: {{^ }}static_assert(static_cast(256) == 0, ""); + // CHECK-FIXES-CXX17: {{^ }}static_assert(static_cast(256) == 0); +} + +} + constexpr bool myfunc(int a, int b) { return a * b == 0; } typedef __SIZE_TYPE__ size_t; diff --git a/clang/CMakeLists.txt b/clang/CMakeLists.txt index 9f814478c4550398b61a4040ce52245455807327..5f2b7f064da437705395f2c7203e5170fcd16ec0 100644 --- a/clang/CMakeLists.txt +++ b/clang/CMakeLists.txt @@ -193,6 +193,12 @@ set(C_INCLUDE_DIRS "" CACHE STRING set(GCC_INSTALL_PREFIX "" CACHE PATH "Directory where gcc is installed." ) set(DEFAULT_SYSROOT "" CACHE STRING "Default to all compiler invocations for --sysroot=." ) +if(GCC_INSTALL_PREFIX) + message(WARNING "GCC_INSTALL_PREFIX is deprecated and will be removed. Use " + "configuration files (https://clang.llvm.org/docs/UsersManual.html#configuration-files)" + "to specify the default --gcc-install-dir= or --gcc-triple=. --gcc-toolchain= is discouraged. " + "See https://github.com/llvm/llvm-project/pull/77537 for detail.") +endif() set(ENABLE_LINKER_BUILD_ID OFF CACHE BOOL "pass --build-id to ld") diff --git a/clang/cmake/caches/Fuchsia.cmake b/clang/cmake/caches/Fuchsia.cmake index dad434be720da11beabbbdf7a47a54dee84fd661..bb2ed30690098e5ce165b0fc9d321a8747610da8 100644 --- a/clang/cmake/caches/Fuchsia.cmake +++ b/clang/cmake/caches/Fuchsia.cmake @@ -38,9 +38,25 @@ set(_FUCHSIA_BOOTSTRAP_PASSTHROUGH CURL_ROOT OpenSSL_ROOT httplib_ROOT + + # Deprecated CursesAndPanel_ROOT + + CURSES_INCLUDE_DIRS + CURSES_LIBRARIES + PANEL_LIBRARIES + + # Deprecated Terminfo_ROOT + + Terminfo_LIBRARIES + + # Deprecated LibEdit_ROOT + + LibEdit_INCLUDE_DIRS + LibEdit_LIBRARIES + FUCHSIA_ENABLE_LLDB LLDB_ENABLE_CURSES LLDB_ENABLE_LIBEDIT diff --git a/clang/cmake/caches/Release.cmake b/clang/cmake/caches/Release.cmake index 3ea65ce26296c86689e437af5f57e9060f4e0a7e..a7b9a8d0e29f88f9ddcb3f94851b7b0f2cf66005 100644 --- a/clang/cmake/caches/Release.cmake +++ b/clang/cmake/caches/Release.cmake @@ -2,6 +2,9 @@ # BOOTSTRAP_* options configure the second build. # BOOTSTRAP_BOOTSTRAP_* options configure the third build. +# General Options +set(LLVM_RELEASE_ENABLE_LTO THIN CACHE STRING "") + set(CMAKE_BUILD_TYPE RELEASE CACHE STRING "") # Stage 1 Bootstrap Setup @@ -33,9 +36,17 @@ set(BOOTSTRAP_CLANG_BOOTSTRAP_TARGETS check-clang CACHE STRING "") # Stage 2 Options -set(BOOTSTRAP_LLVM_ENABLE_PROJECTS "clang" CACHE STRING "") +set(STAGE2_PROJECTS "clang") +if (LLVM_RELEASE_ENABLE_LTO) + list(APPEND STAGE2_PROJECTS "lld") +endif() +set(BOOTSTRAP_LLVM_ENABLE_PROJECTS ${STAGE2_PROJECTS} CACHE STRING "") set(BOOTSTRAP_LLVM_TARGETS_TO_BUILD Native CACHE STRING "") # Stage 3 Options set(BOOTSTRAP_BOOTSTRAP_LLVM_ENABLE_RUNTIMES "compiler-rt;libcxx;libcxxabi;libunwind" CACHE STRING "") set(BOOTSTRAP_BOOTSTRAP_LLVM_ENABLE_PROJECTS "clang;lld;lldb;clang-tools-extra;bolt;polly;mlir;flang" CACHE STRING "") +set(BOOTSTRAP_BOOTSTRAP_LLVM_ENABLE_LTO ${LLVM_RELEASE_ENABLE_LTO} CACHE STRING "") +if (LLVM_RELEASE_ENABLE_LTO) + set(BOOTSTRAP_BOOTSTRAP_LLVM_ENABLE_LLD ON CACHE BOOL "") +endif() diff --git a/clang/docs/ClangFormat.rst b/clang/docs/ClangFormat.rst index 8d4017b29fb8eeb5d76149e7241f31cdad7ed1e1..819d9ee9f9cde1cba0cad142364dab42c3f276c2 100644 --- a/clang/docs/ClangFormat.rst +++ b/clang/docs/ClangFormat.rst @@ -131,6 +131,9 @@ An easy way to create the ``.clang-format`` file is: Available style options are described in :doc:`ClangFormatStyleOptions`. +.clang-format-ignore +==================== + You can create ``.clang-format-ignore`` files to make ``clang-format`` ignore certain files. A ``.clang-format-ignore`` file consists of patterns of file path names. It has the following format: @@ -141,7 +144,8 @@ names. It has the following format: * A non-comment line is a single pattern. * The slash (``/``) is used as the directory separator. * A pattern is relative to the directory of the ``.clang-format-ignore`` file - (or the root directory if the pattern starts with a slash). + (or the root directory if the pattern starts with a slash). Patterns + containing drive names (e.g. ``C:``) are not supported. * Patterns follow the rules specified in `POSIX 2.13.1, 2.13.2, and Rule 1 of 2.13.3 `_. diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst index 3d42571e82d8a07b37f084b2d6c66aeb33761a90..ac9a0b70ed5daa434be57d671c98aac03bab5248 100644 --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -392,6 +392,23 @@ the configuration (without a prefix: ``Auto``). a &= 2; bbb = 2; + * ``bool AlignFunctionPointers`` Only for ``AlignConsecutiveDeclarations``. Whether function pointers are + aligned. + + .. code-block:: c++ + + true: + unsigned i; + int &r; + int *p; + int (*f)(); + + false: + unsigned i; + int &r; + int *p; + int (*f)(); + * ``bool PadOperators`` Only for ``AlignConsecutiveAssignments``. Whether short assignment operators are left-padded to the same length as long ones in order to put all assignment operators to the right of the left hand side. @@ -517,6 +534,23 @@ the configuration (without a prefix: ``Auto``). a &= 2; bbb = 2; + * ``bool AlignFunctionPointers`` Only for ``AlignConsecutiveDeclarations``. Whether function pointers are + aligned. + + .. code-block:: c++ + + true: + unsigned i; + int &r; + int *p; + int (*f)(); + + false: + unsigned i; + int &r; + int *p; + int (*f)(); + * ``bool PadOperators`` Only for ``AlignConsecutiveAssignments``. Whether short assignment operators are left-padded to the same length as long ones in order to put all assignment operators to the right of the left hand side. @@ -642,6 +676,23 @@ the configuration (without a prefix: ``Auto``). a &= 2; bbb = 2; + * ``bool AlignFunctionPointers`` Only for ``AlignConsecutiveDeclarations``. Whether function pointers are + aligned. + + .. code-block:: c++ + + true: + unsigned i; + int &r; + int *p; + int (*f)(); + + false: + unsigned i; + int &r; + int *p; + int (*f)(); + * ``bool PadOperators`` Only for ``AlignConsecutiveAssignments``. Whether short assignment operators are left-padded to the same length as long ones in order to put all assignment operators to the right of the left hand side. @@ -768,6 +819,23 @@ the configuration (without a prefix: ``Auto``). a &= 2; bbb = 2; + * ``bool AlignFunctionPointers`` Only for ``AlignConsecutiveDeclarations``. Whether function pointers are + aligned. + + .. code-block:: c++ + + true: + unsigned i; + int &r; + int *p; + int (*f)(); + + false: + unsigned i; + int &r; + int *p; + int (*f)(); + * ``bool PadOperators`` Only for ``AlignConsecutiveAssignments``. Whether short assignment operators are left-padded to the same length as long ones in order to put all assignment operators to the right of the left hand side. diff --git a/clang/docs/HLSL/FunctionCalls.rst b/clang/docs/HLSL/FunctionCalls.rst new file mode 100644 index 0000000000000000000000000000000000000000..7317de2163f8975b3d9d283a55aa8d4d9ba2ac55 --- /dev/null +++ b/clang/docs/HLSL/FunctionCalls.rst @@ -0,0 +1,321 @@ +=================== +HLSL Function Calls +=================== + +.. contents:: + :local: + +Introduction +============ + +This document describes the design and implementation of HLSL's function call +semantics in Clang. This includes details related to argument conversion and +parameter lifetimes. + +This document does not seek to serve as official documentation for HLSL's +call semantics, but does provide an overview to assist a reader. The +authoritative documentation for HLSL's language semantics is the `draft language +specification `_. + +Argument Semantics +================== + +In HLSL, all function arguments are passed by value in and out of functions. +HLSL has 3 keywords which denote the parameter semantics (``in``, ``out`` and +``inout``). In a function declaration a parameter may be annotated any of the +following ways: + +#. - denotes input +#. ``in`` - denotes input +#. ``out`` - denotes output +#. ``in out`` - denotes input and output +#. ``out in`` - denotes input and output +#. ``inout`` - denotes input and output + +Parameters that are exclusively input behave like C/C++ parameters that are +passed by value. + +For parameters that are output (or input and output), a temporary value is +created in the caller. The temporary value is then passed by-address. For +output-only parameters, the temporary is uninitialized when passed (if the +parameter is not explicitly initialized inside the function an undefined value +is stored back to the argument expression). For parameters that are both input +and output, the temporary is initialized from the lvalue argument expression +through implicit or explicit casting from the lvalue argument type to the +parameter type. + +On return of the function, the values of any parameter temporaries are written +back to the argument expression through an inverted conversion sequence (if an +``out`` parameter was not initialized in the function, the uninitialized value +may be written back). + +Parameters of constant-sized array type are also passed with value semantics. +This requires input parameters of arrays to construct temporaries and the +temporaries go through array-to-pointer decay when initializing parameters. + +Implementations are allowed to avoid unnecessary temporaries, and HLSL's strict +no-alias rules can enable some trivial optimizations. + +Array Temporaries +----------------- + +Given the following example: + +.. code-block:: c++ + + void fn(float a[4]) { + a[0] = a[1] + a[2] + a[3]; + } + + float4 main() : SV_Target { + float arr[4] = {1, 1, 1, 1}; + fn(arr); + return float4(arr[0], arr[1], arr[2], arr[3]); + } + +In C or C++, the array parameter decays to a pointer, so after the call to +``fn``, the value of ``arr[0]`` is ``3``. In HLSL, the array is passed by value, +so modifications inside ``fn`` do not propagate out. + +.. note:: + + DXC may pass unsized arrays directly as decayed pointers, which is an + unfortunate behavior divergence. + +Out Parameter Temporaries +------------------------- + +.. code-block:: c++ + + void Init(inout int X, inout int Y) { + Y = 2; + X = 1; + } + + void main() { + int V; + Init(V, V); // MSVC (or clang-cl) V == 2, Clang V == 1 + } + +In the above example the ``Init`` function's behavior depends on the C++ +implementation. C++ does not define the order in which parameters are +initialized or destroyed. In MSVC and Clang's MSVC compatibility mode, arguments +are emitted right-to-left and destroyed left-to-right. This means that the +parameter initialization and destruction occurs in the order: {``Y``, ``X``, +``~X``, ``~Y``}. This causes the write-back of the value of ``Y`` to occur last, +so the resulting value of ``V`` is ``2``. In the Itanium C++ ABI, the parameter +ordering is reversed, so the initialization and destruction occurs in the order: +{``X``, ``Y``, ``~Y``, ``X``}. This causes the write-back of the value ``X`` to +occur last, resulting in the value of ``V`` being set to ``1``. + +.. code-block:: c++ + + void Trunc(inout int3 V) { } + + + void main() { + float3 F = {1.5, 2.6, 3.3}; + Trunc(F); // F == {1.0, 2.0, 3.0} + } + +In the above example, the argument expression ``F`` undergoes element-wise +conversion from a float vector to an integer vector to create a temporary +``int3``. On expiration the temporary undergoes elementwise conversion back to +the floating point vector type ``float3``. This results in an implicit +element-wise conversion of the vector even if the value is unused in the +function (effectively truncating the floating point values). + + +.. code-block:: c++ + + void UB(out int X) {} + + void main() { + int X = 7; + UB(X); // X is undefined! + } + +In this example an initialized value is passed to an ``out`` parameter. +Parameters marked ``out`` are not initialized by the argument expression or +implicitly by the function. They must be explicitly initialized. In this case +the argument is not initialized in the function so the temporary is still +uninitialized when it is copied back to the argument expression. This is +undefined behavior in HLSL, and any use of the argument after the call is a use +of an undefined value which may be illegal in the target (DXIL programs with +used or potentially used ``undef`` or ``poison`` values fail validation). + +Clang Implementation +==================== + +.. note:: + + The implementation described here is a proposal. It has not yet been fully + implemented, so the current state of Clang's sources may not reflect this + design. A prototype implementation was built on DXC which is Clang-3.7 based. + The prototype can be found + `here `_. A lot + of the changes in the prototype implementation are restoring Clang-3.7 code + that was previously modified to its original state. + +The implementation in clang depends on two new AST nodes and minor extensions to +Clang's existing support for Objective-C write-back arguments. The goal of this +design is to capture the semantic details of HLSL function calls in the AST, and +minimize the amount of magic that needs to occur during IR generation. + +The two new AST nodes are ``HLSLArrayTemporaryExpr`` and ``HLSLOutParamExpr``, +which respectively represent the temporaries used for passing arrays by value +and the temporaries created for function outputs. + +Array Temporaries +----------------- + +The ``HLSLArrayTemporaryExpr`` represents temporary values for input +constant-sized array arguments. This applies for all constant-sized array +arguments regardless of whether or not the parameter is constant-sized or +unsized. + +.. code-block:: c++ + + void SizedArray(float a[4]); + void UnsizedArray(float a[]); + + void main() { + float arr[4] = {1, 1, 1, 1}; + SizedArray(arr); + UnsizedArray(arr); + } + +In the example above, the following AST is generated for the call to +``SizedArray``: + +.. code-block:: text + + CallExpr 'void' + |-ImplicitCastExpr 'void (*)(float [4])' + | `-DeclRefExpr 'void (float [4])' lvalue Function 'SizedArray' 'void (float [4])' + `-HLSLArrayTemporaryExpr 'float [4]' + `-DeclRefExpr 'float [4]' lvalue Var 'arr' 'float [4]' + +In the example above, the following AST is generated for the call to +``UnsizedArray``: + +.. code-block:: text + + CallExpr 'void' + |-ImplicitCastExpr 'void (*)(float [])' + | `-DeclRefExpr 'void (float [])' lvalue Function 'UnsizedArray' 'void (float [])' + `-HLSLArrayTemporaryExpr 'float [4]' + `-DeclRefExpr 'float [4]' lvalue Var 'arr' 'float [4]' + +In both of these cases the argument expression is of known array size so we can +initialize an appropriately sized temporary. + +It is illegal in HLSL to convert an unsized array to a sized array: + +.. code-block:: c++ + + void SizedArray(float a[4]); + void UnsizedArray(float a[]) { + SizedArray(a); // Cannot convert float[] to float[4] + } + +When converting a sized array to an unsized array, an array temporary can also +be inserted. Given the following code: + +.. code-block:: c++ + + void UnsizedArray(float a[]); + void SizedArray(float a[4]) { + UnsizedArray(a); + } + +An expected AST should be something like: + +.. code-block:: text + + CallExpr 'void' + |-ImplicitCastExpr 'void (*)(float [])' + | `-DeclRefExpr 'void (float [])' lvalue Function 'UnsizedArray' 'void (float [])' + `-HLSLArrayTemporaryExpr 'float [4]' + `-DeclRefExpr 'float [4]' lvalue Var 'arr' 'float [4]' + +Out Parameter Temporaries +------------------------- + +Output parameters are defined in HLSL as *casting expiring values* (cx-values), +which is a term made up for HLSL. A cx-value is a temporary value which may be +the result of a cast, and stores its value back to an lvalue when the value +expires. + +To represent this concept in Clang we introduce a new ``HLSLOutParamExpr``. An +``HLSLOutParamExpr`` has two forms, one with a single sub-expression and one +with two sub-expressions. + +The single sub-expression form is used when the argument expression and the +function parameter are the same type, so no cast is required. As in this +example: + +.. code-block:: c++ + + void Init(inout int X) { + X = 1; + } + + void main() { + int V; + Init(V); + } + +The expected AST formulation for this code would be something like: + +.. code-block:: text + + CallExpr 'void' + |-ImplicitCastExpr 'void (*)(int &)' + | `-DeclRefExpr 'void (int &)' lvalue Function 'Init' 'void (int &)' + |-HLSLOutParamExpr 'int' lvalue inout + `-DeclRefExpr 'int' lvalue Var 'V' 'int' + +The ``HLSLOutParamExpr`` captures that the value is ``inout`` vs ``out`` to +denote whether or not the temporary is initialized from the sub-expression. If +no casting is required the sub-expression denotes the lvalue expression that the +cx-value will be copied to when the value expires. + +The two sub-expression form of the AST node is required when the argument type +is not the same as the parameter type. Given this example: + +.. code-block:: c++ + + void Trunc(inout int3 V) { } + + + void main() { + float3 F = {1.5, 2.6, 3.3}; + Trunc(F); + } + +For this case the ``HLSLOutParamExpr`` will have sub-expressions to record both +casting expression sequences for the initialization and write back: + +.. code-block:: text + + -CallExpr 'void' + |-ImplicitCastExpr 'void (*)(int3 &)' + | `-DeclRefExpr 'void (int3 &)' lvalue Function 'inc_i32' 'void (int3 &)' + `-HLSLOutParamExpr 'int3' lvalue inout + |-ImplicitCastExpr 'float3' + | `-ImplicitCastExpr 'int3' + | `-OpaqueValueExpr 'int3' lvalue + `-ImplicitCastExpr 'int3' + `-ImplicitCastExpr 'float3' + `-DeclRefExpr 'float3' lvalue 'F' 'float3' + +In this formation the write-back casts are captured as the first sub-expression +and they cast from an ``OpaqueValueExpr``. In IR generation we can use the +``OpaqueValueExpr`` as a placeholder for the ``HLSLOutParamExpr``'s temporary +value on function return. + +In code generation this can be implemented with some targeted extensions to the +Objective-C write-back support. Specifically extending CGCall.cpp's +``EmitWriteback`` function to support casting expressions and emission of +aggregate lvalues. diff --git a/clang/docs/HLSL/HLSLDocs.rst b/clang/docs/HLSL/HLSLDocs.rst index a02dd2e8a96261b7be013241542ea1244cb61848..1f232129548d0b44b19d8ad5500ab48fdf3eafb4 100644 --- a/clang/docs/HLSL/HLSLDocs.rst +++ b/clang/docs/HLSL/HLSLDocs.rst @@ -14,3 +14,4 @@ HLSL Design and Implementation HLSLIRReference ResourceTypes EntryFunctions + FunctionCalls diff --git a/clang/docs/InternalsManual.rst b/clang/docs/InternalsManual.rst index 05fadf5a034464364191bcd09f8f82021ae71287..b3e2b870ae5f9aad96983e3f6d678c999f7f3989 100644 --- a/clang/docs/InternalsManual.rst +++ b/clang/docs/InternalsManual.rst @@ -931,7 +931,7 @@ the option appears on the command line, the argument value is simply copied. .. code-block:: text def isysroot : JoinedOrSeparate<["-"], "isysroot">, - Visibility<[ClangOption, CC1Option]>, + Visibility<[ClangOption, CC1Option, FlangOption]>, MarshallingInfoString, [{"/"}]>; **List of Strings** @@ -3364,7 +3364,7 @@ Multiple occurrences accumulate prefixes. For example, Specifying Diagnostics ^^^^^^^^^^^^^^^^^^^^^^ -Indicating that a line expects an error or a warning is simple. Put a comment +Indicating that a line expects an error or a warning is easy. Put a comment on the line that has the diagnostic, use ``expected-{error,warning,remark,note}`` to tag if it's an expected error, warning, remark, or note (respectively), and place the expected text between @@ -3373,6 +3373,9 @@ enough to ensure that the correct diagnostic was emitted. (Note: full text should be included in test cases unless there is a compelling reason to use truncated text instead.) +For a full description of the matching behavior, including more complex +matching scenarios, see :ref:`matching ` below. + Here's an example of the most commonly used way to specify expected diagnostics: @@ -3458,8 +3461,33 @@ A range can also be specified by ``-``. For example: In this example, the diagnostic may appear only once, if at all. +.. _DiagnosticMatching: + +Matching Modes +~~~~~~~~~~~~~~ + +The default matching mode is simple string, which looks for the expected text +that appears between the first `{{` and `}}` pair of the comment. The string is +interpreted just as-is, with one exception: the sequence `\n` is converted to a +single newline character. This mode matches the emitted diagnostic when the +text appears as a substring at any position of the emitted message. + +To enable matching against desired strings that contain `}}` or `{{`, the +string-mode parser accepts opening delimiters of more than two curly braces, +like `{{{`. It then looks for a closing delimiter of equal "width" (i.e `}}}`). +For example: + +.. code-block:: c++ + + // expected-note {{{evaluates to '{{2, 3, 4}} == {0, 3, 4}'}}} + +The intent is to allow the delimeter to be wider than the longest `{` or `}` +brace sequence in the content, so that if your expected text contains `{{{` +(three braces) it may be delimited with `{{{{` (four braces), and so on. + Regex matching mode may be selected by appending ``-re`` to the diagnostic type -and including regexes wrapped in double curly braces in the directive, such as: +and including regexes wrapped in double curly braces (`{{` and `}}`) in the +directive, such as: .. code-block:: text @@ -3471,6 +3499,8 @@ Examples matching error: "variable has incomplete type 'struct s'" // expected-error {{variable has incomplete type 'struct s'}} // expected-error {{variable has incomplete type}} + // expected-error {{{variable has incomplete type}}} + // expected-error {{{{variable has incomplete type}}}} // expected-error-re {{variable has type 'struct {{.}}'}} // expected-error-re {{variable has type 'struct {{.*}}'}} diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst index 23a7f4f5d5b926aadd2752d4c808ec59b5fbf401..c1420079f75118d688a043c27c0296a3f103a935 100644 --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -829,6 +829,7 @@ to ``float``; see below for more information on this emulation. see below. * ``_Float16`` is supported on the following targets: + * 32-bit ARM (natively on some architecture versions) * 64-bit ARM (AArch64) (natively on ARMv8.2a and above) * AMDGPU (natively) @@ -837,6 +838,7 @@ to ``float``; see below for more information on this emulation. * RISC-V (natively if Zfh or Zhinx is available) * ``__bf16`` is supported on the following targets (currently never natively): + * 32-bit ARM * 64-bit ARM (AArch64) * RISC-V diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index c9b577bd549b1e27dedf71ffcde422bb9463a42c..3cbce1be15943761b8a2ac723331d293d7624225 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -37,6 +37,35 @@ These changes are ones which we think may surprise users when upgrading to Clang |release| because of the opportunity they pose for disruption to existing code bases. +- Fix a bug in reversed argument for templated operators. + This breaks code in C++20 which was previously accepted in C++17. + Clang did not properly diagnose such casese in C++20 before this change. Eg: + + .. code-block:: cpp + + struct P {}; + template bool operator==(const P&, const S&); + + struct A : public P {}; + struct B : public P {}; + + // This equality is now ambiguous in C++20. + bool ambiguous(A a, B b) { return a == b; } + + template bool operator!=(const P&, const S&); + // Ok. Found a matching operator!=. + bool fine(A a, B b) { return a == b; } + + To reduce such widespread breakages, as an extension, Clang accepts this code + with an existing warning ``-Wambiguous-reversed-operator`` warning. + Fixes `GH `_. + +- The CMake variable ``GCC_INSTALL_PREFIX`` (which sets the default + ``--gcc-toolchain=``) is deprecated and will be removed. Specify + ``--gcc-install-dir=`` or ``--gcc-triple=`` in a `configuration file + ` as a + replacement. + (`#77537 `_) C/C++ Language Potentially Breaking Changes ------------------------------------------- @@ -68,6 +97,10 @@ C/C++ Language Potentially Breaking Changes outlined in "The Equality Operator You Are Looking For" (`P2468 `_). Fixes (`#68901: `_). +- Remove the hardcoded path to the imported modules for C++20 named modules. Now we + require all the dependent modules to specified from the command line. + See (`#62707: `_). + C++ Specific Potentially Breaking Changes ----------------------------------------- - The name mangling rules for function templates has been changed to take into @@ -202,6 +235,11 @@ C Language Changes - Enums will now be represented in TBAA metadata using their actual underlying integer type. Previously they were treated as chars, which meant they could alias with all other types. +- Clang now supports the C-only attribute ``counted_by``. When applied to a + struct's flexible array member, it points to the struct field that holds the + number of elements in the flexible array member. This information can improve + the results of the array bound sanitizer and the + ``__builtin_dynamic_object_size`` builtin. C23 Feature Support ^^^^^^^^^^^^^^^^^^^ @@ -520,6 +558,8 @@ Improvements to Clang's diagnostics - Clang now diagnoses narrowing conversions involving const references. (`#63151: `_). - Clang now diagnoses unexpanded packs within the template argument lists of function template specializations. +- Clang now diagnoses attempts to bind a bitfield to an NTTP of a reference type as erroneous + converted constant expression and not as a reference to subobject. Improvements to Clang's time-trace @@ -610,7 +650,8 @@ Bug Fixes in This Version of template classes. Fixes (`#68543 `_, `#42496 `_, - `#77071 `_) + `#77071 `_, + `#77411 `_) - Fixed an issue when a shift count larger than ``__INT64_MAX__``, in a right shift operation, could result in missing warnings about ``shift count >= width of type`` or internal compiler error. @@ -696,7 +737,22 @@ Bug Fixes in This Version - Clang now accepts recursive non-dependent calls to functions with deduced return type. Fixes (`#71015 `_) - +- Fix assertion failure when initializing union containing struct with + flexible array member using empty initializer list. + Fixes (`#77085 `_) +- Fix assertion crash due to failed scope restoring caused by too-early VarDecl + invalidation by invalid initializer Expr. + Fixes (`#30908 `_) +- Clang now emits correct source location for code-coverage regions in `if constexpr` + and `if consteval` branches. + Fixes (`#54419 `_) +- Fix assertion failure when declaring a template friend function with + a constrained parameter in a template class that declares a class method + or lambda at different depth. + Fixes (`#75426 `_) +- Fix an issue where clang cannot find conversion function with template + parameter when instantiation of template class. + Fixes (`#77583 `_) Bug Fixes to Compiler Builtins ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -875,6 +931,9 @@ Bug Fixes to AST Handling - Fixed a bug where RecursiveASTVisitor fails to visit the initializer of a bitfield. `Issue 64916 `_ +- Fixed a bug where range-loop-analysis checks for trivial copyability, + rather than trivial copy-constructibility + `Issue 47355 `_ - Fixed a bug where Template Instantiation failed to handle Lambda Expressions with certain types of Attributes. (`#76521 `_) @@ -933,6 +992,14 @@ X86 Support - Support ISA of ``AVX10.1``. - ``-march=pantherlake`` and ``-march=clearwaterforest`` are now supported. - Added ABI handling for ``__float128`` to match with GCC. +- Emit warnings for options to enable knl/knm specific ISAs: AVX512PF, AVX512ER + and PREFETCHWT1. From next version (LLVM 19), these ISAs' intrinsic supports + will be deprecated: + * intrinsic series of *_exp2a23_* + * intrinsic series of *_rsqrt28_* + * intrinsic series of *_rcp28_* + * intrinsic series of *_prefetch_i[3|6][2|4]gather_* + * intrinsic series of *_prefetch_i[3|6][2|4]scatter_* Arm and AArch64 Support ^^^^^^^^^^^^^^^^^^^^^^^ @@ -1065,6 +1132,7 @@ clang-format - Add ``ObjCPropertyAttributeOrder`` which can be used to sort ObjC property attributes (like ``nonatomic, strong, nullable``). - Add ``.clang-format-ignore`` files. +- Add ``AlignFunctionPointers`` sub-option for ``AlignConsecutiveDeclarations``. libclang -------- @@ -1150,9 +1218,10 @@ Improvements ^^^^^^^^^^^^ - Improved the ``unix.StdCLibraryFunctions`` checker by modeling more - functions like ``send``, ``recv``, ``readlink``, ``fflush``, ``mkdtemp`` and - ``errno`` behavior. + functions like ``send``, ``recv``, ``readlink``, ``fflush``, ``mkdtemp``, + ``getcwd`` and ``errno`` behavior. (`52ac71f92d38 `_, + `#77040 `_, `#76671 `_, `#71373 `_, `#76557 `_, @@ -1181,8 +1250,9 @@ Improvements (`c3a87ddad62a `_, `0954dc3fb921 `_) -- Improved the ``alpha.unix.Stream`` checker by modeling more functions like, - ``fflush``, ``fputs``, ``fgetc``, ``fputc``, ``fopen``, ``fdopen``, ``fgets``, ``tmpfile``. +- Improved the ``alpha.unix.Stream`` checker by modeling more functions + ``fputs``, ``fputc``, ``fgets``, ``fgetc``, ``fdopen``, ``ungetc``, ``fflush`` + and no not recognize alternative ``fopen`` and ``tmpfile`` implementations. (`#76776 `_, `#74296 `_, `#73335 `_, @@ -1190,7 +1260,8 @@ Improvements `#71518 `_, `#72016 `_, `#70540 `_, - `#73638 `_) + `#73638 `_, + `#77331 `_) - The ``alpha.security.taint.TaintPropagation`` checker no longer propagates taint on ``strlen`` and ``strnlen`` calls, unless these are marked diff --git a/clang/docs/StandardCPlusPlusModules.rst b/clang/docs/StandardCPlusPlusModules.rst index 49704575740303cb128c8907ee9aa03bdb731eed..22d506f0da2b108828039093a429378fbe2b1898 100644 --- a/clang/docs/StandardCPlusPlusModules.rst +++ b/clang/docs/StandardCPlusPlusModules.rst @@ -143,7 +143,7 @@ Then we type: .. code-block:: console $ clang++ -std=c++20 Hello.cppm --precompile -o Hello.pcm - $ clang++ -std=c++20 use.cpp -fprebuilt-module-path=. Hello.pcm -o Hello.out + $ clang++ -std=c++20 use.cpp -fmodule-file=Hello=Hello.pcm Hello.pcm -o Hello.out $ ./Hello.out Hello World! @@ -200,15 +200,15 @@ Then we are able to compile the example by the following command: $ clang++ -std=c++20 interface_part.cppm --precompile -o M-interface_part.pcm $ clang++ -std=c++20 impl_part.cppm --precompile -fprebuilt-module-path=. -o M-impl_part.pcm $ clang++ -std=c++20 M.cppm --precompile -fprebuilt-module-path=. -o M.pcm - $ clang++ -std=c++20 Impl.cpp -fmodule-file=M=M.pcm -c -o Impl.o + $ clang++ -std=c++20 Impl.cpp -fprebuilt-module-path=. -c -o Impl.o # Compiling the user $ clang++ -std=c++20 User.cpp -fprebuilt-module-path=. -c -o User.o # Compiling the module and linking it together - $ clang++ -std=c++20 M-interface_part.pcm -c -o M-interface_part.o - $ clang++ -std=c++20 M-impl_part.pcm -c -o M-impl_part.o - $ clang++ -std=c++20 M.pcm -c -o M.o + $ clang++ -std=c++20 M-interface_part.pcm -fprebuilt-module-path=. -c -o M-interface_part.o + $ clang++ -std=c++20 M-impl_part.pcm -fprebuilt-module-path=. -c -o M-impl_part.o + $ clang++ -std=c++20 M.pcm -fprebuilt-module-path=. -c -o M.o $ clang++ User.o M-interface_part.o M-impl_part.o M.o Impl.o -o a.out We explain the options in the following sections. @@ -218,7 +218,6 @@ How to enable standard C++ modules Currently, standard C++ modules are enabled automatically if the language standard is ``-std=c++20`` or newer. -The ``-fmodules-ts`` option is deprecated and is planned to be removed. How to produce a BMI ~~~~~~~~~~~~~~~~~~~~ diff --git a/clang/include/clang/AST/DeclBase.h b/clang/include/clang/AST/DeclBase.h index 10dcbdb262d84e40c58b72a25a33e2ef5cf1ab0b..5b1038582bc674700132386ff9687ef30ad86592 100644 --- a/clang/include/clang/AST/DeclBase.h +++ b/clang/include/clang/AST/DeclBase.h @@ -19,6 +19,7 @@ #include "clang/AST/SelectorLocationsKind.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/LLVM.h" +#include "clang/Basic/LangOptions.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/Specifiers.h" #include "llvm/ADT/ArrayRef.h" @@ -488,6 +489,15 @@ public: // Return true if this is a FileContext Decl. bool isFileContextDecl() const; + /// Whether it resembles a flexible array member. This is a static member + /// because we want to be able to call it with a nullptr. That allows us to + /// perform non-Decl specific checks based on the object's type and strict + /// flex array level. + static bool isFlexibleArrayMemberLike( + ASTContext &Context, const Decl *D, QualType Ty, + LangOptions::StrictFlexArraysLevelKind StrictFlexArraysLevel, + bool IgnoreTemplateOrMacroSubstitution); + ASTContext &getASTContext() const LLVM_READONLY; /// Helper to get the language options from the ASTContext. diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index 984a4d8bab5e77262a3fb714604e55c46320be06..648f5f946408700081c49ef546e7c3dc2bc39b09 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -1425,6 +1425,9 @@ public: /// (C++11 [class]p6). bool isTriviallyCopyable() const; + /// Determine whether this class is considered trivially copyable per + bool isTriviallyCopyConstructible() const; + /// Determine whether this class is considered trivial. /// /// C++11 [class]p6: diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h index da7b37ce0e1211f87bb3639c0fb16708d2eeacfd..e1fde24e647789aee4bf07e7610569e6ce802d18 100644 --- a/clang/include/clang/AST/Stmt.h +++ b/clang/include/clang/AST/Stmt.h @@ -1631,8 +1631,10 @@ public: SourceLocation RB); // Build an empty compound statement with a location. - explicit CompoundStmt(SourceLocation Loc) - : Stmt(CompoundStmtClass), LBraceLoc(Loc), RBraceLoc(Loc) { + explicit CompoundStmt(SourceLocation Loc) : CompoundStmt(Loc, Loc) {} + + CompoundStmt(SourceLocation Loc, SourceLocation EndLoc) + : Stmt(CompoundStmtClass), LBraceLoc(Loc), RBraceLoc(EndLoc) { CompoundStmtBits.NumStmts = 0; CompoundStmtBits.HasFPFeatures = 0; } diff --git a/clang/include/clang/AST/TextNodeDumper.h b/clang/include/clang/AST/TextNodeDumper.h index 2f4ed082a0c7ad4eb8a193d2ce616920d6bfba42..732749ad305e15d1c519cff221cfb0cca4e24667 100644 --- a/clang/include/clang/AST/TextNodeDumper.h +++ b/clang/include/clang/AST/TextNodeDumper.h @@ -252,6 +252,8 @@ public: void VisitGotoStmt(const GotoStmt *Node); void VisitCaseStmt(const CaseStmt *Node); void VisitReturnStmt(const ReturnStmt *Node); + void VisitCoawaitExpr(const CoawaitExpr *Node); + void VisitCoreturnStmt(const CoreturnStmt *Node); void VisitCompoundStmt(const CompoundStmt *Node); void VisitConstantExpr(const ConstantExpr *Node); void VisitCallExpr(const CallExpr *Node); diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index 9e9f896ebef7a67f4ef10c40556f5ca302cef1af..d4e5310fb3abc60af201307311a712ce34106107 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -917,6 +917,9 @@ public: /// Return true if this is a trivially copyable type (C++0x [basic.types]p9) bool isTriviallyCopyableType(const ASTContext &Context) const; + /// Return true if this is a trivially copyable type + bool isTriviallyCopyConstructibleType(const ASTContext &Context) const; + /// Return true if this is a trivially relocatable type. bool isTriviallyRelocatableType(const ASTContext &Context) const; diff --git a/clang/include/clang/Analysis/CFG.h b/clang/include/clang/Analysis/CFG.h index 67383bb316d3183b135c876d96e17fd87a13f5b9..9f776ca6cc260d39d147dec62e772026d95ae2b8 100644 --- a/clang/include/clang/Analysis/CFG.h +++ b/clang/include/clang/Analysis/CFG.h @@ -1215,7 +1215,9 @@ public: //===--------------------------------------------------------------------===// class BuildOptions { - std::bitset alwaysAddMask; + // Stmt::lastStmtConstant has the same value as the last Stmt kind, + // so make sure we add one to account for this! + std::bitset alwaysAddMask; public: using ForcedBlkExprs = llvm::DenseMap; diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index d5eabaad48896526a37f4523f834003aae251f03..a03b0e44e15f7d99cbedbf370efa5d3c00a1c54f 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -4372,3 +4372,21 @@ def CodeAlign: StmtAttr { static constexpr int MaximumAlignment = 4096; }]; } + +def CountedBy : InheritableAttr { + let Spellings = [Clang<"counted_by">]; + let Subjects = SubjectList<[Field]>; + let Args = [IdentifierArgument<"CountedByField">]; + let Documentation = [CountedByDocs]; + let LangOpts = [COnly]; + // FIXME: This is ugly. Let using a DeclArgument would be nice, but a Decl + // isn't yet available due to the fact that we're still parsing the + // structure. Maybe that code could be changed sometime in the future. + code AdditionalMembers = [{ + private: + SourceRange CountedByFieldLoc; + public: + SourceRange getCountedByFieldLoc() const { return CountedByFieldLoc; } + void setCountedByFieldLoc(SourceRange Loc) { CountedByFieldLoc = Loc; } + }]; +} diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index 5416a0cbdd0757b1592485d49ca00628f7344ad8..2e8d7752c9751e98443308ac10e24078f35a8770 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -7749,3 +7749,81 @@ but do not pass them to the underlying coroutine or pass them by value. .. _`CRT`: https://clang.llvm.org/docs/AttributeReference.html#coro-return-type }]; } + +def CountedByDocs : Documentation { + let Category = DocCatField; + let Content = [{ +Clang supports the ``counted_by`` attribute on the flexible array member of a +structure in C. The argument for the attribute is the name of a field member +holding the count of elements in the flexible array. This information can be +used to improve the results of the array bound sanitizer and the +``__builtin_dynamic_object_size`` builtin. The ``count`` field member must be +within the same non-anonymous, enclosing struct as the flexible array member. + +This example specifies that the flexible array member ``array`` has the number +of elements allocated for it in ``count``: + +.. code-block:: c + + struct bar; + + struct foo { + size_t count; + char other; + struct bar *array[] __attribute__((counted_by(count))); + }; + +This establishes a relationship between ``array`` and ``count``. Specifically, +``array`` must have at least ``count`` number of elements available. It's the +user's responsibility to ensure that this relationship is maintained through +changes to the structure. + +In the following example, the allocated array erroneously has fewer elements +than what's specified by ``p->count``. This would result in an out-of-bounds +access not being detected. + +.. code-block:: c + + #define SIZE_INCR 42 + + struct foo *p; + + void foo_alloc(size_t count) { + p = malloc(MAX(sizeof(struct foo), + offsetof(struct foo, array[0]) + count * sizeof(struct bar *))); + p->count = count + SIZE_INCR; + } + +The next example updates ``p->count``, but breaks the relationship requirement +that ``p->array`` must have at least ``p->count`` number of elements available: + +.. code-block:: c + + #define SIZE_INCR 42 + + struct foo *p; + + void foo_alloc(size_t count) { + p = malloc(MAX(sizeof(struct foo), + offsetof(struct foo, array[0]) + count * sizeof(struct bar *))); + p->count = count; + } + + void use_foo(int index, int val) { + p->count += SIZE_INCR + 1; /* 'count' is now larger than the number of elements of 'array'. */ + p->array[index] = val; /* The sanitizer can't properly check this access. */ + } + +In this example, an update to ``p->count`` maintains the relationship +requirement: + +.. code-block:: c + + void use_foo(int index, int val) { + if (p->count == 0) + return; + --p->count; + p->array[index] = val; + } + }]; +} diff --git a/clang/include/clang/Basic/DiagnosticCommonKinds.td b/clang/include/clang/Basic/DiagnosticCommonKinds.td index 65a33f61a6948ad532f3b428d99838f3906f4578..72952b08c04a490ab88a2a6e757d173e58fea3b5 100644 --- a/clang/include/clang/Basic/DiagnosticCommonKinds.td +++ b/clang/include/clang/Basic/DiagnosticCommonKinds.td @@ -349,6 +349,9 @@ def warn_invalid_feature_combination : Warning< def warn_target_unrecognized_env : Warning< "mismatch between architecture and environment in target triple '%0'; did you mean '%1'?">, InGroup; +def warn_knl_knm_isa_support_removed : Warning< + "KNL, KNM related Intel Xeon Phi CPU's specific ISA's supports will be removed in LLVM 19.">, + InGroup>; // Source manager def err_cannot_open_file : Error<"cannot open file '%0': %1">, DefaultFatal; diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td index 676f1a62b49dd0d0d5ca7f093374e07a44ef5838..8b5232a6df3958125d309a6a4abd58b0d775b944 100644 --- a/clang/include/clang/Basic/DiagnosticDriverKinds.td +++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -472,7 +472,7 @@ def warn_unsupported_branch_protection: Warning < def err_sls_hardening_arm_not_supported : Error< "-mharden-sls is only supported on armv7-a or later">; def warn_drv_large_data_threshold_invalid_code_model: Warning< - "'%0' only applies to medium code model">, + "'%0' only applies to medium and large code models">, InGroup; def note_drv_command_failed_diag_msg : Note< @@ -786,4 +786,7 @@ def warn_android_unversioned_fallback : Warning< " directories will not be used in Clang 19. Provide a versioned directory" " for the target version or lower instead.">, InGroup>; + +def err_drv_triple_version_invalid : Error< + "version '%0' in target triple '%1' is invalid">; } diff --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/clang/include/clang/Basic/DiagnosticFrontendKinds.td index 568000106a84dc75d003089b54383485f9163222..85ecfdf9de62d4403b730f6c5fb76303db89ad04 100644 --- a/clang/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/clang/include/clang/Basic/DiagnosticFrontendKinds.td @@ -167,7 +167,7 @@ def err_verify_no_such_marker : Error< def err_verify_missing_start : Error< "cannot find start ('{{') of expected %0">; def err_verify_missing_end : Error< - "cannot find end ('}}') of expected %0">; + "cannot find end ('%1') of expected %0">; def err_verify_invalid_content : Error< "invalid expected %0: %1">; def err_verify_missing_regex : Error< diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index d150e08d5f5ea8008b1da4516b5d17a87c0ceae8..1a79892e40030ae2dc98f368c52083a7dab5122a 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -2253,6 +2253,8 @@ def warn_cxx17_compat_aggregate_init_paren_list : Warning< def err_reference_bind_to_bitfield : Error< "%select{non-const|volatile}0 reference cannot bind to " "bit-field%select{| %1}2">; +def err_reference_bind_to_bitfield_in_cce : Error< + "reference cannot bind to bit-field in converted constant expression">; def err_reference_bind_to_vector_element : Error< "%select{non-const|volatile}0 reference cannot bind to vector element">; def err_reference_bind_to_matrix_element : Error< @@ -6160,23 +6162,19 @@ def err_illegal_initializer_type : Error<"illegal initializer type %0">; def ext_init_list_type_narrowing : ExtWarn< "type %0 cannot be narrowed to %1 in initializer list">, InGroup, DefaultError, SFINAEFailure; -// *_narrowing_const_reference diagnostics have the same messages, but are -// controlled by -Wc++11-narrowing-const-reference for narrowing involving a -// const reference. def ext_init_list_type_narrowing_const_reference : ExtWarn< - "type %0 cannot be narrowed to %1 in initializer list">, + ext_init_list_type_narrowing.Summary>, InGroup, DefaultError, SFINAEFailure; def ext_init_list_variable_narrowing : ExtWarn< "non-constant-expression cannot be narrowed from type %0 to %1 in " "initializer list">, InGroup, DefaultError, SFINAEFailure; def ext_init_list_variable_narrowing_const_reference : ExtWarn< - "non-constant-expression cannot be narrowed from type %0 to %1 in " - "initializer list">, InGroup, DefaultError, SFINAEFailure; + ext_init_list_variable_narrowing.Summary>, InGroup, DefaultError, SFINAEFailure; def ext_init_list_constant_narrowing : ExtWarn< "constant expression evaluates to %0 which cannot be narrowed to type %1">, InGroup, DefaultError, SFINAEFailure; def ext_init_list_constant_narrowing_const_reference : ExtWarn< - "constant expression evaluates to %0 which cannot be narrowed to type %1">, + ext_init_list_constant_narrowing.Summary>, InGroup, DefaultError, SFINAEFailure; def warn_init_list_type_narrowing : Warning< "type %0 cannot be narrowed to %1 in initializer list in C++11">, @@ -6443,6 +6441,19 @@ def warn_superclass_variable_sized_type_not_at_end : Warning< "field %0 can overwrite instance variable %1 with variable sized type %2" " in superclass %3">, InGroup; +def err_flexible_array_count_not_in_same_struct : Error< + "'counted_by' field %0 isn't within the same struct as the flexible array">; +def err_counted_by_attr_not_on_flexible_array_member : Error< + "'counted_by' only applies to C99 flexible array members">; +def err_counted_by_attr_refers_to_flexible_array : Error< + "'counted_by' cannot refer to the flexible array %0">; +def err_counted_by_must_be_in_structure : Error< + "field %0 in 'counted_by' not inside structure">; +def err_flexible_array_counted_by_attr_field_not_integer : Error< + "field %0 in 'counted_by' must be a non-boolean integer type">; +def note_flexible_array_counted_by_attr_field : Note< + "field %0 declared here">; + let CategoryName = "ARC Semantic Issue" in { // ARC-mode diagnostics. diff --git a/clang/include/clang/Basic/DiagnosticSerializationKinds.td b/clang/include/clang/Basic/DiagnosticSerializationKinds.td index 3cb2cd32cf6d09f48b4571fd07de0684ea12d90c..11c706ebf84b542a4467f52b9d2f9668c2e42629 100644 --- a/clang/include/clang/Basic/DiagnosticSerializationKinds.td +++ b/clang/include/clang/Basic/DiagnosticSerializationKinds.td @@ -129,10 +129,8 @@ def warn_module_system_bit_conflict : Warning< "as a non-system module; any difference in diagnostic options will be ignored">, InGroup; -def warn_reading_std_cxx_module_by_implicit_paths : Warning< - "it is deprecated to read module '%0' implicitly; it is going to be removed in clang 18; " - "consider to specify the dependencies explicitly">, - InGroup>; +def err_failed_to_find_module_file : Error< + "failed to find module file for module '%0'">; } // let CategoryName let CategoryName = "AST Serialization Issue" in { diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def index 21abc346cf17ac30e91d1d1a9e7518499b7452ec..0428b70c602062e6a3842e3e305a0d309194af1d 100644 --- a/clang/include/clang/Basic/LangOptions.def +++ b/clang/include/clang/Basic/LangOptions.def @@ -457,6 +457,7 @@ ENUM_LANGOPT(SignReturnAddressKey, SignReturnAddressKeyKind, 1, SignReturnAddres "Key used for return address signing") LANGOPT(BranchTargetEnforcement, 1, 0, "Branch-target enforcement enabled") LANGOPT(BranchProtectionPAuthLR, 1, 0, "Use PC as a diversifier using PAuthLR NOP instructions.") +LANGOPT(GuardedControlStack, 1, 0, "Guarded control stack enabled") LANGOPT(SpeculativeLoadHardening, 1, 0, "Speculative load hardening enabled") diff --git a/clang/include/clang/Basic/OpenACCKinds.h b/clang/include/clang/Basic/OpenACCKinds.h index 3eb0bf84208fddc3e0398d672a186432d563e8a7..e860893b933ca366a52965c5ec814cf89a888d62 100644 --- a/clang/include/clang/Basic/OpenACCKinds.h +++ b/clang/include/clang/Basic/OpenACCKinds.h @@ -93,6 +93,47 @@ enum class OpenACCClauseKind { /// 'default' clause, allowed on parallel, serial, kernel (and compound) /// constructs. Default, + /// 'if' clause, allowed on all the Compute Constructs, Data Constructs, + /// Executable Constructs, and Combined Constructs. + If, + /// 'self' clause, allowed on Compute and Combined Constructs, plus 'update'. + Self, + /// 'copy' clause, allowed on Compute and Combined Constructs, plus 'data' and + /// 'declare'. + Copy, + /// 'use_device' clause, allowed on 'host_data' construct. + UseDevice, + /// 'attach' clause, allowed on Compute and Combined constructs, plus 'data' + /// and 'enter data'. + Attach, + /// 'delete' clause, allowed on the 'exit data' construct. + Delete, + /// 'detach' clause, allowed on the 'exit data' construct. + Detach, + /// 'device' clause, allowed on the 'update' construct. + Device, + /// 'deviceptr' clause, allowed on Compute and Combined Constructs, plus + /// 'data' and 'declare'. + DevicePtr, + /// 'device_resident' clause, allowed on the 'declare' construct. + DeviceResident, + /// 'firstprivate' clause, allowed on 'parallel', 'serial', 'parallel loop', + /// and 'serial loop' constructs. + FirstPrivate, + /// 'host' clause, allowed on 'update' construct. + Host, + /// 'link' clause, allowed on 'declare' construct. + Link, + /// 'no_create' clause, allowed on allowed on Compute and Combined constructs, + /// plus 'data'. + NoCreate, + /// 'present' clause, allowed on Compute and Combined constructs, plus 'data' + /// and 'declare'. + Present, + /// 'private' clause, allowed on 'parallel', 'serial', 'loop', 'parallel + /// loop', and 'serial loop' constructs. + Private, + /// Represents an invalid clause, for the purposes of parsing. Invalid, }; diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h index ac3c324c6c29c482af7ab61db6ca23807f4d123b..3eb23ebdacf0edd6c796330f57877934dc544942 100644 --- a/clang/include/clang/Basic/TargetInfo.h +++ b/clang/include/clang/Basic/TargetInfo.h @@ -1373,6 +1373,7 @@ public: LangOptions::SignReturnAddressKeyKind::AKey; bool BranchTargetEnforcement = false; bool BranchProtectionPAuthLR = false; + bool GuardedControlStack = false; }; /// Determine if the Architecture in this TargetInfo supports branch diff --git a/clang/include/clang/Basic/arm_sve.td b/clang/include/clang/Basic/arm_sve.td index 7f80fb0386cc77a4cafcb88658a39478cf00024f..6de940b4da60334b79d83e9bfb7d35542f17b6cb 100644 --- a/clang/include/clang/Basic/arm_sve.td +++ b/clang/include/clang/Basic/arm_sve.td @@ -454,11 +454,11 @@ let TargetGuard = "sve,bf16" in { let TargetGuard = "sve2p1" in { // Contiguous truncating store from quadword (single vector). - def SVST1UWQ : MInst<"svst1uwq[_{d}]", "vPcd", "iUif", [IsStore], MemEltTyInt32, "aarch64_sve_st1uwq">; - def SVST1UWQ_VNUM : MInst<"svst1uwq_vnum[_{d}]", "vPcld", "iUif", [IsStore], MemEltTyInt32, "aarch64_sve_st1uwq">; + def SVST1UWQ : MInst<"svst1wq[_{d}]", "vPcd", "iUif", [IsStore], MemEltTyInt32, "aarch64_sve_st1wq">; + def SVST1UWQ_VNUM : MInst<"svst1wq_vnum[_{d}]", "vPcld", "iUif", [IsStore], MemEltTyInt32, "aarch64_sve_st1wq">; - def SVST1UDQ : MInst<"svst1udq[_{d}]", "vPcd", "lUld", [IsStore], MemEltTyInt64, "aarch64_sve_st1udq">; - def SVST1UDQ_VNUM : MInst<"svst1udq_vnum[_{d}]", "vPcld", "lUld", [IsStore], MemEltTyInt64, "aarch64_sve_st1udq">; + def SVST1UDQ : MInst<"svst1dq[_{d}]", "vPcd", "lUld", [IsStore], MemEltTyInt64, "aarch64_sve_st1dq">; + def SVST1UDQ_VNUM : MInst<"svst1dq_vnum[_{d}]", "vPcld", "lUld", [IsStore], MemEltTyInt64, "aarch64_sve_st1dq">; // Store one vector (vector base + scalar offset) def SVST1Q_SCATTER_U64BASE_OFFSET : MInst<"svst1q_scatter[_{2}base]_offset[_{d}]", "vPgld", "cUcsUsiUilUlfhdb", [IsScatterStore, IsByteIndexed], MemEltTyDefault, "aarch64_sve_st1q_scatter_scalar_offset">; @@ -2040,12 +2040,12 @@ let TargetGuard = "sve2p1|sme2" in { } let TargetGuard = "sve2p1" in { -def SVDOT_X2_S : SInst<"svdot[_{d}_{2}_{3}]", "ddhh", "i", MergeNone, "aarch64_sve_sdot_x2", [], []>; -def SVDOT_X2_U : SInst<"svdot[_{d}_{2}_{3}]", "ddhh", "Ui", MergeNone, "aarch64_sve_udot_x2", [], []>; -def SVDOT_X2_F : SInst<"svdot[_{d}_{2}_{3}]", "ddhh", "f", MergeNone, "aarch64_sve_fdot_x2", [], []>; -def SVDOT_LANE_X2_S : SInst<"svdot_lane[_{d}_{2}_{3}]", "ddhhi", "i", MergeNone, "aarch64_sve_sdot_lane_x2", [], [ImmCheck<3, ImmCheck0_3>]>; -def SVDOT_LANE_X2_U : SInst<"svdot_lane[_{d}_{2}_{3}]", "ddhhi", "Ui", MergeNone, "aarch64_sve_udot_lane_x2", [], [ImmCheck<3, ImmCheck0_3>]>; -def SVDOT_LANE_X2_F : SInst<"svdot_lane[_{d}_{2}_{3}]", "ddhhi", "f", MergeNone, "aarch64_sve_fdot_lane_x2", [], [ImmCheck<3, ImmCheck0_3>]>; +def SVDOT_X2_S : SInst<"svdot[_{d}_{2}]", "ddhh", "i", MergeNone, "aarch64_sve_sdot_x2", [], []>; +def SVDOT_X2_U : SInst<"svdot[_{d}_{2}]", "ddhh", "Ui", MergeNone, "aarch64_sve_udot_x2", [], []>; +def SVDOT_X2_F : SInst<"svdot[_{d}_{2}]", "ddhh", "f", MergeNone, "aarch64_sve_fdot_x2", [], []>; +def SVDOT_LANE_X2_S : SInst<"svdot_lane[_{d}_{2}]", "ddhhi", "i", MergeNone, "aarch64_sve_sdot_lane_x2", [], [ImmCheck<3, ImmCheck0_3>]>; +def SVDOT_LANE_X2_U : SInst<"svdot_lane[_{d}_{2}]", "ddhhi", "Ui", MergeNone, "aarch64_sve_udot_lane_x2", [], [ImmCheck<3, ImmCheck0_3>]>; +def SVDOT_LANE_X2_F : SInst<"svdot_lane[_{d}_{2}]", "ddhhi", "f", MergeNone, "aarch64_sve_fdot_lane_x2", [], [ImmCheck<3, ImmCheck0_3>]>; } let TargetGuard = "sve2p1|sme2" in { @@ -2208,7 +2208,7 @@ let TargetGuard = "sve2p1" in { def SVTBLQ : SInst<"svtblq[_{d}]", "ddu", "cUcsUsiUilUlbhfd", MergeNone, "aarch64_sve_tblq">; def SVTBXQ : SInst<"svtbxq[_{d}]", "dddu", "cUcsUsiUilUlbhfd", MergeNone, "aarch64_sve_tbxq">; // EXTQ - def EXTQ : SInst<"svextq_lane[_{d}]", "dddk", "cUcsUsiUilUlbhfd", MergeNone, "aarch64_sve_extq_lane", [], [ImmCheck<2, ImmCheck0_15>]>; + def EXTQ : SInst<"svextq[_{d}]", "dddk", "cUcsUsiUilUlbhfd", MergeNone, "aarch64_sve_extq", [], [ImmCheck<2, ImmCheck0_15>]>; // PMOV // Move to Pred multiclass PMOV_TO_PRED flags=[], ImmCheckType immCh > { @@ -2238,15 +2238,15 @@ let TargetGuard = "sme2" in { def SVCVT_F16_X2 : SInst<"svcvt_f16[_f32_x2]", "e2", "f", MergeNone, "aarch64_sve_fcvt_x2", [IsStreaming],[]>; def SVCVT_BF16_X2 : SInst<"svcvt_bf16[_f32_x2]", "$2", "f", MergeNone, "aarch64_sve_bfcvt_x2", [IsOverloadNone, IsStreaming],[]>; - def SVCVT_F32_U32_X2 : SInst<"svcvt_{d}[_u32_x2]", "2.d2.u", "f", MergeNone, "aarch64_sve_fcvtu_x2", [IsStreaming], []>; - def SVCVT_U32_F32_X2 : SInst<"svcvt_u32[_{d}_x2]", "2.u2.d", "f", MergeNone, "aarch64_sve_ucvtf_x2", [IsStreaming], []>; - def SVCVT_F32_S32_X2 : SInst<"svcvt_{d}[_s32_x2]", "2.d2.x", "f", MergeNone, "aarch64_sve_fcvts_x2", [IsStreaming], []>; - def SVCVT_S32_F32_X2 : SInst<"svcvt_s32[_{d}_x2]", "2.x2.d", "f", MergeNone, "aarch64_sve_scvtf_x2", [IsStreaming], []>; + def SVCVT_F32_U32_X2 : SInst<"svcvt_{d}[_u32_x2]", "2.d2.u", "f", MergeNone, "aarch64_sve_ucvtf_x2", [IsStreaming], []>; + def SVCVT_U32_F32_X2 : SInst<"svcvt_u32[_{d}_x2]", "2.u2.d", "f", MergeNone, "aarch64_sve_fcvtu_x2", [IsStreaming], []>; + def SVCVT_F32_S32_X2 : SInst<"svcvt_{d}[_s32_x2]", "2.d2.x", "f", MergeNone, "aarch64_sve_scvtf_x2", [IsStreaming], []>; + def SVCVT_S32_F32_X2 : SInst<"svcvt_s32[_{d}_x2]", "2.x2.d", "f", MergeNone, "aarch64_sve_fcvts_x2", [IsStreaming], []>; - def SVCVT_F32_U32_X4 : SInst<"svcvt_{d}[_u32_x4]", "4.d4.u", "f", MergeNone, "aarch64_sve_fcvtu_x4", [IsStreaming], []>; - def SVCVT_U32_F32_X4 : SInst<"svcvt_u32[_{d}_x4]", "4.u4.d", "f", MergeNone, "aarch64_sve_ucvtf_x4", [IsStreaming], []>; - def SVCVT_F32_S32_X4 : SInst<"svcvt_{d}[_s32_x4]", "4.d4.x", "f", MergeNone, "aarch64_sve_fcvts_x4", [IsStreaming], []>; - def SVCVT_S32_F32_X4 : SInst<"svcvt_s32[_{d}_x4]", "4.x4.d", "f", MergeNone, "aarch64_sve_scvtf_x4", [IsStreaming], []>; + def SVCVT_F32_U32_X4 : SInst<"svcvt_{d}[_u32_x4]", "4.d4.u", "f", MergeNone, "aarch64_sve_ucvtf_x4", [IsStreaming], []>; + def SVCVT_U32_F32_X4 : SInst<"svcvt_u32[_{d}_x4]", "4.u4.d", "f", MergeNone, "aarch64_sve_fcvtu_x4", [IsStreaming], []>; + def SVCVT_F32_S32_X4 : SInst<"svcvt_{d}[_s32_x4]", "4.d4.x", "f", MergeNone, "aarch64_sve_scvtf_x4", [IsStreaming], []>; + def SVCVT_S32_F32_X4 : SInst<"svcvt_s32[_{d}_x4]", "4.x4.d", "f", MergeNone, "aarch64_sve_fcvts_x4", [IsStreaming], []>; } // diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 6a5a7c58759e62f5877f3db1b99793df97be298e..bd897d5b6de31babb9db924fcab902cbacbed087 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -773,6 +773,8 @@ def gcc_install_dir_EQ : Joined<["--"], "gcc-install-dir=">, def gcc_toolchain : Joined<["--"], "gcc-toolchain=">, Flags<[NoXarchOption]>, HelpText<"Specify a directory where Clang can find 'include' and 'lib{,32,64}/gcc{,-cross}/$triple/$version'. " "Clang will use the GCC installation with the largest version">; +def gcc_triple_EQ : Joined<["--"], "gcc-triple=">, + HelpText<"Search for the GCC installation with the specified triple.">; def CC : Flag<["-"], "CC">, Visibility<[ClangOption, CC1Option]>, Group, HelpText<"Include comments from within macros in preprocessed output">, @@ -4265,7 +4267,7 @@ def iquote : JoinedOrSeparate<["-"], "iquote">, Group, Visibility<[ClangOption, CC1Option]>, HelpText<"Add directory to QUOTE include search path">, MetaVarName<"">; def isysroot : JoinedOrSeparate<["-"], "isysroot">, Group, - Visibility<[ClangOption, CC1Option]>, + Visibility<[ClangOption, CC1Option, FlangOption]>, HelpText<"Set the system root directory (usually /)">, MetaVarName<"">, MarshallingInfoString, [{"/"}]>; def isystem : JoinedOrSeparate<["-"], "isystem">, Group, @@ -4390,8 +4392,8 @@ def mcmodel_EQ : Joined<["-"], "mcmodel=">, Group, Visibility<[ClangOption, CC1Option]>, MarshallingInfoString, [{"default"}]>; def mlarge_data_threshold_EQ : Joined<["-"], "mlarge-data-threshold=">, Group, - Visibility<[ClangOption, CC1Option]>, - MarshallingInfoInt, "65535">; + Flags<[TargetSpecific]>, Visibility<[ClangOption, CC1Option]>, + MarshallingInfoInt, "0">; def mtls_size_EQ : Joined<["-"], "mtls-size=">, Group, Visibility<[ClangOption, CC1Option]>, HelpText<"Specify bit size of immediate TLS offsets (AArch64 ELF only): " @@ -4583,11 +4585,13 @@ let Flags = [TargetSpecific] in { def menable_experimental_extensions : Flag<["-"], "menable-experimental-extensions">, Group, HelpText<"Enable use of experimental RISC-V extensions.">; def mrvv_vector_bits_EQ : Joined<["-"], "mrvv-vector-bits=">, Group, - HelpText<"Specify the size in bits of an RVV vector register. Defaults to " - "the vector length agnostic value of \"scalable\". Accepts power of " - "2 values between 64 and 65536. Also accepts \"zvl\" " - "to use the value implied by -march/-mcpu. Value will be reflected " - "in __riscv_v_fixed_vlen preprocessor define (RISC-V only)">; + Visibility<[ClangOption, FlangOption]>, + HelpText<"Specify the size in bits of an RVV vector register">, + DocBrief<"Defaults to the vector length agnostic value of \"scalable\". " + "Accepts power of 2 values between 64 and 65536. Also accepts " + "\"zvl\" to use the value implied by -march/-mcpu. On Clang, value " + "will be reflected in __riscv_v_fixed_vlen preprocessor define " + "(RISC-V only)">; def munaligned_access : Flag<["-"], "munaligned-access">, Group, HelpText<"Allow memory accesses to be unaligned (AArch32/AArch64/LoongArch/RISC-V only)">; @@ -5195,12 +5199,12 @@ def nohipwrapperinc : Flag<["-"], "nohipwrapperinc">, Group, HelpText<"Do not include the default HIP wrapper headers and include paths">; def : Flag<["-"], "nocudainc">, Alias; def nogpulib : Flag<["-"], "nogpulib">, MarshallingInfoFlag>, - Visibility<[ClangOption, CC1Option]>, + Visibility<[ClangOption, CC1Option, FlangOption, FC1Option]>, HelpText<"Do not link device library for CUDA/HIP device compilation">; def : Flag<["-"], "nocudalib">, Alias; -def gpulibc : Flag<["-"], "gpulibc">, Visibility<[ClangOption, CC1Option]>, +def gpulibc : Flag<["-"], "gpulibc">, Visibility<[ClangOption, CC1Option, FlangOption, FC1Option]>, HelpText<"Link the LLVM C Library for GPUs">; -def nogpulibc : Flag<["-"], "nogpulibc">, Visibility<[ClangOption, CC1Option]>; +def nogpulibc : Flag<["-"], "nogpulibc">, Visibility<[ClangOption, CC1Option, FlangOption, FC1Option]>; def nodefaultlibs : Flag<["-"], "nodefaultlibs">; def nodriverkitlib : Flag<["-"], "nodriverkitlib">; def nofixprebinding : Flag<["-"], "nofixprebinding">; @@ -7013,6 +7017,8 @@ def mbranch_target_enforce : Flag<["-"], "mbranch-target-enforce">, MarshallingInfoFlag>; def mbranch_protection_pauth_lr : Flag<["-"], "mbranch-protection-pauth-lr">, MarshallingInfoFlag>; +def mguarded_control_stack : Flag<["-"], "mguarded-control-stack">, + MarshallingInfoFlag>; def fno_dllexport_inlines : Flag<["-"], "fno-dllexport-inlines">, MarshallingInfoNegativeFlag>; def cfguard_no_checks : Flag<["-"], "cfguard-no-checks">, diff --git a/clang/include/clang/Format/.clang-format b/clang/include/clang/Format/.clang-format index d7331b3c8cf02ef7944e83a4280476627e33b31d..f95602cab0f7fcdf5d34c485d52b65993dbb83d9 100644 --- a/clang/include/clang/Format/.clang-format +++ b/clang/include/clang/Format/.clang-format @@ -1 +1,6 @@ -BasedOnStyle: clang-format +BasedOnStyle: LLVM +InsertBraces: true +InsertNewlineAtEOF: true +LineEnding: LF +RemoveBracesLLVM: true +RemoveParentheses: ReturnStatement diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h index 8604dea689f9371669ed9d7570dea224de4b1dae..5ffd63ee73fc361e21be5e53f893f1e5503487a7 100644 --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -225,6 +225,22 @@ struct FormatStyle { /// bbb = 2; /// \endcode bool AlignCompound; + /// Only for ``AlignConsecutiveDeclarations``. Whether function pointers are + /// aligned. + /// \code + /// true: + /// unsigned i; + /// int &r; + /// int *p; + /// int (*f)(); + /// + /// false: + /// unsigned i; + /// int &r; + /// int *p; + /// int (*f)(); + /// \endcode + bool AlignFunctionPointers; /// Only for ``AlignConsecutiveAssignments``. Whether short assignment /// operators are left-padded to the same length as long ones in order to /// put all assignment operators to the right of the left hand side. @@ -247,7 +263,9 @@ struct FormatStyle { bool operator==(const AlignConsecutiveStyle &R) const { return Enabled == R.Enabled && AcrossEmptyLines == R.AcrossEmptyLines && AcrossComments == R.AcrossComments && - AlignCompound == R.AlignCompound && PadOperators == R.PadOperators; + AlignCompound == R.AlignCompound && + AlignFunctionPointers == R.AlignFunctionPointers && + PadOperators == R.PadOperators; } bool operator!=(const AlignConsecutiveStyle &R) const { return !(*this == R); @@ -3037,6 +3055,7 @@ struct FormatStyle { bool isProto() const { return Language == LK_Proto || Language == LK_TextProto; } + bool isTableGen() const { return Language == LK_TableGen; } /// Language, this format style is targeted at. /// \version 3.5 diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 2dbe090bd0932fc5afe59b25ffaf4f5910f2de70..e50a4d05b459918379ae6cbf61742f2c89f4c2c4 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -13,6 +13,7 @@ #ifndef LLVM_CLANG_PARSE_PARSER_H #define LLVM_CLANG_PARSE_PARSER_H +#include "clang/Basic/OpenACCKinds.h" #include "clang/Basic/OperatorPrecedence.h" #include "clang/Lex/CodeCompletionHandler.h" #include "clang/Lex/Preprocessor.h" @@ -234,6 +235,26 @@ class Parser : public CodeCompletionHandler { /// Parsing OpenACC directive mode. bool OpenACCDirectiveParsing = false; + /// Currently parsing a situation where an OpenACC array section could be + /// legal, such as a 'var-list'. + bool AllowOpenACCArraySections = false; + + /// RAII object to set reset OpenACC parsing a context where Array Sections + /// are allowed. + class OpenACCArraySectionRAII { + Parser &P; + + public: + OpenACCArraySectionRAII(Parser &P) : P(P) { + assert(!P.AllowOpenACCArraySections); + P.AllowOpenACCArraySections = true; + } + ~OpenACCArraySectionRAII() { + assert(P.AllowOpenACCArraySections); + P.AllowOpenACCArraySections = false; + } + }; + /// When true, we are directly inside an Objective-C message /// send expression. /// @@ -3546,8 +3567,18 @@ private: ExprResult ParseOpenACCIDExpression(); /// Parses the variable list for the `cache` construct. void ParseOpenACCCacheVarList(); - /// Parses a single variable in a variable list for the 'cache' construct. - bool ParseOpenACCCacheVar(); + /// Parses a single variable in a variable list for OpenACC. + bool ParseOpenACCVar(); + /// Parses the variable list for the variety of clauses that take a var-list, + /// including the optional Special Token listed for some,based on clause type. + bool ParseOpenACCClauseVarList(OpenACCClauseKind Kind); + /// Parses any parameters for an OpenACC Clause, including required/optional + /// parens. + bool ParseOpenACCClauseParams(OpenACCClauseKind Kind); + /// Parses a single clause in a clause-list for OpenACC. + bool ParseOpenACCClause(); + /// Parses the clause-list for an OpenACC directive. + void ParseOpenACCClauseList(); bool ParseOpenACCWaitArgument(); private: diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 8f44adef38159eaa08389e92f4bbf15f0eb72473..cf2d4fbe6d3ba105ec4be16f746df1c298e185bb 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -4799,6 +4799,8 @@ public: bool CheckAlwaysInlineAttr(const Stmt *OrigSt, const Stmt *CurSt, const AttributeCommonInfo &A); + bool CheckCountedByAttr(Scope *Scope, const FieldDecl *FD); + /// Adjust the calling convention of a method to be the ABI default if it /// wasn't specified explicitly. This handles method types formed from /// function type typedefs and typename template arguments. @@ -5642,6 +5644,7 @@ public: CorrectionCandidateCallback &CCC, TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr, ArrayRef Args = std::nullopt, + DeclContext *LookupCtx = nullptr, TypoExpr **Out = nullptr); DeclResult LookupIvarInObjCMethod(LookupResult &Lookup, Scope *S, @@ -11346,9 +11349,12 @@ private: /// rigorous semantic checking in the new mapped directives. bool mapLoopConstruct(llvm::SmallVector &ClausesWithoutBind, ArrayRef Clauses, - OpenMPBindClauseKind BindKind, + OpenMPBindClauseKind &BindKind, OpenMPDirectiveKind &Kind, - OpenMPDirectiveKind &PrevMappedDirective); + OpenMPDirectiveKind &PrevMappedDirective, + SourceLocation StartLoc, SourceLocation EndLoc, + const DeclarationNameInfo &DirName, + OpenMPDirectiveKind CancelRegion); public: /// The declarator \p D defines a function in the scope \p S which is nested @@ -12969,7 +12975,7 @@ public: QualType FindCompositeObjCPointerType(ExprResult &LHS, ExprResult &RHS, SourceLocation QuestionLoc); - bool DiagnoseConditionalForNull(Expr *LHSExpr, Expr *RHSExpr, + bool DiagnoseConditionalForNull(const Expr *LHSExpr, const Expr *RHSExpr, SourceLocation QuestionLoc); void DiagnoseAlwaysNonNullPointer(Expr *E, diff --git a/clang/include/clang/Sema/TypoCorrection.h b/clang/include/clang/Sema/TypoCorrection.h index e0f8d152dbe5545a56055ec2b554c0a37e93b889..09de164297e7baa982ef75db617647bd5d92b528 100644 --- a/clang/include/clang/Sema/TypoCorrection.h +++ b/clang/include/clang/Sema/TypoCorrection.h @@ -282,7 +282,7 @@ class CorrectionCandidateCallback { public: static const unsigned InvalidDistance = TypoCorrection::InvalidDistance; - explicit CorrectionCandidateCallback(IdentifierInfo *Typo = nullptr, + explicit CorrectionCandidateCallback(const IdentifierInfo *Typo = nullptr, NestedNameSpecifier *TypoNNS = nullptr) : Typo(Typo), TypoNNS(TypoNNS) {} @@ -319,7 +319,7 @@ public: /// this method. virtual std::unique_ptr clone() = 0; - void setTypoName(IdentifierInfo *II) { Typo = II; } + void setTypoName(const IdentifierInfo *II) { Typo = II; } void setTypoNNS(NestedNameSpecifier *NNS) { TypoNNS = NNS; } // Flags for context-dependent keywords. WantFunctionLikeCasts is only @@ -345,13 +345,13 @@ protected: candidate.getCorrectionSpecifier() == TypoNNS; } - IdentifierInfo *Typo; + const IdentifierInfo *Typo; NestedNameSpecifier *TypoNNS; }; class DefaultFilterCCC final : public CorrectionCandidateCallback { public: - explicit DefaultFilterCCC(IdentifierInfo *Typo = nullptr, + explicit DefaultFilterCCC(const IdentifierInfo *Typo = nullptr, NestedNameSpecifier *TypoNNS = nullptr) : CorrectionCandidateCallback(Typo, TypoNNS) {} @@ -365,6 +365,10 @@ public: template class DeclFilterCCC final : public CorrectionCandidateCallback { public: + explicit DeclFilterCCC(const IdentifierInfo *Typo = nullptr, + NestedNameSpecifier *TypoNNS = nullptr) + : CorrectionCandidateCallback(Typo, TypoNNS) {} + bool ValidateCandidate(const TypoCorrection &candidate) override { return candidate.getCorrectionDeclAs(); } diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index b60dcfaabfd1a4bef96ddcb428789aad9dbeefb6..d9cefcaa84d7e5d1080abc6eea2e53183b07ee23 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -1318,6 +1318,13 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target, InitBuiltinType(OMPArrayShapingTy, BuiltinType::OMPArrayShaping); InitBuiltinType(OMPIteratorTy, BuiltinType::OMPIterator); } + // Placeholder type for OpenACC array sections. + if (LangOpts.OpenACC) { + // FIXME: Once we implement OpenACC array sections in Sema, this will either + // be combined with the OpenMP type, or given its own type. In the meantime, + // just use the OpenMP type so that parsing can work. + InitBuiltinType(OMPArraySectionTy, BuiltinType::OMPArraySection); + } if (LangOpts.MatrixTypes) InitBuiltinType(IncompleteMatrixIdxTy, BuiltinType::IncompleteMatrixIdx); diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 9ffae72346f2affda656c728686f4ca04c8cad45..b762d6a4cd3800fdb935a90d7ffa347e57e0069a 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -2034,23 +2034,25 @@ ASTNodeImporter::ImportDeclContext(DeclContext *FromDC, bool ForceImport) { return ToDCOrErr.takeError(); } - DeclContext *ToDC = *ToDCOrErr; - // Remove all declarations, which may be in wrong order in the - // lexical DeclContext and then add them in the proper order. - for (auto *D : FromDC->decls()) { - if (!MightNeedReordering(D)) - continue; + if (const auto *FromRD = dyn_cast(FromDC)) { + DeclContext *ToDC = *ToDCOrErr; + // Remove all declarations, which may be in wrong order in the + // lexical DeclContext and then add them in the proper order. + for (auto *D : FromRD->decls()) { + if (!MightNeedReordering(D)) + continue; - assert(D && "DC contains a null decl"); - if (Decl *ToD = Importer.GetAlreadyImportedOrNull(D)) { - // Remove only the decls which we successfully imported. - assert(ToDC == ToD->getLexicalDeclContext() && ToDC->containsDecl(ToD)); - // Remove the decl from its wrong place in the linked list. - ToDC->removeDecl(ToD); - // Add the decl to the end of the linked list. - // This time it will be at the proper place because the enclosing for - // loop iterates in the original (good) order of the decls. - ToDC->addDeclInternal(ToD); + assert(D && "DC contains a null decl"); + if (Decl *ToD = Importer.GetAlreadyImportedOrNull(D)) { + // Remove only the decls which we successfully imported. + assert(ToDC == ToD->getLexicalDeclContext() && ToDC->containsDecl(ToD)); + // Remove the decl from its wrong place in the linked list. + ToDC->removeDecl(ToD); + // Add the decl to the end of the linked list. + // This time it will be at the proper place because the enclosing for + // loop iterates in the original (good) order of the decls. + ToDC->addDeclInternal(ToD); + } } } @@ -5927,15 +5929,22 @@ ExpectedDecl ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) { if (ToD) return ToD; - bool IsFriendTemplate = D->getFriendObjectKind() != Decl::FOK_None; - bool IsDependentContext = DC != LexicalDC ? LexicalDC->isDependentContext() - : DC->isDependentContext(); - bool DependentFriend = IsFriendTemplate && IsDependentContext; + // Should check if a declaration is friend in a dependent context. + // Such templates are not linked together in a declaration chain. + // The ASTImporter strategy is to map existing forward declarations to + // imported ones only if strictly necessary, otherwise import these as new + // forward declarations. In case of the "dependent friend" declarations, new + // declarations are created, but not linked in a declaration chain. + auto IsDependentFriend = [](ClassTemplateDecl *TD) { + return TD->getFriendObjectKind() != Decl::FOK_None && + TD->getLexicalDeclContext()->isDependentContext(); + }; + bool DependentFriend = IsDependentFriend(D); ClassTemplateDecl *FoundByLookup = nullptr; // We may already have a template of the same name; try to find and match it. - if (!DependentFriend && !DC->isFunctionOrMethod()) { + if (!DC->isFunctionOrMethod()) { SmallVector ConflictingDecls; auto FoundDecls = Importer.findDeclsInToCtx(DC, Name); for (auto *FoundDecl : FoundDecls) { @@ -5951,10 +5960,13 @@ ExpectedDecl ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) { // FIXME: sufficient conditon for 'IgnoreTemplateParmDepth'? bool IgnoreTemplateParmDepth = - FoundTemplate->getFriendObjectKind() != Decl::FOK_None && - !D->specializations().empty(); + (FoundTemplate->getFriendObjectKind() != Decl::FOK_None) != + (D->getFriendObjectKind() != Decl::FOK_None); if (IsStructuralMatch(D, FoundTemplate, /*Complain=*/true, IgnoreTemplateParmDepth)) { + if (DependentFriend || IsDependentFriend(FoundTemplate)) + continue; + ClassTemplateDecl *TemplateWithDef = getTemplateDefinition(FoundTemplate); if (D->isThisDeclarationADefinition() && TemplateWithDef) @@ -9028,6 +9040,10 @@ class AttrImporter { public: AttrImporter(ASTImporter &I) : Importer(I), NImporter(I) {} + // Useful for accessing the imported attribute. + template T *castAttrAs() { return cast(ToAttr); } + template const T *castAttrAs() const { return cast(ToAttr); } + // Create an "importer" for an attribute parameter. // Result of the 'value()' of that object is to be passed to the function // 'importAttr', in the order that is expected by the attribute class. @@ -9241,6 +9257,15 @@ Expected ASTImporter::Import(const Attr *FromAttr) { From->args_size()); break; } + case attr::CountedBy: { + AI.cloneAttr(FromAttr); + const auto *CBA = cast(FromAttr); + Expected SR = Import(CBA->getCountedByFieldLoc()).get(); + if (!SR) + return SR.takeError(); + AI.castAttrAs()->setCountedByFieldLoc(SR.get()); + break; + } default: { // The default branch works for attributes that have no arguments to import. diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 12e0a6faa4c33d184324bb1bfa26574ae32676e0..e1440e5183a4e61b2243a98eb259b0f429534d87 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -2835,7 +2835,7 @@ CharUnits VarDecl::getFlexibleArrayInitChars(const ASTContext &Ctx) const { if (!Ty || !Ty->getDecl()->hasFlexibleArrayMember()) return CharUnits::Zero(); auto *List = dyn_cast(getInit()->IgnoreParens()); - if (!List) + if (!List || List->getNumInits() == 0) return CharUnits::Zero(); const Expr *FlexibleInit = List->getInit(List->getNumInits() - 1); auto InitTy = Ctx.getAsConstantArrayType(FlexibleInit->getType()); diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp index b1733c2d052a65ef654eddd6b8350749596f0500..8163f9bdaf8d971063b4a533623ca1d3a6ac347d 100644 --- a/clang/lib/AST/DeclBase.cpp +++ b/clang/lib/AST/DeclBase.cpp @@ -29,7 +29,6 @@ #include "clang/AST/Type.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/LLVM.h" -#include "clang/Basic/LangOptions.h" #include "clang/Basic/Module.h" #include "clang/Basic/ObjCRuntime.h" #include "clang/Basic/PartialDiagnostic.h" @@ -411,6 +410,79 @@ bool Decl::isFileContextDecl() const { return DC && DC->isFileContext(); } +bool Decl::isFlexibleArrayMemberLike( + ASTContext &Ctx, const Decl *D, QualType Ty, + LangOptions::StrictFlexArraysLevelKind StrictFlexArraysLevel, + bool IgnoreTemplateOrMacroSubstitution) { + // For compatibility with existing code, we treat arrays of length 0 or + // 1 as flexible array members. + const auto *CAT = Ctx.getAsConstantArrayType(Ty); + if (CAT) { + using FAMKind = LangOptions::StrictFlexArraysLevelKind; + + llvm::APInt Size = CAT->getSize(); + if (StrictFlexArraysLevel == FAMKind::IncompleteOnly) + return false; + + // GCC extension, only allowed to represent a FAM. + if (Size.isZero()) + return true; + + if (StrictFlexArraysLevel == FAMKind::ZeroOrIncomplete && Size.uge(1)) + return false; + + if (StrictFlexArraysLevel == FAMKind::OneZeroOrIncomplete && Size.uge(2)) + return false; + } else if (!Ctx.getAsIncompleteArrayType(Ty)) { + return false; + } + + if (const auto *OID = dyn_cast_if_present(D)) + return OID->getNextIvar() == nullptr; + + const auto *FD = dyn_cast_if_present(D); + if (!FD) + return false; + + if (CAT) { + // GCC treats an array memeber of a union as an FAM if the size is one or + // zero. + llvm::APInt Size = CAT->getSize(); + if (FD->getParent()->isUnion() && (Size.isZero() || Size.isOne())) + return true; + } + + // Don't consider sizes resulting from macro expansions or template argument + // substitution to form C89 tail-padded arrays. + if (IgnoreTemplateOrMacroSubstitution) { + TypeSourceInfo *TInfo = FD->getTypeSourceInfo(); + while (TInfo) { + TypeLoc TL = TInfo->getTypeLoc(); + + // Look through typedefs. + if (TypedefTypeLoc TTL = TL.getAsAdjusted()) { + const TypedefNameDecl *TDL = TTL.getTypedefNameDecl(); + TInfo = TDL->getTypeSourceInfo(); + continue; + } + + if (auto CTL = TL.getAs()) { + if (const Expr *SizeExpr = + dyn_cast_if_present(CTL.getSizeExpr()); + !SizeExpr || SizeExpr->getExprLoc().isMacroID()) + return false; + } + + break; + } + } + + // Test that the field is the last in the structure. + RecordDecl::field_iterator FI( + DeclContext::decl_iterator(const_cast(FD))); + return ++FI == FD->getParent()->field_end(); +} + TranslationUnitDecl *Decl::getTranslationUnitDecl() { if (auto *TUD = dyn_cast(this)) return TUD; diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index c944862fcefeeef35820d8e890c46d1d9fe12769..98b0a6dc28ea2f0e225d9be3da3bb750287c8fa8 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -587,6 +587,19 @@ bool CXXRecordDecl::isTriviallyCopyable() const { return true; } +bool CXXRecordDecl::isTriviallyCopyConstructible() const { + + // A trivially copy constructible class is a class that: + // -- has no non-trivial copy constructors, + if (hasNonTrivialCopyConstructor()) + return false; + // -- has a trivial destructor. + if (!hasTrivialDestructor()) + return false; + + return true; +} + void CXXRecordDecl::markedVirtualFunctionPure() { // C++ [class.abstract]p2: // A class is abstract if it has at least one pure virtual function. diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index a90f92d07f86d26b85a544a888487f5cc8169e72..b125fc676da8419e737761b7db2a711df54adb46 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -205,85 +205,22 @@ bool Expr::isKnownToHaveBooleanValue(bool Semantic) const { } bool Expr::isFlexibleArrayMemberLike( - ASTContext &Context, + ASTContext &Ctx, LangOptions::StrictFlexArraysLevelKind StrictFlexArraysLevel, bool IgnoreTemplateOrMacroSubstitution) const { - - // For compatibility with existing code, we treat arrays of length 0 or - // 1 as flexible array members. - const auto *CAT = Context.getAsConstantArrayType(getType()); - if (CAT) { - llvm::APInt Size = CAT->getSize(); - - using FAMKind = LangOptions::StrictFlexArraysLevelKind; - - if (StrictFlexArraysLevel == FAMKind::IncompleteOnly) - return false; - - // GCC extension, only allowed to represent a FAM. - if (Size == 0) - return true; - - if (StrictFlexArraysLevel == FAMKind::ZeroOrIncomplete && Size.uge(1)) - return false; - - if (StrictFlexArraysLevel == FAMKind::OneZeroOrIncomplete && Size.uge(2)) - return false; - } else if (!Context.getAsIncompleteArrayType(getType())) - return false; - const Expr *E = IgnoreParens(); + const Decl *D = nullptr; - const NamedDecl *ND = nullptr; - if (const auto *DRE = dyn_cast(E)) - ND = DRE->getDecl(); - else if (const auto *ME = dyn_cast(E)) - ND = ME->getMemberDecl(); + if (const auto *ME = dyn_cast(E)) + D = ME->getMemberDecl(); + else if (const auto *DRE = dyn_cast(E)) + D = DRE->getDecl(); else if (const auto *IRE = dyn_cast(E)) - return IRE->getDecl()->getNextIvar() == nullptr; - - if (!ND) - return false; + D = IRE->getDecl(); - // A flexible array member must be the last member in the class. - // FIXME: If the base type of the member expr is not FD->getParent(), - // this should not be treated as a flexible array member access. - if (const auto *FD = dyn_cast(ND)) { - // GCC treats an array memeber of a union as an FAM if the size is one or - // zero. - if (CAT) { - llvm::APInt Size = CAT->getSize(); - if (FD->getParent()->isUnion() && (Size.isZero() || Size.isOne())) - return true; - } - - // Don't consider sizes resulting from macro expansions or template argument - // substitution to form C89 tail-padded arrays. - if (IgnoreTemplateOrMacroSubstitution) { - TypeSourceInfo *TInfo = FD->getTypeSourceInfo(); - while (TInfo) { - TypeLoc TL = TInfo->getTypeLoc(); - // Look through typedefs. - if (TypedefTypeLoc TTL = TL.getAsAdjusted()) { - const TypedefNameDecl *TDL = TTL.getTypedefNameDecl(); - TInfo = TDL->getTypeSourceInfo(); - continue; - } - if (ConstantArrayTypeLoc CTL = TL.getAs()) { - const Expr *SizeExpr = dyn_cast(CTL.getSizeExpr()); - if (!SizeExpr || SizeExpr->getExprLoc().isMacroID()) - return false; - } - break; - } - } - - RecordDecl::field_iterator FI( - DeclContext::decl_iterator(const_cast(FD))); - return ++FI == FD->getParent()->field_end(); - } - - return false; + return Decl::isFlexibleArrayMemberLike(Ctx, D, E->getType(), + StrictFlexArraysLevel, + IgnoreTemplateOrMacroSubstitution); } const ValueDecl * diff --git a/clang/lib/AST/FormatString.cpp b/clang/lib/AST/FormatString.cpp index e0c9e18cfe3a243238de8a8f17a302c33f3f66ed..c5d14b4af7ff1547cef803d8f9818674ecbf3285 100644 --- a/clang/lib/AST/FormatString.cpp +++ b/clang/lib/AST/FormatString.cpp @@ -488,7 +488,6 @@ ArgType::matchesType(ASTContext &C, QualType argTy) const { return NoMatchPromotionTypeConfusion; break; case BuiltinType::Half: - case BuiltinType::Float16: case BuiltinType::Float: if (T == C.DoubleTy) return MatchPromotion; diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp index e6b3097a80d8f78994308057e8877c2e72648a70..7f8bbe787324814295679b55cb44972d0de9324f 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -114,6 +114,8 @@ bool ByteCodeExprGen::VisitCastExpr(const CastExpr *CE) { } case CK_FloatingCast: { + if (DiscardResult) + return this->discard(SubExpr); if (!this->visit(SubExpr)) return false; const auto *TargetSemantics = &Ctx.getFloatSemantics(CE->getType()); @@ -121,6 +123,8 @@ bool ByteCodeExprGen::VisitCastExpr(const CastExpr *CE) { } case CK_IntegralToFloating: { + if (DiscardResult) + return this->discard(SubExpr); std::optional FromT = classify(SubExpr->getType()); if (!FromT) return false; @@ -135,6 +139,9 @@ bool ByteCodeExprGen::VisitCastExpr(const CastExpr *CE) { case CK_FloatingToBoolean: case CK_FloatingToIntegral: { + if (DiscardResult) + return this->discard(SubExpr); + std::optional ToT = classify(CE->getType()); if (!ToT) diff --git a/clang/lib/AST/Interp/Descriptor.cpp b/clang/lib/AST/Interp/Descriptor.cpp index 59a952135a2d80911e122b1ebade6d3c566dee60..b330e54baf335a7ac083deb5044206fa9e889a1b 100644 --- a/clang/lib/AST/Interp/Descriptor.cpp +++ b/clang/lib/AST/Interp/Descriptor.cpp @@ -275,8 +275,8 @@ Descriptor::Descriptor(const DeclTy &D, const Descriptor *Elem, MetadataSize MD, } /// Unknown-size arrays of composite elements. -Descriptor::Descriptor(const DeclTy &D, Descriptor *Elem, bool IsTemporary, - UnknownSize) +Descriptor::Descriptor(const DeclTy &D, const Descriptor *Elem, + bool IsTemporary, UnknownSize) : Source(D), ElemSize(Elem->getAllocSize() + sizeof(InlineDescriptor)), Size(UnknownSizeMark), MDSize(0), AllocSize(alignof(void *) + sizeof(InitMapPtr)), ElemDesc(Elem), @@ -286,7 +286,7 @@ Descriptor::Descriptor(const DeclTy &D, Descriptor *Elem, bool IsTemporary, } /// Composite records. -Descriptor::Descriptor(const DeclTy &D, Record *R, MetadataSize MD, +Descriptor::Descriptor(const DeclTy &D, const Record *R, MetadataSize MD, bool IsConst, bool IsTemporary, bool IsMutable) : Source(D), ElemSize(std::max(alignof(void *), R->getFullSize())), Size(ElemSize), MDSize(MD.value_or(0)), AllocSize(Size + MDSize), diff --git a/clang/lib/AST/Interp/Descriptor.h b/clang/lib/AST/Interp/Descriptor.h index 8135f3d12f7035cd3ab3518876277d1491587170..580c200f9095296b1150984626d4a8a877d8ed2b 100644 --- a/clang/lib/AST/Interp/Descriptor.h +++ b/clang/lib/AST/Interp/Descriptor.h @@ -100,7 +100,7 @@ public: static constexpr MetadataSize InlineDescMD = sizeof(InlineDescriptor); /// Pointer to the record, if block contains records. - Record *const ElemRecord = nullptr; + const Record *const ElemRecord = nullptr; /// Descriptor of the array element. const Descriptor *const ElemDesc = nullptr; /// Flag indicating if the block is mutable. @@ -135,10 +135,11 @@ public: unsigned NumElems, bool IsConst, bool IsTemporary, bool IsMutable); /// Allocates a descriptor for an array of composites of unknown size. - Descriptor(const DeclTy &D, Descriptor *Elem, bool IsTemporary, UnknownSize); + Descriptor(const DeclTy &D, const Descriptor *Elem, bool IsTemporary, + UnknownSize); /// Allocates a descriptor for a record. - Descriptor(const DeclTy &D, Record *R, MetadataSize MD, bool IsConst, + Descriptor(const DeclTy &D, const Record *R, MetadataSize MD, bool IsConst, bool IsTemporary, bool IsMutable); Descriptor(const DeclTy &D, MetadataSize MD); diff --git a/clang/lib/AST/Interp/Interp.cpp b/clang/lib/AST/Interp/Interp.cpp index a82d1c3c7c622a3db101443ed6fc8aa5d144f51d..9de0926b9dba9cd0feefd6d919f57fb9b5880457 100644 --- a/clang/lib/AST/Interp/Interp.cpp +++ b/clang/lib/AST/Interp/Interp.cpp @@ -134,6 +134,18 @@ void cleanupAfterFunctionCall(InterpState &S, CodePtr OpPC) { if (CurFunc->isUnevaluatedBuiltin()) return; + // Some builtin functions require us to only look at the call site, since + // the classified parameter types do not match. + if (CurFunc->isBuiltin()) { + const auto *CE = + cast(S.Current->Caller->getExpr(S.Current->getRetPC())); + for (int32_t I = CE->getNumArgs() - 1; I >= 0; --I) { + const Expr *A = CE->getArg(I); + popArg(S, A); + } + return; + } + if (S.Current->Caller && CurFunc->isVariadic()) { // CallExpr we're look for is at the return PC of the current function, i.e. // in the caller. @@ -290,10 +302,10 @@ bool CheckInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr, } bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr) { - if (!CheckDummy(S, OpPC, Ptr)) - return false; if (!CheckLive(S, OpPC, Ptr, AK_Read)) return false; + if (!CheckDummy(S, OpPC, Ptr)) + return false; if (!CheckExtern(S, OpPC, Ptr)) return false; if (!CheckRange(S, OpPC, Ptr, AK_Read)) diff --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h index 828d4ea35526d6c5261eb1b264afc306c394318f..c05dea0cc55d3c3721130d28c0cea1c5d4661b51 100644 --- a/clang/lib/AST/Interp/Interp.h +++ b/clang/lib/AST/Interp/Interp.h @@ -1813,9 +1813,6 @@ inline bool ArrayElemPtr(InterpState &S, CodePtr OpPC) { const T &Offset = S.Stk.pop(); const Pointer &Ptr = S.Stk.peek(); - if (!CheckArray(S, OpPC, Ptr)) - return false; - if (!OffsetHelper(S, OpPC, Offset, Ptr)) return false; @@ -1843,9 +1840,6 @@ inline bool ArrayElemPtrPop(InterpState &S, CodePtr OpPC) { const T &Offset = S.Stk.pop(); const Pointer &Ptr = S.Stk.pop(); - if (!CheckArray(S, OpPC, Ptr)) - return false; - if (!OffsetHelper(S, OpPC, Offset, Ptr)) return false; diff --git a/clang/lib/AST/Interp/InterpBuiltin.cpp b/clang/lib/AST/Interp/InterpBuiltin.cpp index b55b1569a259835f1a8f2b0a910ebd359d7f6f9f..754ca96b0c645e5b01df37159a9446a2ed3ba3a2 100644 --- a/clang/lib/AST/Interp/InterpBuiltin.cpp +++ b/clang/lib/AST/Interp/InterpBuiltin.cpp @@ -164,6 +164,8 @@ static bool retPrimValue(InterpState &S, CodePtr OpPC, APValue &Result, case X: \ return Ret(S, OpPC, Result); switch (*T) { + RET_CASE(PT_Ptr); + RET_CASE(PT_FnPtr); RET_CASE(PT_Float); RET_CASE(PT_Bool); RET_CASE(PT_Sint8); @@ -613,15 +615,34 @@ static bool interp__builtin_ffs(InterpState &S, CodePtr OpPC, return true; } +static bool interp__builtin_addressof(InterpState &S, CodePtr OpPC, + const InterpFrame *Frame, + const Function *Func, + const CallExpr *Call) { + PrimType PtrT = + S.getContext().classify(Call->getArg(0)->getType()).value_or(PT_Ptr); + + if (PtrT == PT_FnPtr) { + const FunctionPointer &Arg = S.Stk.peek(); + S.Stk.push(Arg); + } else if (PtrT == PT_Ptr) { + const Pointer &Arg = S.Stk.peek(); + S.Stk.push(Arg); + } else { + assert(false && "Unsupported pointer type passed to __builtin_addressof()"); + } + return true; +} + bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F, const CallExpr *Call) { InterpFrame *Frame = S.Current; APValue Dummy; - QualType ReturnType = Call->getCallReturnType(S.getCtx()); - std::optional ReturnT = S.getContext().classify(ReturnType); + std::optional ReturnT = S.getContext().classify(Call->getType()); + // If classify failed, we assume void. - assert(ReturnT || ReturnType->isVoidType()); + assert(ReturnT || Call->getType()->isVoidType()); switch (F->getBuiltinID()) { case Builtin::BI__builtin_is_constant_evaluated: @@ -820,6 +841,12 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F, if (!interp__builtin_ffs(S, OpPC, Frame, F, Call)) return false; break; + case Builtin::BIaddressof: + case Builtin::BI__addressof: + case Builtin::BI__builtin_addressof: + if (!interp__builtin_addressof(S, OpPC, Frame, F, Call)) + return false; + break; default: return false; diff --git a/clang/lib/AST/Interp/Program.cpp b/clang/lib/AST/Interp/Program.cpp index 52e13398163ecf79accac7ce285e07b008c3f64d..1daefab4dcdac1a7f5f696b1a53afef30cffe58c 100644 --- a/clang/lib/AST/Interp/Program.cpp +++ b/clang/lib/AST/Interp/Program.cpp @@ -315,14 +315,14 @@ Descriptor *Program::createDescriptor(const DeclTy &D, const Type *Ty, bool IsConst, bool IsTemporary, bool IsMutable, const Expr *Init) { // Classes and structures. - if (auto *RT = Ty->getAs()) { - if (auto *Record = getOrCreateRecord(RT->getDecl())) + if (const auto *RT = Ty->getAs()) { + if (const auto *Record = getOrCreateRecord(RT->getDecl())) return allocateDescriptor(D, Record, MDSize, IsConst, IsTemporary, IsMutable); } // Arrays. - if (auto ArrayType = Ty->getAsArrayTypeUnsafe()) { + if (const auto ArrayType = Ty->getAsArrayTypeUnsafe()) { QualType ElemTy = ArrayType->getElementType(); // Array of well-known bounds. if (auto CAT = dyn_cast(ArrayType)) { @@ -338,7 +338,7 @@ Descriptor *Program::createDescriptor(const DeclTy &D, const Type *Ty, } else { // Arrays of composites. In this case, the array is a list of pointers, // followed by the actual elements. - Descriptor *ElemDesc = createDescriptor( + const Descriptor *ElemDesc = createDescriptor( D, ElemTy.getTypePtr(), std::nullopt, IsConst, IsTemporary); if (!ElemDesc) return nullptr; @@ -358,8 +358,8 @@ Descriptor *Program::createDescriptor(const DeclTy &D, const Type *Ty, return allocateDescriptor(D, *T, IsTemporary, Descriptor::UnknownSize{}); } else { - Descriptor *Desc = createDescriptor(D, ElemTy.getTypePtr(), MDSize, - IsConst, IsTemporary); + const Descriptor *Desc = createDescriptor(D, ElemTy.getTypePtr(), + MDSize, IsConst, IsTemporary); if (!Desc) return nullptr; return allocateDescriptor(D, Desc, IsTemporary, @@ -369,14 +369,14 @@ Descriptor *Program::createDescriptor(const DeclTy &D, const Type *Ty, } // Atomic types. - if (auto *AT = Ty->getAs()) { + if (const auto *AT = Ty->getAs()) { const Type *InnerTy = AT->getValueType().getTypePtr(); return createDescriptor(D, InnerTy, MDSize, IsConst, IsTemporary, IsMutable); } // Complex types - represented as arrays of elements. - if (auto *CT = Ty->getAs()) { + if (const auto *CT = Ty->getAs()) { PrimType ElemTy = *Ctx.classify(CT->getElementType()); return allocateDescriptor(D, ElemTy, MDSize, 2, IsConst, IsTemporary, IsMutable); diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp index e8274fcd5cfe9cbc3c2deb7e16a582823769c87b..369ff66ac4dbc6d3a28aead018e500d09a1bba7b 100644 --- a/clang/lib/AST/TextNodeDumper.cpp +++ b/clang/lib/AST/TextNodeDumper.cpp @@ -1094,6 +1094,16 @@ void clang::TextNodeDumper::VisitReturnStmt(const ReturnStmt *Node) { } } +void clang::TextNodeDumper::VisitCoawaitExpr(const CoawaitExpr *Node) { + if (Node->isImplicit()) + OS << " implicit"; +} + +void clang::TextNodeDumper::VisitCoreturnStmt(const CoreturnStmt *Node) { + if (Node->isImplicit()) + OS << " implicit"; +} + void TextNodeDumper::VisitConstantExpr(const ConstantExpr *Node) { if (Node->hasAPValueResult()) AddChild("value", diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index a894d3289eb185defdcef98bea9b7e572fb168e8..b419fc8836b032455cb40bcbcc3a0dd1c5787a52 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -2604,19 +2604,22 @@ bool QualType::isTrivialType(const ASTContext &Context) const { return false; } -bool QualType::isTriviallyCopyableType(const ASTContext &Context) const { - if ((*this)->isArrayType()) - return Context.getBaseElementType(*this).isTriviallyCopyableType(Context); +static bool isTriviallyCopyableTypeImpl(const QualType &type, + const ASTContext &Context, + bool IsCopyConstructible) { + if (type->isArrayType()) + return isTriviallyCopyableTypeImpl(Context.getBaseElementType(type), + Context, IsCopyConstructible); - if (hasNonTrivialObjCLifetime()) + if (type.hasNonTrivialObjCLifetime()) return false; // C++11 [basic.types]p9 - See Core 2094 // Scalar types, trivially copyable class types, arrays of such types, and // cv-qualified versions of these types are collectively - // called trivially copyable types. + // called trivially copy constructible types. - QualType CanonicalType = getCanonicalType(); + QualType CanonicalType = type.getCanonicalType(); if (CanonicalType->isDependentType()) return false; @@ -2634,16 +2637,29 @@ bool QualType::isTriviallyCopyableType(const ASTContext &Context) const { if (const auto *RT = CanonicalType->getAs()) { if (const auto *ClassDecl = dyn_cast(RT->getDecl())) { - if (!ClassDecl->isTriviallyCopyable()) return false; + if (IsCopyConstructible) { + return ClassDecl->isTriviallyCopyConstructible(); + } else { + return ClassDecl->isTriviallyCopyable(); + } } - return true; } - // No other types can match. return false; } +bool QualType::isTriviallyCopyableType(const ASTContext &Context) const { + return isTriviallyCopyableTypeImpl(*this, Context, + /*IsCopyConstructible=*/false); +} + +bool QualType::isTriviallyCopyConstructibleType( + const ASTContext &Context) const { + return isTriviallyCopyableTypeImpl(*this, Context, + /*IsCopyConstructible=*/true); +} + bool QualType::isTriviallyRelocatableType(const ASTContext &Context) const { QualType BaseElementType = Context.getBaseElementType(*this); diff --git a/clang/lib/Analysis/ExprMutationAnalyzer.cpp b/clang/lib/Analysis/ExprMutationAnalyzer.cpp index 624a643cc60e4ba8b4993934ec3740c63135af7f..c0de9277ff866fdfd7fa7585859c2ae6741de1f8 100644 --- a/clang/lib/Analysis/ExprMutationAnalyzer.cpp +++ b/clang/lib/Analysis/ExprMutationAnalyzer.cpp @@ -15,6 +15,81 @@ namespace clang { using namespace ast_matchers; +// Check if result of Source expression could be a Target expression. +// Checks: +// - Implicit Casts +// - Binary Operators +// - ConditionalOperator +// - BinaryConditionalOperator +static bool canExprResolveTo(const Expr *Source, const Expr *Target) { + + const auto IgnoreDerivedToBase = [](const Expr *E, auto Matcher) { + if (Matcher(E)) + return true; + if (const auto *Cast = dyn_cast(E)) { + if ((Cast->getCastKind() == CK_DerivedToBase || + Cast->getCastKind() == CK_UncheckedDerivedToBase) && + Matcher(Cast->getSubExpr())) + return true; + } + return false; + }; + + const auto EvalCommaExpr = [](const Expr *E, auto Matcher) { + const Expr *Result = E; + while (const auto *BOComma = + dyn_cast_or_null(Result->IgnoreParens())) { + if (!BOComma->isCommaOp()) + break; + Result = BOComma->getRHS(); + } + + return Result != E && Matcher(Result); + }; + + // The 'ConditionalOperatorM' matches on ` ? : `. + // This matching must be recursive because `` can be anything resolving + // to the `InnerMatcher`, for example another conditional operator. + // The edge-case `BaseClass &b = ? DerivedVar1 : DerivedVar2;` + // is handled, too. The implicit cast happens outside of the conditional. + // This is matched by `IgnoreDerivedToBase(canResolveToExpr(InnerMatcher))` + // below. + const auto ConditionalOperatorM = [Target](const Expr *E) { + if (const auto *OP = dyn_cast(E)) { + if (const auto *TE = OP->getTrueExpr()->IgnoreParens()) + if (canExprResolveTo(TE, Target)) + return true; + if (const auto *FE = OP->getFalseExpr()->IgnoreParens()) + if (canExprResolveTo(FE, Target)) + return true; + } + return false; + }; + + const auto ElvisOperator = [Target](const Expr *E) { + if (const auto *OP = dyn_cast(E)) { + if (const auto *TE = OP->getTrueExpr()->IgnoreParens()) + if (canExprResolveTo(TE, Target)) + return true; + if (const auto *FE = OP->getFalseExpr()->IgnoreParens()) + if (canExprResolveTo(FE, Target)) + return true; + } + return false; + }; + + const Expr *SourceExprP = Source->IgnoreParens(); + return IgnoreDerivedToBase(SourceExprP, + [&](const Expr *E) { + return E == Target || ConditionalOperatorM(E) || + ElvisOperator(E); + }) || + EvalCommaExpr(SourceExprP, [&](const Expr *E) { + return IgnoreDerivedToBase( + E->IgnoreParens(), [&](const Expr *EE) { return EE == Target; }); + }); +} + namespace { AST_MATCHER_P(LambdaExpr, hasCaptureInit, const Expr *, E) { @@ -27,56 +102,14 @@ AST_MATCHER_P(CXXForRangeStmt, hasRangeStmt, return InnerMatcher.matches(*Range, Finder, Builder); } -AST_MATCHER_P(Expr, maybeEvalCommaExpr, ast_matchers::internal::Matcher, - InnerMatcher) { - const Expr *Result = &Node; - while (const auto *BOComma = - dyn_cast_or_null(Result->IgnoreParens())) { - if (!BOComma->isCommaOp()) - break; - Result = BOComma->getRHS(); - } - return InnerMatcher.matches(*Result, Finder, Builder); -} - -AST_MATCHER_P(Stmt, canResolveToExpr, ast_matchers::internal::Matcher, - InnerMatcher) { +AST_MATCHER_P(Stmt, canResolveToExpr, const Stmt *, Inner) { auto *Exp = dyn_cast(&Node); - if (!Exp) { - return stmt().matches(Node, Finder, Builder); - } - - auto DerivedToBase = [](const ast_matchers::internal::Matcher &Inner) { - return implicitCastExpr(anyOf(hasCastKind(CK_DerivedToBase), - hasCastKind(CK_UncheckedDerivedToBase)), - hasSourceExpression(Inner)); - }; - auto IgnoreDerivedToBase = - [&DerivedToBase](const ast_matchers::internal::Matcher &Inner) { - return ignoringParens(expr(anyOf(Inner, DerivedToBase(Inner)))); - }; - - // The 'ConditionalOperator' matches on ` ? : `. - // This matching must be recursive because `` can be anything resolving - // to the `InnerMatcher`, for example another conditional operator. - // The edge-case `BaseClass &b = ? DerivedVar1 : DerivedVar2;` - // is handled, too. The implicit cast happens outside of the conditional. - // This is matched by `IgnoreDerivedToBase(canResolveToExpr(InnerMatcher))` - // below. - auto const ConditionalOperator = conditionalOperator(anyOf( - hasTrueExpression(ignoringParens(canResolveToExpr(InnerMatcher))), - hasFalseExpression(ignoringParens(canResolveToExpr(InnerMatcher))))); - auto const ElvisOperator = binaryConditionalOperator(anyOf( - hasTrueExpression(ignoringParens(canResolveToExpr(InnerMatcher))), - hasFalseExpression(ignoringParens(canResolveToExpr(InnerMatcher))))); - - auto const ComplexMatcher = ignoringParens( - expr(anyOf(IgnoreDerivedToBase(InnerMatcher), - maybeEvalCommaExpr(IgnoreDerivedToBase(InnerMatcher)), - IgnoreDerivedToBase(ConditionalOperator), - IgnoreDerivedToBase(ElvisOperator)))); - - return ComplexMatcher.matches(*Exp, Finder, Builder); + if (!Exp) + return true; + auto *Target = dyn_cast(Inner); + if (!Target) + return false; + return canExprResolveTo(Exp, Target); } // Similar to 'hasAnyArgument', but does not work because 'InitListExpr' does @@ -121,6 +154,12 @@ AST_MATCHER_P(GenericSelectionExpr, hasControllingExpr, return InnerMatcher.matches(*Node.getControllingExpr(), Finder, Builder); } +template +ast_matchers::internal::Matcher +findFirst(const ast_matchers::internal::Matcher &Matcher) { + return anyOf(Matcher, hasDescendant(Matcher)); +} + const auto nonConstReferenceType = [] { return hasUnqualifiedDesugaredType( referenceType(pointee(unless(isConstQualified())))); @@ -220,8 +259,8 @@ bool ExprMutationAnalyzer::isUnevaluated(const Stmt *Exp, const Stmt &Stm, return selectFirst( NodeID::value, match( - findAll( - stmt(canResolveToExpr(equalsNode(Exp)), + findFirst( + stmt(canResolveToExpr(Exp), anyOf( // `Exp` is part of the underlying expression of // decltype/typeof if it has an ancestor of @@ -275,44 +314,41 @@ const Stmt *ExprMutationAnalyzer::findDeclPointeeMutation( const Stmt *ExprMutationAnalyzer::findDirectMutation(const Expr *Exp) { // LHS of any assignment operators. - const auto AsAssignmentLhs = binaryOperator( - isAssignmentOperator(), hasLHS(canResolveToExpr(equalsNode(Exp)))); + const auto AsAssignmentLhs = + binaryOperator(isAssignmentOperator(), hasLHS(canResolveToExpr(Exp))); // Operand of increment/decrement operators. const auto AsIncDecOperand = unaryOperator(anyOf(hasOperatorName("++"), hasOperatorName("--")), - hasUnaryOperand(canResolveToExpr(equalsNode(Exp)))); + hasUnaryOperand(canResolveToExpr(Exp))); // Invoking non-const member function. // A member function is assumed to be non-const when it is unresolved. const auto NonConstMethod = cxxMethodDecl(unless(isConst())); const auto AsNonConstThis = expr(anyOf( - cxxMemberCallExpr(on(canResolveToExpr(equalsNode(Exp))), - unless(isConstCallee())), + cxxMemberCallExpr(on(canResolveToExpr(Exp)), unless(isConstCallee())), cxxOperatorCallExpr(callee(NonConstMethod), - hasArgument(0, canResolveToExpr(equalsNode(Exp)))), + hasArgument(0, canResolveToExpr(Exp))), // In case of a templated type, calling overloaded operators is not // resolved and modelled as `binaryOperator` on a dependent type. // Such instances are considered a modification, because they can modify // in different instantiations of the template. - binaryOperator( - hasEitherOperand(ignoringImpCasts(canResolveToExpr(equalsNode(Exp)))), - isTypeDependent()), + binaryOperator(isTypeDependent(), + hasEitherOperand(ignoringImpCasts(canResolveToExpr(Exp)))), // Within class templates and member functions the member expression might // not be resolved. In that case, the `callExpr` is considered to be a // modification. - callExpr( - callee(expr(anyOf(unresolvedMemberExpr(hasObjectExpression( - canResolveToExpr(equalsNode(Exp)))), - cxxDependentScopeMemberExpr(hasObjectExpression( - canResolveToExpr(equalsNode(Exp)))))))), + callExpr(callee(expr(anyOf( + unresolvedMemberExpr(hasObjectExpression(canResolveToExpr(Exp))), + cxxDependentScopeMemberExpr( + hasObjectExpression(canResolveToExpr(Exp))))))), // Match on a call to a known method, but the call itself is type // dependent (e.g. `vector v; v.push(T{});` in a templated function). - callExpr(allOf(isTypeDependent(), - callee(memberExpr(hasDeclaration(NonConstMethod), - hasObjectExpression(canResolveToExpr( - equalsNode(Exp))))))))); + callExpr(allOf( + isTypeDependent(), + callee(memberExpr(hasDeclaration(NonConstMethod), + hasObjectExpression(canResolveToExpr(Exp)))))))); // Taking address of 'Exp'. // We're assuming 'Exp' is mutated as soon as its address is taken, though in @@ -322,11 +358,10 @@ const Stmt *ExprMutationAnalyzer::findDirectMutation(const Expr *Exp) { unaryOperator(hasOperatorName("&"), // A NoOp implicit cast is adding const. unless(hasParent(implicitCastExpr(hasCastKind(CK_NoOp)))), - hasUnaryOperand(canResolveToExpr(equalsNode(Exp)))); - const auto AsPointerFromArrayDecay = - castExpr(hasCastKind(CK_ArrayToPointerDecay), - unless(hasParent(arraySubscriptExpr())), - has(canResolveToExpr(equalsNode(Exp)))); + hasUnaryOperand(canResolveToExpr(Exp))); + const auto AsPointerFromArrayDecay = castExpr( + hasCastKind(CK_ArrayToPointerDecay), + unless(hasParent(arraySubscriptExpr())), has(canResolveToExpr(Exp))); // Treat calling `operator->()` of move-only classes as taking address. // These are typically smart pointers with unique ownership so we treat // mutation of pointee as mutation of the smart pointer itself. @@ -334,7 +369,7 @@ const Stmt *ExprMutationAnalyzer::findDirectMutation(const Expr *Exp) { hasOverloadedOperatorName("->"), callee( cxxMethodDecl(ofClass(isMoveOnly()), returns(nonConstPointerType()))), - argumentCountIs(1), hasArgument(0, canResolveToExpr(equalsNode(Exp)))); + argumentCountIs(1), hasArgument(0, canResolveToExpr(Exp))); // Used as non-const-ref argument when calling a function. // An argument is assumed to be non-const-ref when the function is unresolved. @@ -342,8 +377,8 @@ const Stmt *ExprMutationAnalyzer::findDirectMutation(const Expr *Exp) { // findFunctionArgMutation which has additional smarts for handling forwarding // references. const auto NonConstRefParam = forEachArgumentWithParamType( - anyOf(canResolveToExpr(equalsNode(Exp)), - memberExpr(hasObjectExpression(canResolveToExpr(equalsNode(Exp))))), + anyOf(canResolveToExpr(Exp), + memberExpr(hasObjectExpression(canResolveToExpr(Exp)))), nonConstReferenceType()); const auto NotInstantiated = unless(hasDeclaration(isInstantiated())); const auto TypeDependentCallee = @@ -354,19 +389,17 @@ const Stmt *ExprMutationAnalyzer::findDirectMutation(const Expr *Exp) { const auto AsNonConstRefArg = anyOf( callExpr(NonConstRefParam, NotInstantiated), cxxConstructExpr(NonConstRefParam, NotInstantiated), - callExpr(TypeDependentCallee, - hasAnyArgument(canResolveToExpr(equalsNode(Exp)))), - cxxUnresolvedConstructExpr( - hasAnyArgument(canResolveToExpr(equalsNode(Exp)))), + callExpr(TypeDependentCallee, hasAnyArgument(canResolveToExpr(Exp))), + cxxUnresolvedConstructExpr(hasAnyArgument(canResolveToExpr(Exp))), // Previous False Positive in the following Code: // `template void f() { int i = 42; new Type(i); }` // Where the constructor of `Type` takes its argument as reference. // The AST does not resolve in a `cxxConstructExpr` because it is // type-dependent. - parenListExpr(hasDescendant(expr(canResolveToExpr(equalsNode(Exp))))), + parenListExpr(hasDescendant(expr(canResolveToExpr(Exp)))), // If the initializer is for a reference type, there is no cast for // the variable. Values are cast to RValue first. - initListExpr(hasAnyInit(expr(canResolveToExpr(equalsNode(Exp)))))); + initListExpr(hasAnyInit(expr(canResolveToExpr(Exp))))); // Captured by a lambda by reference. // If we're initializing a capture with 'Exp' directly then we're initializing @@ -380,76 +413,72 @@ const Stmt *ExprMutationAnalyzer::findDirectMutation(const Expr *Exp) { // For returning by const-ref there will be an ImplicitCastExpr (for // adding const.) const auto AsNonConstRefReturn = - returnStmt(hasReturnValue(canResolveToExpr(equalsNode(Exp)))); + returnStmt(hasReturnValue(canResolveToExpr(Exp))); // It is used as a non-const-reference for initalizing a range-for loop. - const auto AsNonConstRefRangeInit = cxxForRangeStmt( - hasRangeInit(declRefExpr(allOf(canResolveToExpr(equalsNode(Exp)), - hasType(nonConstReferenceType()))))); + const auto AsNonConstRefRangeInit = cxxForRangeStmt(hasRangeInit(declRefExpr( + allOf(canResolveToExpr(Exp), hasType(nonConstReferenceType()))))); const auto Matches = match( - traverse(TK_AsIs, - findAll(stmt(anyOf(AsAssignmentLhs, AsIncDecOperand, - AsNonConstThis, AsAmpersandOperand, - AsPointerFromArrayDecay, AsOperatorArrowThis, - AsNonConstRefArg, AsLambdaRefCaptureInit, - AsNonConstRefReturn, AsNonConstRefRangeInit)) - .bind("stmt"))), + traverse( + TK_AsIs, + findFirst(stmt(anyOf(AsAssignmentLhs, AsIncDecOperand, AsNonConstThis, + AsAmpersandOperand, AsPointerFromArrayDecay, + AsOperatorArrowThis, AsNonConstRefArg, + AsLambdaRefCaptureInit, AsNonConstRefReturn, + AsNonConstRefRangeInit)) + .bind("stmt"))), Stm, Context); return selectFirst("stmt", Matches); } const Stmt *ExprMutationAnalyzer::findMemberMutation(const Expr *Exp) { // Check whether any member of 'Exp' is mutated. - const auto MemberExprs = - match(findAll(expr(anyOf(memberExpr(hasObjectExpression( - canResolveToExpr(equalsNode(Exp)))), - cxxDependentScopeMemberExpr(hasObjectExpression( - canResolveToExpr(equalsNode(Exp)))), - binaryOperator(hasOperatorName(".*"), - hasLHS(equalsNode(Exp))))) - .bind(NodeID::value)), - Stm, Context); + const auto MemberExprs = match( + findAll(expr(anyOf(memberExpr(hasObjectExpression(canResolveToExpr(Exp))), + cxxDependentScopeMemberExpr( + hasObjectExpression(canResolveToExpr(Exp))), + binaryOperator(hasOperatorName(".*"), + hasLHS(equalsNode(Exp))))) + .bind(NodeID::value)), + Stm, Context); return findExprMutation(MemberExprs); } const Stmt *ExprMutationAnalyzer::findArrayElementMutation(const Expr *Exp) { // Check whether any element of an array is mutated. - const auto SubscriptExprs = - match(findAll(arraySubscriptExpr( - anyOf(hasBase(canResolveToExpr(equalsNode(Exp))), - hasBase(implicitCastExpr( - allOf(hasCastKind(CK_ArrayToPointerDecay), - hasSourceExpression(canResolveToExpr( - equalsNode(Exp)))))))) - .bind(NodeID::value)), - Stm, Context); + const auto SubscriptExprs = match( + findAll(arraySubscriptExpr( + anyOf(hasBase(canResolveToExpr(Exp)), + hasBase(implicitCastExpr(allOf( + hasCastKind(CK_ArrayToPointerDecay), + hasSourceExpression(canResolveToExpr(Exp))))))) + .bind(NodeID::value)), + Stm, Context); return findExprMutation(SubscriptExprs); } const Stmt *ExprMutationAnalyzer::findCastMutation(const Expr *Exp) { // If the 'Exp' is explicitly casted to a non-const reference type the // 'Exp' is considered to be modified. - const auto ExplicitCast = match( - findAll( - stmt(castExpr(hasSourceExpression(canResolveToExpr(equalsNode(Exp))), - explicitCastExpr( - hasDestinationType(nonConstReferenceType())))) - .bind("stmt")), - Stm, Context); + const auto ExplicitCast = + match(findFirst(stmt(castExpr(hasSourceExpression(canResolveToExpr(Exp)), + explicitCastExpr(hasDestinationType( + nonConstReferenceType())))) + .bind("stmt")), + Stm, Context); if (const auto *CastStmt = selectFirst("stmt", ExplicitCast)) return CastStmt; // If 'Exp' is casted to any non-const reference type, check the castExpr. const auto Casts = match( - findAll( - expr(castExpr(hasSourceExpression(canResolveToExpr(equalsNode(Exp))), - anyOf(explicitCastExpr( - hasDestinationType(nonConstReferenceType())), - implicitCastExpr(hasImplicitDestinationType( - nonConstReferenceType()))))) - .bind(NodeID::value)), + findAll(expr(castExpr(hasSourceExpression(canResolveToExpr(Exp)), + anyOf(explicitCastExpr(hasDestinationType( + nonConstReferenceType())), + implicitCastExpr(hasImplicitDestinationType( + nonConstReferenceType()))))) + .bind(NodeID::value)), Stm, Context); if (const Stmt *S = findExprMutation(Casts)) @@ -458,7 +487,7 @@ const Stmt *ExprMutationAnalyzer::findCastMutation(const Expr *Exp) { const auto Calls = match(findAll(callExpr(callee(namedDecl( hasAnyName("::std::move", "::std::forward"))), - hasArgument(0, canResolveToExpr(equalsNode(Exp)))) + hasArgument(0, canResolveToExpr(Exp))) .bind("expr")), Stm, Context); return findExprMutation(Calls); @@ -473,16 +502,16 @@ const Stmt *ExprMutationAnalyzer::findRangeLoopMutation(const Expr *Exp) { // array is considered modified if the loop-variable is a non-const reference. const auto DeclStmtToNonRefToArray = declStmt(hasSingleDecl(varDecl(hasType( hasUnqualifiedDesugaredType(referenceType(pointee(arrayType()))))))); - const auto RefToArrayRefToElements = - match(findAll(stmt(cxxForRangeStmt( - hasLoopVariable( - varDecl(anyOf(hasType(nonConstReferenceType()), - hasType(nonConstPointerType()))) - .bind(NodeID::value)), - hasRangeStmt(DeclStmtToNonRefToArray), - hasRangeInit(canResolveToExpr(equalsNode(Exp))))) - .bind("stmt")), - Stm, Context); + const auto RefToArrayRefToElements = match( + findFirst(stmt(cxxForRangeStmt( + hasLoopVariable( + varDecl(anyOf(hasType(nonConstReferenceType()), + hasType(nonConstPointerType()))) + .bind(NodeID::value)), + hasRangeStmt(DeclStmtToNonRefToArray), + hasRangeInit(canResolveToExpr(Exp)))) + .bind("stmt")), + Stm, Context); if (const auto *BadRangeInitFromArray = selectFirst("stmt", RefToArrayRefToElements)) @@ -505,12 +534,12 @@ const Stmt *ExprMutationAnalyzer::findRangeLoopMutation(const Expr *Exp) { hasSingleDecl(varDecl(hasType(hasUnqualifiedDesugaredType(referenceType( pointee(hasDeclaration(cxxRecordDecl(HasAnyNonConstIterator))))))))); - const auto RefToContainerBadIterators = - match(findAll(stmt(cxxForRangeStmt(allOf( - hasRangeStmt(DeclStmtToNonConstIteratorContainer), - hasRangeInit(canResolveToExpr(equalsNode(Exp)))))) - .bind("stmt")), - Stm, Context); + const auto RefToContainerBadIterators = match( + findFirst(stmt(cxxForRangeStmt(allOf( + hasRangeStmt(DeclStmtToNonConstIteratorContainer), + hasRangeInit(canResolveToExpr(Exp))))) + .bind("stmt")), + Stm, Context); if (const auto *BadIteratorsContainer = selectFirst("stmt", RefToContainerBadIterators)) @@ -522,7 +551,7 @@ const Stmt *ExprMutationAnalyzer::findRangeLoopMutation(const Expr *Exp) { match(findAll(cxxForRangeStmt( hasLoopVariable(varDecl(hasType(nonConstReferenceType())) .bind(NodeID::value)), - hasRangeInit(canResolveToExpr(equalsNode(Exp))))), + hasRangeInit(canResolveToExpr(Exp)))), Stm, Context); return findDeclMutation(LoopVars); } @@ -531,31 +560,29 @@ const Stmt *ExprMutationAnalyzer::findReferenceMutation(const Expr *Exp) { // Follow non-const reference returned by `operator*()` of move-only classes. // These are typically smart pointers with unique ownership so we treat // mutation of pointee as mutation of the smart pointer itself. - const auto Ref = - match(findAll(cxxOperatorCallExpr( - hasOverloadedOperatorName("*"), - callee(cxxMethodDecl(ofClass(isMoveOnly()), - returns(nonConstReferenceType()))), - argumentCountIs(1), - hasArgument(0, canResolveToExpr(equalsNode(Exp)))) - .bind(NodeID::value)), - Stm, Context); + const auto Ref = match( + findAll(cxxOperatorCallExpr( + hasOverloadedOperatorName("*"), + callee(cxxMethodDecl(ofClass(isMoveOnly()), + returns(nonConstReferenceType()))), + argumentCountIs(1), hasArgument(0, canResolveToExpr(Exp))) + .bind(NodeID::value)), + Stm, Context); if (const Stmt *S = findExprMutation(Ref)) return S; // If 'Exp' is bound to a non-const reference, check all declRefExpr to that. const auto Refs = match( stmt(forEachDescendant( - varDecl( - hasType(nonConstReferenceType()), - hasInitializer(anyOf(canResolveToExpr(equalsNode(Exp)), - memberExpr(hasObjectExpression( - canResolveToExpr(equalsNode(Exp)))))), - hasParent(declStmt().bind("stmt")), - // Don't follow the reference in range statement, we've - // handled that separately. - unless(hasParent(declStmt(hasParent( - cxxForRangeStmt(hasRangeStmt(equalsBoundNode("stmt")))))))) + varDecl(hasType(nonConstReferenceType()), + hasInitializer(anyOf( + canResolveToExpr(Exp), + memberExpr(hasObjectExpression(canResolveToExpr(Exp))))), + hasParent(declStmt().bind("stmt")), + // Don't follow the reference in range statement, we've + // handled that separately. + unless(hasParent(declStmt(hasParent(cxxForRangeStmt( + hasRangeStmt(equalsBoundNode("stmt")))))))) .bind(NodeID::value))), Stm, Context); return findDeclMutation(Refs); @@ -563,7 +590,7 @@ const Stmt *ExprMutationAnalyzer::findReferenceMutation(const Expr *Exp) { const Stmt *ExprMutationAnalyzer::findFunctionArgMutation(const Expr *Exp) { const auto NonConstRefParam = forEachArgumentWithParam( - canResolveToExpr(equalsNode(Exp)), + canResolveToExpr(Exp), parmVarDecl(hasType(nonConstReferenceType())).bind("parm")); const auto IsInstantiated = hasDeclaration(isInstantiated()); const auto FuncDecl = hasDeclaration(functionDecl().bind("func")); diff --git a/clang/lib/Analysis/PathDiagnostic.cpp b/clang/lib/Analysis/PathDiagnostic.cpp index 0cb03943c547c36e6dfd7e1e87de9346ac85367b..79f337a91ec8fafd581e89d1205e58ad3611e3ac 100644 --- a/clang/lib/Analysis/PathDiagnostic.cpp +++ b/clang/lib/Analysis/PathDiagnostic.cpp @@ -50,12 +50,7 @@ using namespace clang; using namespace ento; -static StringRef StripTrailingDots(StringRef s) { - for (StringRef::size_type i = s.size(); i != 0; --i) - if (s[i - 1] != '.') - return s.substr(0, i); - return {}; -} +static StringRef StripTrailingDots(StringRef s) { return s.rtrim('.'); } PathDiagnosticPiece::PathDiagnosticPiece(StringRef s, Kind k, DisplayHint hint) diff --git a/clang/lib/Basic/Targets/AArch64.cpp b/clang/lib/Basic/Targets/AArch64.cpp index 2f8395cb8932f25ae6089be9644cefd92aeb072b..9ebaf4d40cd7e56591bec9381c4cba7ea75fcee1 100644 --- a/clang/lib/Basic/Targets/AArch64.cpp +++ b/clang/lib/Basic/Targets/AArch64.cpp @@ -226,6 +226,7 @@ bool AArch64TargetInfo::validateBranchProtection(StringRef Spec, StringRef, BPI.BranchTargetEnforcement = PBP.BranchTargetEnforcement; BPI.BranchProtectionPAuthLR = PBP.BranchProtectionPAuthLR; + BPI.GuardedControlStack = PBP.GuardedControlStack; return true; } @@ -532,6 +533,9 @@ void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts, if (Opts.BranchTargetEnforcement) Builder.defineMacro("__ARM_FEATURE_BTI_DEFAULT", "1"); + if (Opts.GuardedControlStack) + Builder.defineMacro("__ARM_FEATURE_GCS_DEFAULT", "1"); + if (HasLS64) Builder.defineMacro("__ARM_FEATURE_LS64", "1"); @@ -544,6 +548,9 @@ void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts, if (HasD128) Builder.defineMacro("__ARM_FEATURE_SYSREG128", "1"); + if (HasGCS) + Builder.defineMacro("__ARM_FEATURE_GCS", "1"); + if (*ArchInfo == llvm::AArch64::ARMV8_1A) getTargetDefinesARMV81A(Opts, Builder); else if (*ArchInfo == llvm::AArch64::ARMV8_2A) diff --git a/clang/lib/Basic/Targets/ARM.cpp b/clang/lib/Basic/Targets/ARM.cpp index 01f9e844da12a085ce3e2114775585afc9b77f00..a72bd42bad41579fb8f414aa4bf8cc615b86384f 100644 --- a/clang/lib/Basic/Targets/ARM.cpp +++ b/clang/lib/Basic/Targets/ARM.cpp @@ -17,6 +17,7 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSwitch.h" +#include "llvm/TargetParser/ARMTargetParser.h" using namespace clang; using namespace clang::targets; @@ -837,6 +838,69 @@ void ARMTargetInfo::getTargetDefines(const LangOptions &Opts, if (Opts.RWPI) Builder.defineMacro("__ARM_RWPI", "1"); + // Macros for enabling co-proc intrinsics + uint64_t FeatureCoprocBF = 0; + switch (ArchKind) { + default: + break; + case llvm::ARM::ArchKind::ARMV4: + case llvm::ARM::ArchKind::ARMV4T: + // Filter __arm_ldcl and __arm_stcl in acle.h + FeatureCoprocBF = isThumb() ? 0 : FEATURE_COPROC_B1; + break; + case llvm::ARM::ArchKind::ARMV5T: + FeatureCoprocBF = isThumb() ? 0 : FEATURE_COPROC_B1 | FEATURE_COPROC_B2; + break; + case llvm::ARM::ArchKind::ARMV5TE: + case llvm::ARM::ArchKind::ARMV5TEJ: + if (!isThumb()) + FeatureCoprocBF = + FEATURE_COPROC_B1 | FEATURE_COPROC_B2 | FEATURE_COPROC_B3; + break; + case llvm::ARM::ArchKind::ARMV6: + case llvm::ARM::ArchKind::ARMV6K: + case llvm::ARM::ArchKind::ARMV6KZ: + case llvm::ARM::ArchKind::ARMV6T2: + if (!isThumb() || ArchKind == llvm::ARM::ArchKind::ARMV6T2) + FeatureCoprocBF = FEATURE_COPROC_B1 | FEATURE_COPROC_B2 | + FEATURE_COPROC_B3 | FEATURE_COPROC_B4; + break; + case llvm::ARM::ArchKind::ARMV7A: + case llvm::ARM::ArchKind::ARMV7R: + case llvm::ARM::ArchKind::ARMV7M: + case llvm::ARM::ArchKind::ARMV7S: + case llvm::ARM::ArchKind::ARMV7EM: + FeatureCoprocBF = FEATURE_COPROC_B1 | FEATURE_COPROC_B2 | + FEATURE_COPROC_B3 | FEATURE_COPROC_B4; + break; + case llvm::ARM::ArchKind::ARMV8A: + case llvm::ARM::ArchKind::ARMV8R: + case llvm::ARM::ArchKind::ARMV8_1A: + case llvm::ARM::ArchKind::ARMV8_2A: + case llvm::ARM::ArchKind::ARMV8_3A: + case llvm::ARM::ArchKind::ARMV8_4A: + case llvm::ARM::ArchKind::ARMV8_5A: + case llvm::ARM::ArchKind::ARMV8_6A: + case llvm::ARM::ArchKind::ARMV8_7A: + case llvm::ARM::ArchKind::ARMV8_8A: + case llvm::ARM::ArchKind::ARMV8_9A: + case llvm::ARM::ArchKind::ARMV9A: + case llvm::ARM::ArchKind::ARMV9_1A: + case llvm::ARM::ArchKind::ARMV9_2A: + case llvm::ARM::ArchKind::ARMV9_3A: + case llvm::ARM::ArchKind::ARMV9_4A: + // Filter __arm_cdp, __arm_ldcl, __arm_stcl in arm_acle.h + FeatureCoprocBF = FEATURE_COPROC_B1 | FEATURE_COPROC_B3; + break; + case llvm::ARM::ArchKind::ARMV8MMainline: + case llvm::ARM::ArchKind::ARMV8_1MMainline: + FeatureCoprocBF = FEATURE_COPROC_B1 | FEATURE_COPROC_B2 | + FEATURE_COPROC_B3 | FEATURE_COPROC_B4; + break; + } + Builder.defineMacro("__ARM_FEATURE_COPROC", + "0x" + Twine::utohexstr(FeatureCoprocBF)); + if (ArchKind == llvm::ARM::ArchKind::XSCALE) Builder.defineMacro("__XSCALE__"); diff --git a/clang/lib/Basic/Targets/ARM.h b/clang/lib/Basic/Targets/ARM.h index b1aa2794c7e4c3d9bd1d8daab7a9a1cf6cdfb5fa..9802eb01abf3c43229917479b6ab6c2148ca1649 100644 --- a/clang/lib/Basic/Targets/ARM.h +++ b/clang/lib/Basic/Targets/ARM.h @@ -100,6 +100,19 @@ class LLVM_LIBRARY_VISIBILITY ARMTargetInfo : public TargetInfo { }; uint32_t HW_FP; + enum { + /// __arm_cdp __arm_ldc, __arm_ldcl, __arm_stc, + /// __arm_stcl, __arm_mcr and __arm_mrc + FEATURE_COPROC_B1 = (1 << 0), + /// __arm_cdp2, __arm_ldc2, __arm_stc2, __arm_ldc2l, + /// __arm_stc2l, __arm_mcr2 and __arm_mrc2 + FEATURE_COPROC_B2 = (1 << 1), + /// __arm_mcrr, __arm_mrrc + FEATURE_COPROC_B3 = (1 << 2), + /// __arm_mcrr2, __arm_mrrc2 + FEATURE_COPROC_B4 = (1 << 3), + }; + void setABIAAPCS(); void setABIAPCS(bool IsAAPCS16); diff --git a/clang/lib/Basic/Targets/RISCV.cpp b/clang/lib/Basic/Targets/RISCV.cpp index 6bc57a83a2d5ae6d79edc7b150ee98e60c9bcbe1..fb312b6cf26e02a783e2be71b92b766dedc53b7c 100644 --- a/clang/lib/Basic/Targets/RISCV.cpp +++ b/clang/lib/Basic/Targets/RISCV.cpp @@ -163,9 +163,8 @@ void RISCVTargetInfo::getTargetDefines(const LangOptions &Opts, auto ExtName = Extension.first; auto ExtInfo = Extension.second; - Builder.defineMacro( - Twine("__riscv_", ExtName), - Twine(getVersionValue(ExtInfo.MajorVersion, ExtInfo.MinorVersion))); + Builder.defineMacro(Twine("__riscv_", ExtName), + Twine(getVersionValue(ExtInfo.Major, ExtInfo.Minor))); } if (ISAInfo->hasExtension("m") || ISAInfo->hasExtension("zmmul")) @@ -237,22 +236,15 @@ ArrayRef RISCVTargetInfo::getTargetBuiltins() const { static std::vector collectNonISAExtFeature(ArrayRef FeaturesNeedOverride, int XLen) { - auto ParseResult = - llvm::RISCVISAInfo::parseFeatures(XLen, FeaturesNeedOverride); - - if (!ParseResult) { - consumeError(ParseResult.takeError()); - return std::vector(); - } - - std::vector ImpliedFeatures = (*ParseResult)->toFeatureVector(); - std::vector NonISAExtFeatureVec; + auto IsNonISAExtFeature = [](const std::string &Feature) { + assert(Feature.size() > 1 && (Feature[0] == '+' || Feature[0] == '-')); + StringRef Ext = StringRef(Feature).drop_front(); // drop the +/- + return !llvm::RISCVISAInfo::isSupportedExtensionFeature(Ext); + }; llvm::copy_if(FeaturesNeedOverride, std::back_inserter(NonISAExtFeatureVec), - [&](const std::string &Feat) { - return !llvm::is_contained(ImpliedFeatures, Feat); - }); + IsNonISAExtFeature); return NonISAExtFeatureVec; } @@ -303,7 +295,7 @@ bool RISCVTargetInfo::initFeatureMap( } // RISCVISAInfo makes implications for ISA features - std::vector ImpliedFeatures = (*ParseResult)->toFeatureVector(); + std::vector ImpliedFeatures = (*ParseResult)->toFeatures(); // parseFeatures normalizes the feature set by dropping any explicit // negatives, and non-extension features. We need to preserve the later @@ -420,7 +412,7 @@ static void handleFullArchString(StringRef FullArchStr, // Forward the invalid FullArchStr. Features.push_back("+" + FullArchStr.str()); } else { - std::vector FeatStrings = (*RII)->toFeatureVector(); + std::vector FeatStrings = (*RII)->toFeatures(); Features.insert(Features.end(), FeatStrings.begin(), FeatStrings.end()); } } diff --git a/clang/lib/Basic/Targets/X86.cpp b/clang/lib/Basic/Targets/X86.cpp index 3deaa19f8d4fc4abefe0746c19d6893bb63b8830..64e281b888a95ff07078e5b97200451cbe322e30 100644 --- a/clang/lib/Basic/Targets/X86.cpp +++ b/clang/lib/Basic/Targets/X86.cpp @@ -295,11 +295,13 @@ bool X86TargetInfo::handleTargetFeatures(std::vector &Features, HasAVX512BF16 = true; } else if (Feature == "+avx512er") { HasAVX512ER = true; + Diags.Report(diag::warn_knl_knm_isa_support_removed); } else if (Feature == "+avx512fp16") { HasAVX512FP16 = true; HasLegalHalfType = true; } else if (Feature == "+avx512pf") { HasAVX512PF = true; + Diags.Report(diag::warn_knl_knm_isa_support_removed); } else if (Feature == "+avx512dq") { HasAVX512DQ = true; } else if (Feature == "+avx512bitalg") { @@ -358,6 +360,7 @@ bool X86TargetInfo::handleTargetFeatures(std::vector &Features, HasPREFETCHI = true; } else if (Feature == "+prefetchwt1") { HasPREFETCHWT1 = true; + Diags.Report(diag::warn_knl_knm_isa_support_removed); } else if (Feature == "+clzero") { HasCLZERO = true; } else if (Feature == "+cldemote") { diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index f71dbf1729a1d6da7b41a73a49089e79fec37bbb..998fcc3af581753faceaa5eff43a8befe3392c93 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -25,6 +25,7 @@ #include "clang/AST/Attr.h" #include "clang/AST/Decl.h" #include "clang/AST/OSLog.h" +#include "clang/AST/OperationKinds.h" #include "clang/Basic/TargetBuiltins.h" #include "clang/Basic/TargetInfo.h" #include "clang/Basic/TargetOptions.h" @@ -818,6 +819,238 @@ CodeGenFunction::evaluateOrEmitBuiltinObjectSize(const Expr *E, unsigned Type, return ConstantInt::get(ResType, ObjectSize, /*isSigned=*/true); } +const FieldDecl *CodeGenFunction::FindFlexibleArrayMemberField( + ASTContext &Ctx, const RecordDecl *RD, StringRef Name, uint64_t &Offset) { + const LangOptions::StrictFlexArraysLevelKind StrictFlexArraysLevel = + getLangOpts().getStrictFlexArraysLevel(); + unsigned FieldNo = 0; + bool IsUnion = RD->isUnion(); + + for (const Decl *D : RD->decls()) { + if (const auto *Field = dyn_cast(D); + Field && (Name.empty() || Field->getNameAsString() == Name) && + Decl::isFlexibleArrayMemberLike( + Ctx, Field, Field->getType(), StrictFlexArraysLevel, + /*IgnoreTemplateOrMacroSubstitution=*/true)) { + const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(RD); + Offset += Layout.getFieldOffset(FieldNo); + return Field; + } + + if (const auto *Record = dyn_cast(D)) + if (const FieldDecl *Field = + FindFlexibleArrayMemberField(Ctx, Record, Name, Offset)) { + const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(RD); + Offset += Layout.getFieldOffset(FieldNo); + return Field; + } + + if (!IsUnion && isa(D)) + ++FieldNo; + } + + return nullptr; +} + +static unsigned CountCountedByAttrs(const RecordDecl *RD) { + unsigned Num = 0; + + for (const Decl *D : RD->decls()) { + if (const auto *FD = dyn_cast(D); + FD && FD->hasAttr()) { + return ++Num; + } + + if (const auto *Rec = dyn_cast(D)) + Num += CountCountedByAttrs(Rec); + } + + return Num; +} + +llvm::Value * +CodeGenFunction::emitFlexibleArrayMemberSize(const Expr *E, unsigned Type, + llvm::IntegerType *ResType) { + // The code generated here calculates the size of a struct with a flexible + // array member that uses the counted_by attribute. There are two instances + // we handle: + // + // struct s { + // unsigned long flags; + // int count; + // int array[] __attribute__((counted_by(count))); + // } + // + // 1) bdos of the flexible array itself: + // + // __builtin_dynamic_object_size(p->array, 1) == + // p->count * sizeof(*p->array) + // + // 2) bdos of a pointer into the flexible array: + // + // __builtin_dynamic_object_size(&p->array[42], 1) == + // (p->count - 42) * sizeof(*p->array) + // + // 2) bdos of the whole struct, including the flexible array: + // + // __builtin_dynamic_object_size(p, 1) == + // max(sizeof(struct s), + // offsetof(struct s, array) + p->count * sizeof(*p->array)) + // + ASTContext &Ctx = getContext(); + const Expr *Base = E->IgnoreParenImpCasts(); + const Expr *Idx = nullptr; + + if (const auto *UO = dyn_cast(Base); + UO && UO->getOpcode() == UO_AddrOf) { + Expr *SubExpr = UO->getSubExpr()->IgnoreParenImpCasts(); + if (const auto *ASE = dyn_cast(SubExpr)) { + Base = ASE->getBase()->IgnoreParenImpCasts(); + Idx = ASE->getIdx()->IgnoreParenImpCasts(); + + if (const auto *IL = dyn_cast(Idx)) { + int64_t Val = IL->getValue().getSExtValue(); + if (Val < 0) + return getDefaultBuiltinObjectSizeResult(Type, ResType); + + if (Val == 0) + // The index is 0, so we don't need to take it into account. + Idx = nullptr; + } + } else { + // Potential pointer to another element in the struct. + Base = SubExpr; + } + } + + // Get the flexible array member Decl. + const RecordDecl *OuterRD = nullptr; + std::string FAMName; + if (const auto *ME = dyn_cast(Base)) { + // Check if \p Base is referencing the FAM itself. + const ValueDecl *VD = ME->getMemberDecl(); + OuterRD = VD->getDeclContext()->getOuterLexicalRecordContext(); + FAMName = VD->getNameAsString(); + } else if (const auto *DRE = dyn_cast(Base)) { + // Check if we're pointing to the whole struct. + QualType Ty = DRE->getDecl()->getType(); + if (Ty->isPointerType()) + Ty = Ty->getPointeeType(); + OuterRD = Ty->getAsRecordDecl(); + + // If we have a situation like this: + // + // struct union_of_fams { + // int flags; + // union { + // signed char normal_field; + // struct { + // int count1; + // int arr1[] __counted_by(count1); + // }; + // struct { + // signed char count2; + // int arr2[] __counted_by(count2); + // }; + // }; + // }; + // + // We don't konw which 'count' to use in this scenario: + // + // size_t get_size(struct union_of_fams *p) { + // return __builtin_dynamic_object_size(p, 1); + // } + // + // Instead of calculating a wrong number, we give up. + if (OuterRD && CountCountedByAttrs(OuterRD) > 1) + return nullptr; + } + + if (!OuterRD) + return nullptr; + + uint64_t Offset = 0; + const FieldDecl *FAMDecl = + FindFlexibleArrayMemberField(Ctx, OuterRD, FAMName, Offset); + Offset = Ctx.toCharUnitsFromBits(Offset).getQuantity(); + + if (!FAMDecl || !FAMDecl->hasAttr()) + // No flexible array member found or it doesn't have the "counted_by" + // attribute. + return nullptr; + + const FieldDecl *CountedByFD = FindCountedByField(FAMDecl); + if (!CountedByFD) + // Can't find the field referenced by the "counted_by" attribute. + return nullptr; + + // Build a load of the counted_by field. + bool IsSigned = CountedByFD->getType()->isSignedIntegerType(); + Value *CountedByInst = EmitCountedByFieldExpr(Base, FAMDecl, CountedByFD); + if (!CountedByInst) + return getDefaultBuiltinObjectSizeResult(Type, ResType); + + CountedByInst = Builder.CreateIntCast(CountedByInst, ResType, IsSigned); + + // Build a load of the index and subtract it from the count. + Value *IdxInst = nullptr; + if (Idx) { + if (Idx->HasSideEffects(getContext())) + // We can't have side-effects. + return getDefaultBuiltinObjectSizeResult(Type, ResType); + + bool IdxSigned = Idx->getType()->isSignedIntegerType(); + IdxInst = EmitAnyExprToTemp(Idx).getScalarVal(); + IdxInst = Builder.CreateIntCast(IdxInst, ResType, IdxSigned); + + // We go ahead with the calculation here. If the index turns out to be + // negative, we'll catch it at the end. + CountedByInst = + Builder.CreateSub(CountedByInst, IdxInst, "", !IsSigned, IsSigned); + } + + // Calculate how large the flexible array member is in bytes. + const ArrayType *ArrayTy = Ctx.getAsArrayType(FAMDecl->getType()); + CharUnits Size = Ctx.getTypeSizeInChars(ArrayTy->getElementType()); + llvm::Constant *ElemSize = + llvm::ConstantInt::get(ResType, Size.getQuantity(), IsSigned); + Value *FAMSize = + Builder.CreateMul(CountedByInst, ElemSize, "", !IsSigned, IsSigned); + FAMSize = Builder.CreateIntCast(FAMSize, ResType, IsSigned); + Value *Res = FAMSize; + + if (const auto *DRE = dyn_cast(Base)) { + // The whole struct is specificed in the __bdos. + const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(OuterRD); + + // Get the offset of the FAM. + llvm::Constant *FAMOffset = ConstantInt::get(ResType, Offset, IsSigned); + Value *OffsetAndFAMSize = + Builder.CreateAdd(FAMOffset, Res, "", !IsSigned, IsSigned); + + // Get the full size of the struct. + llvm::Constant *SizeofStruct = + ConstantInt::get(ResType, Layout.getSize().getQuantity(), IsSigned); + + // max(sizeof(struct s), + // offsetof(struct s, array) + p->count * sizeof(*p->array)) + Res = IsSigned + ? Builder.CreateBinaryIntrinsic(llvm::Intrinsic::smax, + OffsetAndFAMSize, SizeofStruct) + : Builder.CreateBinaryIntrinsic(llvm::Intrinsic::umax, + OffsetAndFAMSize, SizeofStruct); + } + + // A negative \p IdxInst or \p CountedByInst means that the index lands + // outside of the flexible array member. If that's the case, we want to + // return 0. + Value *Cmp = Builder.CreateIsNotNeg(CountedByInst); + if (IdxInst) + Cmp = Builder.CreateAnd(Builder.CreateIsNotNeg(IdxInst), Cmp); + + return Builder.CreateSelect(Cmp, Res, ConstantInt::get(ResType, 0, IsSigned)); +} + /// Returns a Value corresponding to the size of the given expression. /// This Value may be either of the following: /// - A llvm::Argument (if E is a param with the pass_object_size attribute on @@ -850,6 +1083,13 @@ CodeGenFunction::emitBuiltinObjectSize(const Expr *E, unsigned Type, } } + if (IsDynamic) { + // Emit special code for a flexible array member with the "counted_by" + // attribute. + if (Value *V = emitFlexibleArrayMemberSize(E, Type, ResType)) + return V; + } + // LLVM can't handle Type=3 appropriately, and __builtin_object_size shouldn't // evaluate E for side-effects. In either case, we shouldn't lower to // @llvm.objectsize. @@ -9681,8 +9921,8 @@ Value *CodeGenFunction::EmitSVEMaskedStore(const CallExpr *E, bool IsQuadStore = false; switch (IntrinsicID) { - case Intrinsic::aarch64_sve_st1uwq: - case Intrinsic::aarch64_sve_st1udq: + case Intrinsic::aarch64_sve_st1wq: + case Intrinsic::aarch64_sve_st1dq: AddrMemoryTy = llvm::ScalableVectorType::get(MemEltTy, 1); PredTy = llvm::ScalableVectorType::get(IntegerType::get(getLLVMContext(), 1), 1); diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 51a43b5f85b3cc40cb135ab04593f181f1e29369..13677cf150aed2f39183f12bc42cde945a13b07b 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -2612,6 +2612,8 @@ void CodeGenModule::ConstructAttributeList(StringRef Name, if (IRFunctionArgs.hasSRetArg()) { llvm::AttrBuilder SRETAttrs(getLLVMContext()); SRETAttrs.addStructRetAttr(getTypes().ConvertTypeForMem(RetTy)); + SRETAttrs.addAttribute(llvm::Attribute::Writable); + SRETAttrs.addAttribute(llvm::Attribute::DeadOnUnwind); hasUsedSRet = true; if (RetAI.getInReg()) SRETAttrs.addAttribute(llvm::Attribute::InReg); diff --git a/clang/lib/CodeGen/CGException.cpp b/clang/lib/CodeGen/CGException.cpp index 0d507da5c1ba92f78ac5df4f0840c9e7edf605ac..56a246eb65e0a82222bee8c2699c9791c947c4bb 100644 --- a/clang/lib/CodeGen/CGException.cpp +++ b/clang/lib/CodeGen/CGException.cpp @@ -156,7 +156,9 @@ static const EHPersonality &getObjCPersonality(const TargetInfo &Target, case ObjCRuntime::WatchOS: return EHPersonality::NeXT_ObjC; case ObjCRuntime::GNUstep: - if (L.ObjCRuntime.getVersion() >= VersionTuple(1, 7)) + if (T.isOSCygMing()) + return EHPersonality::GNU_CPlusPlus_SEH; + else if (L.ObjCRuntime.getVersion() >= VersionTuple(1, 7)) return EHPersonality::GNUstep_ObjC; [[fallthrough]]; case ObjCRuntime::GCC: @@ -210,7 +212,8 @@ static const EHPersonality &getObjCXXPersonality(const TargetInfo &Target, return getObjCPersonality(Target, L); case ObjCRuntime::GNUstep: - return EHPersonality::GNU_ObjCXX; + return Target.getTriple().isOSCygMing() ? EHPersonality::GNU_CPlusPlus_SEH + : EHPersonality::GNU_ObjCXX; // The GCC runtime's personality function inherently doesn't support // mixed EH. Use the ObjC personality just to avoid returning null. diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 3f277725d9e7fc2a5e548124ce48501045bf3b95..d12e85b48d0b00b141aca52d39ba0cdfb5c38978 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -26,10 +26,12 @@ #include "clang/AST/Attr.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/NSAPI.h" +#include "clang/AST/StmtVisitor.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/CodeGenOptions.h" #include "clang/Basic/SourceManager.h" #include "llvm/ADT/Hashing.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringExtras.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/Intrinsics.h" @@ -925,16 +927,21 @@ static llvm::Value *getArrayIndexingBound(CodeGenFunction &CGF, if (CE->getCastKind() == CK_ArrayToPointerDecay && !CE->getSubExpr()->isFlexibleArrayMemberLike(CGF.getContext(), StrictFlexArraysLevel)) { + CodeGenFunction::SanitizerScope SanScope(&CGF); + IndexedType = CE->getSubExpr()->getType(); const ArrayType *AT = IndexedType->castAsArrayTypeUnsafe(); if (const auto *CAT = dyn_cast(AT)) return CGF.Builder.getInt(CAT->getSize()); - else if (const auto *VAT = dyn_cast(AT)) + + if (const auto *VAT = dyn_cast(AT)) return CGF.getVLASize(VAT).NumElts; // Ignore pass_object_size here. It's not applicable on decayed pointers. } } + CodeGenFunction::SanitizerScope SanScope(&CGF); + QualType EltTy{Base->getType()->getPointeeOrArrayElementType(), 0}; if (llvm::Value *POS = CGF.LoadPassedObjectSize(Base, EltTy)) { IndexedType = Base->getType(); @@ -944,22 +951,248 @@ static llvm::Value *getArrayIndexingBound(CodeGenFunction &CGF, return nullptr; } +namespace { + +/// \p StructAccessBase returns the base \p Expr of a field access. It returns +/// either a \p DeclRefExpr, representing the base pointer to the struct, i.e.: +/// +/// p in p-> a.b.c +/// +/// or a \p MemberExpr, if the \p MemberExpr has the \p RecordDecl we're +/// looking for: +/// +/// struct s { +/// struct s *ptr; +/// int count; +/// char array[] __attribute__((counted_by(count))); +/// }; +/// +/// If we have an expression like \p p->ptr->array[index], we want the +/// \p MemberExpr for \p p->ptr instead of \p p. +class StructAccessBase + : public ConstStmtVisitor { + const RecordDecl *ExpectedRD; + + bool IsExpectedRecordDecl(const Expr *E) const { + QualType Ty = E->getType(); + if (Ty->isPointerType()) + Ty = Ty->getPointeeType(); + return ExpectedRD == Ty->getAsRecordDecl(); + } + +public: + StructAccessBase(const RecordDecl *ExpectedRD) : ExpectedRD(ExpectedRD) {} + + //===--------------------------------------------------------------------===// + // Visitor Methods + //===--------------------------------------------------------------------===// + + // NOTE: If we build C++ support for counted_by, then we'll have to handle + // horrors like this: + // + // struct S { + // int x, y; + // int blah[] __attribute__((counted_by(x))); + // } s; + // + // int foo(int index, int val) { + // int (S::*IHatePMDs)[] = &S::blah; + // (s.*IHatePMDs)[index] = val; + // } + + const Expr *Visit(const Expr *E) { + return ConstStmtVisitor::Visit(E); + } + + const Expr *VisitStmt(const Stmt *S) { return nullptr; } + + // These are the types we expect to return (in order of most to least + // likely): + // + // 1. DeclRefExpr - This is the expression for the base of the structure. + // It's exactly what we want to build an access to the \p counted_by + // field. + // 2. MemberExpr - This is the expression that has the same \p RecordDecl + // as the flexble array member's lexical enclosing \p RecordDecl. This + // allows us to catch things like: "p->p->array" + // 3. CompoundLiteralExpr - This is for people who create something + // heretical like (struct foo has a flexible array member): + // + // (struct foo){ 1, 2 }.blah[idx]; + const Expr *VisitDeclRefExpr(const DeclRefExpr *E) { + return IsExpectedRecordDecl(E) ? E : nullptr; + } + const Expr *VisitMemberExpr(const MemberExpr *E) { + if (IsExpectedRecordDecl(E) && E->isArrow()) + return E; + const Expr *Res = Visit(E->getBase()); + return !Res && IsExpectedRecordDecl(E) ? E : Res; + } + const Expr *VisitCompoundLiteralExpr(const CompoundLiteralExpr *E) { + return IsExpectedRecordDecl(E) ? E : nullptr; + } + const Expr *VisitCallExpr(const CallExpr *E) { + return IsExpectedRecordDecl(E) ? E : nullptr; + } + + const Expr *VisitArraySubscriptExpr(const ArraySubscriptExpr *E) { + if (IsExpectedRecordDecl(E)) + return E; + return Visit(E->getBase()); + } + const Expr *VisitCastExpr(const CastExpr *E) { + return Visit(E->getSubExpr()); + } + const Expr *VisitParenExpr(const ParenExpr *E) { + return Visit(E->getSubExpr()); + } + const Expr *VisitUnaryAddrOf(const UnaryOperator *E) { + return Visit(E->getSubExpr()); + } + const Expr *VisitUnaryDeref(const UnaryOperator *E) { + return Visit(E->getSubExpr()); + } +}; + +} // end anonymous namespace + +using RecIndicesTy = + SmallVector, 8>; + +static bool getGEPIndicesToField(CodeGenFunction &CGF, const RecordDecl *RD, + const FieldDecl *FD, RecIndicesTy &Indices) { + const CGRecordLayout &Layout = CGF.CGM.getTypes().getCGRecordLayout(RD); + int64_t FieldNo = -1; + for (const Decl *D : RD->decls()) { + if (const auto *Field = dyn_cast(D)) { + FieldNo = Layout.getLLVMFieldNo(Field); + if (FD == Field) { + Indices.emplace_back(std::make_pair(RD, CGF.Builder.getInt32(FieldNo))); + return true; + } + } + + if (const auto *Record = dyn_cast(D)) { + ++FieldNo; + if (getGEPIndicesToField(CGF, Record, FD, Indices)) { + if (RD->isUnion()) + FieldNo = 0; + Indices.emplace_back(std::make_pair(RD, CGF.Builder.getInt32(FieldNo))); + return true; + } + } + } + + return false; +} + +/// This method is typically called in contexts where we can't generate +/// side-effects, like in __builtin_dynamic_object_size. When finding +/// expressions, only choose those that have either already been emitted or can +/// be loaded without side-effects. +/// +/// - \p FAMDecl: the \p Decl for the flexible array member. It may not be +/// within the top-level struct. +/// - \p CountDecl: must be within the same non-anonymous struct as \p FAMDecl. +llvm::Value *CodeGenFunction::EmitCountedByFieldExpr( + const Expr *Base, const FieldDecl *FAMDecl, const FieldDecl *CountDecl) { + const RecordDecl *RD = CountDecl->getParent()->getOuterLexicalRecordContext(); + + // Find the base struct expr (i.e. p in p->a.b.c.d). + const Expr *StructBase = StructAccessBase(RD).Visit(Base); + if (!StructBase || StructBase->HasSideEffects(getContext())) + return nullptr; + + llvm::Value *Res = nullptr; + if (const auto *DRE = dyn_cast(StructBase)) { + Res = EmitDeclRefLValue(DRE).getPointer(*this); + Res = Builder.CreateAlignedLoad(ConvertType(DRE->getType()), Res, + getPointerAlign(), "dre.load"); + } else if (const MemberExpr *ME = dyn_cast(StructBase)) { + LValue LV = EmitMemberExpr(ME); + Address Addr = LV.getAddress(*this); + Res = Addr.getPointer(); + } else if (StructBase->getType()->isPointerType()) { + LValueBaseInfo BaseInfo; + TBAAAccessInfo TBAAInfo; + Address Addr = EmitPointerWithAlignment(StructBase, &BaseInfo, &TBAAInfo); + Res = Addr.getPointer(); + } else { + return nullptr; + } + + llvm::Value *Zero = Builder.getInt32(0); + RecIndicesTy Indices; + + getGEPIndicesToField(*this, RD, CountDecl, Indices); + + for (auto I = Indices.rbegin(), E = Indices.rend(); I != E; ++I) + Res = Builder.CreateInBoundsGEP( + ConvertType(QualType(I->first->getTypeForDecl(), 0)), Res, + {Zero, I->second}, "..counted_by.gep"); + + return Builder.CreateAlignedLoad(ConvertType(CountDecl->getType()), Res, + getIntAlign(), "..counted_by.load"); +} + +const FieldDecl *CodeGenFunction::FindCountedByField(const FieldDecl *FD) { + if (!FD || !FD->hasAttr()) + return nullptr; + + const auto *CBA = FD->getAttr(); + if (!CBA) + return nullptr; + + auto GetNonAnonStructOrUnion = + [](const RecordDecl *RD) -> const RecordDecl * { + while (RD && RD->isAnonymousStructOrUnion()) { + const auto *R = dyn_cast(RD->getDeclContext()); + if (!R) + return nullptr; + RD = R; + } + return RD; + }; + const RecordDecl *EnclosingRD = GetNonAnonStructOrUnion(FD->getParent()); + if (!EnclosingRD) + return nullptr; + + DeclarationName DName(CBA->getCountedByField()); + DeclContext::lookup_result Lookup = EnclosingRD->lookup(DName); + + if (Lookup.empty()) + return nullptr; + + const NamedDecl *ND = Lookup.front(); + if (const auto *IFD = dyn_cast(ND)) + ND = IFD->getAnonField(); + + return dyn_cast(ND); +} + void CodeGenFunction::EmitBoundsCheck(const Expr *E, const Expr *Base, llvm::Value *Index, QualType IndexType, bool Accessed) { assert(SanOpts.has(SanitizerKind::ArrayBounds) && "should not be called unless adding bounds checks"); - SanitizerScope SanScope(this); - const LangOptions::StrictFlexArraysLevelKind StrictFlexArraysLevel = - getLangOpts().getStrictFlexArraysLevel(); - + getLangOpts().getStrictFlexArraysLevel(); QualType IndexedType; llvm::Value *Bound = getArrayIndexingBound(*this, Base, IndexedType, StrictFlexArraysLevel); + + EmitBoundsCheckImpl(E, Bound, Index, IndexType, IndexedType, Accessed); +} + +void CodeGenFunction::EmitBoundsCheckImpl(const Expr *E, llvm::Value *Bound, + llvm::Value *Index, + QualType IndexType, + QualType IndexedType, bool Accessed) { if (!Bound) return; + SanitizerScope SanScope(this); + bool IndexSigned = IndexType->isSignedIntegerOrEnumerationType(); llvm::Value *IndexVal = Builder.CreateIntCast(Index, SizeTy, IndexSigned); llvm::Value *BoundVal = Builder.CreateIntCast(Bound, SizeTy, false); @@ -975,7 +1208,6 @@ void CodeGenFunction::EmitBoundsCheck(const Expr *E, const Expr *Base, SanitizerHandler::OutOfBounds, StaticData, Index); } - CodeGenFunction::ComplexPairTy CodeGenFunction:: EmitComplexPrePostIncDec(const UnaryOperator *E, LValue LV, bool isInc, bool isPre) { @@ -3823,6 +4055,61 @@ static Address emitArraySubscriptGEP(CodeGenFunction &CGF, Address addr, return Address(eltPtr, CGF.ConvertTypeForMem(eltType), eltAlign); } +/// The offset of a field from the beginning of the record. +static bool getFieldOffsetInBits(CodeGenFunction &CGF, const RecordDecl *RD, + const FieldDecl *FD, int64_t &Offset) { + ASTContext &Ctx = CGF.getContext(); + const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(RD); + unsigned FieldNo = 0; + + for (const Decl *D : RD->decls()) { + if (const auto *Record = dyn_cast(D)) + if (getFieldOffsetInBits(CGF, Record, FD, Offset)) { + Offset += Layout.getFieldOffset(FieldNo); + return true; + } + + if (const auto *Field = dyn_cast(D)) + if (FD == Field) { + Offset += Layout.getFieldOffset(FieldNo); + return true; + } + + if (isa(D)) + ++FieldNo; + } + + return false; +} + +/// Returns the relative offset difference between \p FD1 and \p FD2. +/// \code +/// offsetof(struct foo, FD1) - offsetof(struct foo, FD2) +/// \endcode +/// Both fields must be within the same struct. +static std::optional getOffsetDifferenceInBits(CodeGenFunction &CGF, + const FieldDecl *FD1, + const FieldDecl *FD2) { + const RecordDecl *FD1OuterRec = + FD1->getParent()->getOuterLexicalRecordContext(); + const RecordDecl *FD2OuterRec = + FD2->getParent()->getOuterLexicalRecordContext(); + + if (FD1OuterRec != FD2OuterRec) + // Fields must be within the same RecordDecl. + return std::optional(); + + int64_t FD1Offset = 0; + if (!getFieldOffsetInBits(CGF, FD1OuterRec, FD1, FD1Offset)) + return std::optional(); + + int64_t FD2Offset = 0; + if (!getFieldOffsetInBits(CGF, FD2OuterRec, FD2, FD2Offset)) + return std::optional(); + + return std::make_optional(FD1Offset - FD2Offset); +} + LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E, bool Accessed) { // The index must always be an integer, which is not an aggregate. Emit it @@ -3950,6 +4237,47 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E, ArrayLV = EmitLValue(Array); auto *Idx = EmitIdxAfterBase(/*Promote*/true); + if (SanOpts.has(SanitizerKind::ArrayBounds)) { + // If the array being accessed has a "counted_by" attribute, generate + // bounds checking code. The "count" field is at the top level of the + // struct or in an anonymous struct, that's also at the top level. Future + // expansions may allow the "count" to reside at any place in the struct, + // but the value of "counted_by" will be a "simple" path to the count, + // i.e. "a.b.count", so we shouldn't need the full force of EmitLValue or + // similar to emit the correct GEP. + const LangOptions::StrictFlexArraysLevelKind StrictFlexArraysLevel = + getLangOpts().getStrictFlexArraysLevel(); + + if (const auto *ME = dyn_cast(Array); + ME && + ME->isFlexibleArrayMemberLike(getContext(), StrictFlexArraysLevel) && + ME->getMemberDecl()->hasAttr()) { + const FieldDecl *FAMDecl = dyn_cast(ME->getMemberDecl()); + if (const FieldDecl *CountFD = FindCountedByField(FAMDecl)) { + if (std::optional Diff = + getOffsetDifferenceInBits(*this, CountFD, FAMDecl)) { + CharUnits OffsetDiff = CGM.getContext().toCharUnitsFromBits(*Diff); + + // Create a GEP with a byte offset between the FAM and count and + // use that to load the count value. + Addr = Builder.CreatePointerBitCastOrAddrSpaceCast( + ArrayLV.getAddress(*this), Int8PtrTy, Int8Ty); + + llvm::Type *CountTy = ConvertType(CountFD->getType()); + llvm::Value *Res = Builder.CreateInBoundsGEP( + Int8Ty, Addr.getPointer(), + Builder.getInt32(OffsetDiff.getQuantity()), ".counted_by.gep"); + Res = Builder.CreateAlignedLoad(CountTy, Res, getIntAlign(), + ".counted_by.load"); + + // Now emit the bounds checking. + EmitBoundsCheckImpl(E, Res, Idx, E->getIdx()->getType(), + Array->getType(), Accessed); + } + } + } + } + // Propagate the alignment from the array itself to the result. QualType arrayType = Array->getType(); Addr = emitArraySubscriptGEP( diff --git a/clang/lib/CodeGen/CGObjCGNU.cpp b/clang/lib/CodeGen/CGObjCGNU.cpp index 4ca1a8cce64d895d7ddaf914bf1224bb67d1275b..9cc7f32815f7e9e27a894bc8f315ef2e8d94f0ea 100644 --- a/clang/lib/CodeGen/CGObjCGNU.cpp +++ b/clang/lib/CodeGen/CGObjCGNU.cpp @@ -168,6 +168,8 @@ protected: /// Does the current target use SEH-based exceptions? False implies /// Itanium-style DWARF unwinding. bool usesSEHExceptions; + /// Does the current target uses C++-based exceptions? + bool usesCxxExceptions; /// Helper to check if we are targeting a specific runtime version or later. bool isRuntime(ObjCRuntime::Kind kind, unsigned major, unsigned minor=0) { @@ -819,12 +821,18 @@ class CGObjCGNUstep : public CGObjCGNU { SlotLookupSuperFn.init(&CGM, "objc_slot_lookup_super", SlotTy, PtrToObjCSuperTy, SelectorTy); // If we're in ObjC++ mode, then we want to make - if (usesSEHExceptions) { - llvm::Type *VoidTy = llvm::Type::getVoidTy(VMContext); - // void objc_exception_rethrow(void) - ExceptionReThrowFn.init(&CGM, "objc_exception_rethrow", VoidTy); + llvm::Type *VoidTy = llvm::Type::getVoidTy(VMContext); + if (usesCxxExceptions) { + // void *__cxa_begin_catch(void *e) + EnterCatchFn.init(&CGM, "__cxa_begin_catch", PtrTy, PtrTy); + // void __cxa_end_catch(void) + ExitCatchFn.init(&CGM, "__cxa_end_catch", VoidTy); + // void objc_exception_rethrow(void*) + ExceptionReThrowFn.init(&CGM, "__cxa_rethrow", PtrTy); + } else if (usesSEHExceptions) { + // void objc_exception_rethrow(void) + ExceptionReThrowFn.init(&CGM, "objc_exception_rethrow", VoidTy); } else if (CGM.getLangOpts().CPlusPlus) { - llvm::Type *VoidTy = llvm::Type::getVoidTy(VMContext); // void *__cxa_begin_catch(void *e) EnterCatchFn.init(&CGM, "__cxa_begin_catch", PtrTy, PtrTy); // void __cxa_end_catch(void) @@ -833,7 +841,6 @@ class CGObjCGNUstep : public CGObjCGNU { ExceptionReThrowFn.init(&CGM, "_Unwind_Resume_or_Rethrow", VoidTy, PtrTy); } else if (R.getVersion() >= VersionTuple(1, 7)) { - llvm::Type *VoidTy = llvm::Type::getVoidTy(VMContext); // id objc_begin_catch(void *e) EnterCatchFn.init(&CGM, "objc_begin_catch", IdTy, PtrTy); // void objc_end_catch(void) @@ -841,7 +848,6 @@ class CGObjCGNUstep : public CGObjCGNU { // void _Unwind_Resume_or_Rethrow(void*) ExceptionReThrowFn.init(&CGM, "objc_exception_rethrow", VoidTy, PtrTy); } - llvm::Type *VoidTy = llvm::Type::getVoidTy(VMContext); SetPropertyAtomic.init(&CGM, "objc_setProperty_atomic", VoidTy, IdTy, SelectorTy, IdTy, PtrDiffTy); SetPropertyAtomicCopy.init(&CGM, "objc_setProperty_atomic_copy", VoidTy, @@ -1425,12 +1431,24 @@ class CGObjCGNUstep2 : public CGObjCGNUstep { const std::string &TypeEncoding) override { return GetConstantSelector(Sel, TypeEncoding); } + std::string GetSymbolNameForTypeEncoding(const std::string &TypeEncoding) { + std::string MangledTypes = std::string(TypeEncoding); + // @ is used as a special character in ELF symbol names (used for symbol + // versioning), so mangle the name to not include it. Replace it with a + // character that is not a valid type encoding character (and, being + // non-printable, never will be!) + if (CGM.getTriple().isOSBinFormatELF()) + std::replace(MangledTypes.begin(), MangledTypes.end(), '@', '\1'); + // = in dll exported names causes lld to fail when linking on Windows. + if (CGM.getTriple().isOSWindows()) + std::replace(MangledTypes.begin(), MangledTypes.end(), '=', '\2'); + return MangledTypes; + } llvm::Constant *GetTypeString(llvm::StringRef TypeEncoding) { if (TypeEncoding.empty()) return NULLPtr; - std::string MangledTypes = std::string(TypeEncoding); - std::replace(MangledTypes.begin(), MangledTypes.end(), - '@', '\1'); + std::string MangledTypes = + GetSymbolNameForTypeEncoding(std::string(TypeEncoding)); std::string TypesVarName = ".objc_sel_types_" + MangledTypes; auto *TypesGlobal = TheModule.getGlobalVariable(TypesVarName); if (!TypesGlobal) { @@ -1447,13 +1465,7 @@ class CGObjCGNUstep2 : public CGObjCGNUstep { } llvm::Constant *GetConstantSelector(Selector Sel, const std::string &TypeEncoding) override { - // @ is used as a special character in symbol names (used for symbol - // versioning), so mangle the name to not include it. Replace it with a - // character that is not a valid type encoding character (and, being - // non-printable, never will be!) - std::string MangledTypes = TypeEncoding; - std::replace(MangledTypes.begin(), MangledTypes.end(), - '@', '\1'); + std::string MangledTypes = GetSymbolNameForTypeEncoding(TypeEncoding); auto SelVarName = (StringRef(".objc_selector_") + Sel.getAsString() + "_" + MangledTypes).str(); if (auto *GV = TheModule.getNamedGlobal(SelVarName)) @@ -1665,9 +1677,7 @@ class CGObjCGNUstep2 : public CGObjCGNUstep { const ObjCIvarDecl *Ivar) override { std::string TypeEncoding; CGM.getContext().getObjCEncodingForType(Ivar->getType(), TypeEncoding); - // Prevent the @ from being interpreted as a symbol version. - std::replace(TypeEncoding.begin(), TypeEncoding.end(), - '@', '\1'); + TypeEncoding = GetSymbolNameForTypeEncoding(TypeEncoding); const std::string Name = "__objc_ivar_offset_" + ID->getNameAsString() + '.' + Ivar->getNameAsString() + '.' + TypeEncoding; return Name; @@ -1851,6 +1861,8 @@ class CGObjCGNUstep2 : public CGObjCGNUstep { llvm::GlobalValue::HiddenVisibility : llvm::GlobalValue::DefaultVisibility; OffsetVar->setVisibility(ivarVisibility); + if (ivarVisibility != llvm::GlobalValue::HiddenVisibility) + CGM.setGVProperties(OffsetVar, OID->getClassInterface()); ivarBuilder.add(OffsetVar); // Ivar size ivarBuilder.addInt(Int32Ty, @@ -2124,6 +2136,9 @@ CGObjCGNU::CGObjCGNU(CodeGenModule &cgm, unsigned runtimeABIVersion, msgSendMDKind = VMContext.getMDKindID("GNUObjCMessageSend"); usesSEHExceptions = cgm.getContext().getTargetInfo().getTriple().isWindowsMSVCEnvironment(); + usesCxxExceptions = + cgm.getContext().getTargetInfo().getTriple().isOSCygMing() && + isRuntime(ObjCRuntime::GNUstep, 2); CodeGenTypes &Types = CGM.getTypes(); IntTy = cast( @@ -2210,7 +2225,10 @@ CGObjCGNU::CGObjCGNU(CodeGenModule &cgm, unsigned runtimeABIVersion, // void objc_exception_throw(id); ExceptionThrowFn.init(&CGM, "objc_exception_throw", VoidTy, IdTy); - ExceptionReThrowFn.init(&CGM, "objc_exception_throw", VoidTy, IdTy); + ExceptionReThrowFn.init(&CGM, + usesCxxExceptions ? "objc_exception_rethrow" + : "objc_exception_throw", + VoidTy, IdTy); // int objc_sync_enter(id); SyncEnterFn.init(&CGM, "objc_sync_enter", IntTy, IdTy); // int objc_sync_exit(id); @@ -2387,7 +2405,7 @@ llvm::Constant *CGObjCGNUstep::GetEHType(QualType T) { if (usesSEHExceptions) return CGM.getCXXABI().getAddrOfRTTIDescriptor(T); - if (!CGM.getLangOpts().CPlusPlus) + if (!CGM.getLangOpts().CPlusPlus && !usesCxxExceptions) return CGObjCGNU::GetEHType(T); // For Objective-C++, we want to provide the ability to catch both C++ and @@ -3993,7 +4011,7 @@ void CGObjCGNU::EmitThrowStmt(CodeGenFunction &CGF, ExceptionAsObject = CGF.ObjCEHValueStack.back(); isRethrow = true; } - if (isRethrow && usesSEHExceptions) { + if (isRethrow && (usesSEHExceptions || usesCxxExceptions)) { // For SEH, ExceptionAsObject may be undef, because the catch handler is // not passed it for catchalls and so it is not visible to the catch // funclet. The real thrown object will still be live on the stack at this @@ -4003,8 +4021,7 @@ void CGObjCGNU::EmitThrowStmt(CodeGenFunction &CGF, // argument. llvm::CallBase *Throw = CGF.EmitRuntimeCallOrInvoke(ExceptionReThrowFn); Throw->setDoesNotReturn(); - } - else { + } else { ExceptionAsObject = CGF.Builder.CreateBitCast(ExceptionAsObject, IdTy); llvm::CallBase *Throw = CGF.EmitRuntimeCallOrInvoke(ExceptionThrowFn, ExceptionAsObject); diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 07c7678df87eb8c5d257583bfd2f370934696deb..143ad64e8816b12ee5297ab6689ca058b6e1aa96 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -3073,6 +3073,25 @@ public: /// this expression is used as an lvalue, for instance in "&Arr[Idx]". void EmitBoundsCheck(const Expr *E, const Expr *Base, llvm::Value *Index, QualType IndexType, bool Accessed); + void EmitBoundsCheckImpl(const Expr *E, llvm::Value *Bound, + llvm::Value *Index, QualType IndexType, + QualType IndexedType, bool Accessed); + + // Find a struct's flexible array member. It may be embedded inside multiple + // sub-structs, but must still be the last field. + const FieldDecl *FindFlexibleArrayMemberField(ASTContext &Ctx, + const RecordDecl *RD, + StringRef Name, + uint64_t &Offset); + + /// Find the FieldDecl specified in a FAM's "counted_by" attribute. Returns + /// \p nullptr if either the attribute or the field doesn't exist. + const FieldDecl *FindCountedByField(const FieldDecl *FD); + + /// Build an expression accessing the "counted_by" field. + llvm::Value *EmitCountedByFieldExpr(const Expr *Base, + const FieldDecl *FAMDecl, + const FieldDecl *CountDecl); llvm::Value *EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV, bool isInc, bool isPre); @@ -4873,6 +4892,9 @@ private: llvm::Value *EmittedE, bool IsDynamic); + llvm::Value *emitFlexibleArrayMemberSize(const Expr *E, unsigned Type, + llvm::IntegerType *ResType); + void emitZeroOrPatternForAutoVarInit(QualType type, const VarDecl &D, Address Loc); diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 4fd32337cccc09308aa65c363427ecc9e1f4a9d5..0cfe7a0133b7e32e1ce72214c219280109c8ff00 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -1109,6 +1109,8 @@ void CodeGenModule::Release() { if (LangOpts.BranchProtectionPAuthLR) getModule().addModuleFlag(llvm::Module::Min, "branch-protection-pauth-lr", 1); + if (LangOpts.GuardedControlStack) + getModule().addModuleFlag(llvm::Module::Min, "guarded-control-stack", 1); if (LangOpts.hasSignReturnAddress()) getModule().addModuleFlag(llvm::Module::Min, "sign-return-address", 1); if (LangOpts.isSignReturnAddressScopeAll()) @@ -1199,7 +1201,7 @@ void CodeGenModule::Release() { llvm::CodeModel::Model codeModel = static_cast(CM); getModule().setCodeModel(codeModel); - if (CM == llvm::CodeModel::Medium && + if ((CM == llvm::CodeModel::Medium || CM == llvm::CodeModel::Large) && Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86_64) { getModule().setLargeDataThreshold(getCodeGenOpts().LargeDataThreshold); diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp index bf227386a71b78e74d395810d7714b00cbf6ba20..b245abd16c3f4a29b55e645f9fce473193a2ea1d 100644 --- a/clang/lib/CodeGen/CoverageMappingGen.cpp +++ b/clang/lib/CodeGen/CoverageMappingGen.cpp @@ -1712,7 +1712,11 @@ struct CounterCoverageMappingBuilder extendRegion(S->getCond()); Counter ParentCount = getRegion().getCounter(); - Counter ThenCount = getRegionCounter(S); + + // If this is "if !consteval" the then-branch will never be taken, we don't + // need to change counter + Counter ThenCount = + S->isNegatedConsteval() ? ParentCount : getRegionCounter(S); if (!S->isConsteval()) { // Emitting a counter for the condition makes it easier to interpret the @@ -1729,7 +1733,12 @@ struct CounterCoverageMappingBuilder extendRegion(S->getThen()); Counter OutCount = propagateCounts(ThenCount, S->getThen()); - Counter ElseCount = subtractCounters(ParentCount, ThenCount); + // If this is "if consteval" the else-branch will never be taken, we don't + // need to change counter + Counter ElseCount = S->isNonNegatedConsteval() + ? ParentCount + : subtractCounters(ParentCount, ThenCount); + if (const Stmt *Else = S->getElse()) { bool ThenHasTerminateStmt = HasTerminateStmt; HasTerminateStmt = false; diff --git a/clang/lib/CodeGen/Targets/AArch64.cpp b/clang/lib/CodeGen/Targets/AArch64.cpp index 7102d190fe008bd47fa74933e39a8739b4c19ff5..ee7f95084d2e0b6628778a0189649729ba800a5d 100644 --- a/clang/lib/CodeGen/Targets/AArch64.cpp +++ b/clang/lib/CodeGen/Targets/AArch64.cpp @@ -138,6 +138,8 @@ public: BPI.BranchTargetEnforcement ? "true" : "false"); Fn->addFnAttr("branch-protection-pauth-lr", BPI.BranchProtectionPAuthLR ? "true" : "false"); + Fn->addFnAttr("guarded-control-stack", + BPI.GuardedControlStack ? "true" : "false"); } bool isScalarizableAsmOperand(CodeGen::CodeGenFunction &CGF, diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index 9b2f2a374809835e03209ae1c8ceda1ec6265aa1..1889ea28079df10dc49123c7fae749630a68610e 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -1430,6 +1430,17 @@ Compilation *Driver::BuildCompilation(ArrayRef ArgList) { const ToolChain &TC = getToolChain( *UArgs, computeTargetTriple(*this, TargetTriple, *UArgs)); + if (TC.getTriple().isAndroid()) { + llvm::Triple Triple = TC.getTriple(); + StringRef TripleVersionName = Triple.getEnvironmentVersionString(); + + if (Triple.getEnvironmentVersion().empty() && TripleVersionName != "") { + Diags.Report(diag::err_drv_triple_version_invalid) + << TripleVersionName << TC.getTripleString(); + ContainsError = true; + } + } + // Report warning when arm64EC option is overridden by specified target if ((TC.getTriple().getArch() != llvm::Triple::aarch64 || TC.getTriple().getSubArch() != llvm::Triple::AArch64SubArch_arm64ec) && diff --git a/clang/lib/Driver/SanitizerArgs.cpp b/clang/lib/Driver/SanitizerArgs.cpp index ad68c086b71790cbf4927e691e7687a5e901ffd7..9d6ea371f9f6dd529382bc9e205c88c6008e499c 100644 --- a/clang/lib/Driver/SanitizerArgs.cpp +++ b/clang/lib/Driver/SanitizerArgs.cpp @@ -39,8 +39,6 @@ static const SanitizerMask NotAllowedWithTrap = SanitizerKind::Vptr; static const SanitizerMask NotAllowedWithMinimalRuntime = SanitizerKind::Vptr; static const SanitizerMask NotAllowedWithExecuteOnly = SanitizerKind::Function | SanitizerKind::KCFI; -static const SanitizerMask RequiresPIE = - SanitizerKind::DataFlow | SanitizerKind::Scudo; static const SanitizerMask NeedsUnwindTables = SanitizerKind::Address | SanitizerKind::HWAddress | SanitizerKind::Thread | SanitizerKind::Memory | SanitizerKind::DataFlow; @@ -303,9 +301,7 @@ bool SanitizerArgs::needsCfiDiagRt() const { CfiCrossDso && !ImplicitCfiRuntime; } -bool SanitizerArgs::requiresPIE() const { - return NeedPIE || (Sanitizers.Mask & RequiresPIE); -} +bool SanitizerArgs::requiresPIE() const { return NeedPIE; } bool SanitizerArgs::needsUnwindTables() const { return static_cast(Sanitizers.Mask & NeedsUnwindTables); @@ -699,8 +695,6 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC, MsanParamRetval = Args.hasFlag( options::OPT_fsanitize_memory_param_retval, options::OPT_fno_sanitize_memory_param_retval, MsanParamRetval); - NeedPIE |= !(TC.getTriple().isOSLinux() && - TC.getTriple().getArch() == llvm::Triple::x86_64); } else if (AllAddedKinds & SanitizerKind::KernelMemory) { MsanUseAfterDtor = false; MsanParamRetval = Args.hasFlag( diff --git a/clang/lib/Driver/ToolChains/Arch/RISCV.cpp b/clang/lib/Driver/ToolChains/Arch/RISCV.cpp index 0717e3b813e1e23d14882485efd6cd4540536899..16a8b3cc42bab4c1520d1ac53d4dbe25a4a3c4a4 100644 --- a/clang/lib/Driver/ToolChains/Arch/RISCV.cpp +++ b/clang/lib/Driver/ToolChains/Arch/RISCV.cpp @@ -42,9 +42,9 @@ static bool getArchFeatures(const Driver &D, StringRef Arch, return false; } - (*ISAInfo)->toFeatures( - Features, [&Args](const Twine &Str) { return Args.MakeArgString(Str); }, - /*AddAllExtensions=*/true); + for (const std::string &Str : (*ISAInfo)->toFeatures(/*AddAllExtension=*/true, + /*IgnoreUnknown=*/false)) + Features.push_back(Args.MakeArgString(Str)); if (EnableExperimentalExtensions) Features.push_back(Args.MakeArgString("+experimental")); diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 2d8ef841d4f6be6709a6fbb9d8c54bd950e3914b..9edae3fec91a87f67748d37ccbd4566b09163075 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -1508,7 +1508,7 @@ static void CollectARMPACBTIOptions(const ToolChain &TC, const ArgList &Args, << Triple.getArchName(); StringRef Scope, Key; - bool IndirectBranches, BranchProtectionPAuthLR; + bool IndirectBranches, BranchProtectionPAuthLR, GuardedControlStack; if (A->getOption().matches(options::OPT_msign_return_address_EQ)) { Scope = A->getValue(); @@ -1518,6 +1518,7 @@ static void CollectARMPACBTIOptions(const ToolChain &TC, const ArgList &Args, Key = "a_key"; IndirectBranches = false; BranchProtectionPAuthLR = false; + GuardedControlStack = false; } else { StringRef DiagMsg; llvm::ARM::ParsedBranchProtection PBP; @@ -1531,6 +1532,7 @@ static void CollectARMPACBTIOptions(const ToolChain &TC, const ArgList &Args, Key = PBP.Key; BranchProtectionPAuthLR = PBP.BranchProtectionPAuthLR; IndirectBranches = PBP.BranchTargetEnforcement; + GuardedControlStack = PBP.GuardedControlStack; } CmdArgs.push_back( @@ -1543,6 +1545,8 @@ static void CollectARMPACBTIOptions(const ToolChain &TC, const ArgList &Args, Args.MakeArgString(Twine("-mbranch-protection-pauth-lr"))); if (IndirectBranches) CmdArgs.push_back("-mbranch-target-enforce"); + if (GuardedControlStack) + CmdArgs.push_back("-mguarded-control-stack"); } void Clang::AddARMTargetArgs(const llvm::Triple &Triple, const ArgList &Args, @@ -5748,20 +5752,24 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, } } - if (Arg *A = Args.getLastArg(options::OPT_mlarge_data_threshold_EQ)) { - if (!Triple.isX86()) { - D.Diag(diag::err_drv_unsupported_opt_for_target) - << A->getOption().getName() << TripleStr; - } else { - bool IsMediumCM = false; - if (Arg *A = Args.getLastArg(options::OPT_mcmodel_EQ)) - IsMediumCM = StringRef(A->getValue()) == "medium"; - if (!IsMediumCM) { + if (Triple.getArch() == llvm::Triple::x86_64) { + bool IsMediumCM = false; + bool IsLargeCM = false; + if (Arg *A = Args.getLastArg(options::OPT_mcmodel_EQ)) { + IsMediumCM = StringRef(A->getValue()) == "medium"; + IsLargeCM = StringRef(A->getValue()) == "large"; + } + if (Arg *A = Args.getLastArg(options::OPT_mlarge_data_threshold_EQ)) { + if (!IsMediumCM && !IsLargeCM) { D.Diag(diag::warn_drv_large_data_threshold_invalid_code_model) << A->getOption().getRenderName(); } else { A->render(Args, CmdArgs); } + } else if (IsMediumCM) { + CmdArgs.push_back("-mlarge-data-threshold=65536"); + } else if (IsLargeCM) { + CmdArgs.push_back("-mlarge-data-threshold=0"); } } diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp index 2340191ca97d9876bcdc9c979939b40f0c66d754..385f66f3782bc1ab14ccaf65a84e6c5332e01f94 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -736,6 +736,8 @@ void tools::addLTOOptions(const ToolChain &ToolChain, const ArgList &Args, const bool IsAMDGCN = ToolChain.getTriple().isAMDGCN(); const char *Linker = Args.MakeArgString(ToolChain.GetLinkerPath()); const Driver &D = ToolChain.getDriver(); + const bool IsFatLTO = Args.hasArg(options::OPT_ffat_lto_objects); + const bool IsUnifiedLTO = Args.hasArg(options::OPT_funified_lto); if (llvm::sys::path::filename(Linker) != "ld.lld" && llvm::sys::path::stem(Linker) != "ld.lld" && !ToolChain.getTriple().isOSOpenBSD()) { @@ -765,7 +767,7 @@ void tools::addLTOOptions(const ToolChain &ToolChain, const ArgList &Args, } else { // Tell LLD to find and use .llvm.lto section in regular relocatable object // files - if (Args.hasArg(options::OPT_ffat_lto_objects)) + if (IsFatLTO) CmdArgs.push_back("--fat-lto-objects"); } @@ -825,7 +827,8 @@ void tools::addLTOOptions(const ToolChain &ToolChain, const ArgList &Args, // Matrix intrinsic lowering happens at link time with ThinLTO. Enable // LowerMatrixIntrinsicsPass, which is transitively called by // buildThinLTODefaultPipeline under EnableMatrix. - if (IsThinLTO && Args.hasArg(options::OPT_fenable_matrix)) + if ((IsThinLTO || IsFatLTO || IsUnifiedLTO) && + Args.hasArg(options::OPT_fenable_matrix)) CmdArgs.push_back( Args.MakeArgString(Twine(PluginOptPrefix) + "-enable-matrix")); diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp index 41eaad3bbad0a37f1d191fc71facbc183286314a..03d68c3df7fb374195341d3d5128d20b17e9906e 100644 --- a/clang/lib/Driver/ToolChains/Flang.cpp +++ b/clang/lib/Driver/ToolChains/Flang.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "Flang.h" +#include "Arch/RISCV.h" #include "CommonArgs.h" #include "clang/Basic/CodeGenOptions.h" @@ -14,6 +15,8 @@ #include "llvm/Frontend/Debug/Options.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" +#include "llvm/Support/RISCVISAInfo.h" +#include "llvm/TargetParser/RISCVTargetParser.h" #include @@ -203,6 +206,51 @@ void Flang::AddAArch64TargetArgs(const ArgList &Args, } } +void Flang::AddRISCVTargetArgs(const ArgList &Args, + ArgStringList &CmdArgs) const { + const llvm::Triple &Triple = getToolChain().getTriple(); + // Handle -mrvv-vector-bits= + if (Arg *A = Args.getLastArg(options::OPT_mrvv_vector_bits_EQ)) { + StringRef Val = A->getValue(); + const Driver &D = getToolChain().getDriver(); + + // Get minimum VLen from march. + unsigned MinVLen = 0; + StringRef Arch = riscv::getRISCVArch(Args, Triple); + auto ISAInfo = llvm::RISCVISAInfo::parseArchString( + Arch, /*EnableExperimentalExtensions*/ true); + // Ignore parsing error. + if (!errorToBool(ISAInfo.takeError())) + MinVLen = (*ISAInfo)->getMinVLen(); + + // If the value is "zvl", use MinVLen from march. Otherwise, try to parse + // as integer as long as we have a MinVLen. + unsigned Bits = 0; + if (Val.equals("zvl") && MinVLen >= llvm::RISCV::RVVBitsPerBlock) { + Bits = MinVLen; + } else if (!Val.getAsInteger(10, Bits)) { + // Only accept power of 2 values beteen RVVBitsPerBlock and 65536 that + // at least MinVLen. + if (Bits < MinVLen || Bits < llvm::RISCV::RVVBitsPerBlock || + Bits > 65536 || !llvm::isPowerOf2_32(Bits)) + Bits = 0; + } + + // If we got a valid value try to use it. + if (Bits != 0) { + unsigned VScaleMin = Bits / llvm::RISCV::RVVBitsPerBlock; + CmdArgs.push_back( + Args.MakeArgString("-mvscale-max=" + llvm::Twine(VScaleMin))); + CmdArgs.push_back( + Args.MakeArgString("-mvscale-min=" + llvm::Twine(VScaleMin))); + } else if (!Val.equals("scalable")) { + // Handle the unsupported values passed to mrvv-vector-bits. + D.Diag(diag::err_drv_unsupported_option_argument) + << A->getSpelling() << Val; + } + } +} + static void addVSDefines(const ToolChain &TC, const ArgList &Args, ArgStringList &CmdArgs) { @@ -321,6 +369,9 @@ void Flang::addTargetOptions(const ArgList &Args, AddAMDGPUTargetArgs(Args, CmdArgs); break; case llvm::Triple::riscv64: + getTargetFeatures(D, Triple, Args, CmdArgs, /*ForAs*/ false); + AddRISCVTargetArgs(Args, CmdArgs); + break; case llvm::Triple::x86_64: getTargetFeatures(D, Triple, Args, CmdArgs, /*ForAs*/ false); break; @@ -352,12 +403,10 @@ void Flang::addTargetOptions(const ArgList &Args, if (A->getValue() == StringRef{"Accelerate"}) { CmdArgs.push_back("-framework"); CmdArgs.push_back("Accelerate"); - A->render(Args, CmdArgs); } } - } else { - A->render(Args, CmdArgs); } + A->render(Args, CmdArgs); } if (Triple.isKnownWindowsMSVCEnvironment()) { @@ -428,6 +477,8 @@ void Flang::addOffloadOptions(Compilation &C, const InputInfoList &Inputs, CmdArgs.push_back("-fopenmp-assume-no-thread-state"); if (Args.hasArg(options::OPT_fopenmp_assume_no_nested_parallelism)) CmdArgs.push_back("-fopenmp-assume-no-nested-parallelism"); + if (Args.hasArg(options::OPT_nogpulib)) + CmdArgs.push_back("-nogpulib"); } } diff --git a/clang/lib/Driver/ToolChains/Flang.h b/clang/lib/Driver/ToolChains/Flang.h index 8d35080e1c0c88bfc21ac699567efce1b2040393..ec2e545a1d0b5cfb109ac506b1345c06ff0153af 100644 --- a/clang/lib/Driver/ToolChains/Flang.h +++ b/clang/lib/Driver/ToolChains/Flang.h @@ -70,6 +70,13 @@ private: void AddAMDGPUTargetArgs(const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs) const; + /// Add specific options for RISC-V target. + /// + /// \param [in] Args The list of input driver arguments + /// \param [out] CmdArgs The list of output command arguments + void AddRISCVTargetArgs(const llvm::opt::ArgList &Args, + llvm::opt::ArgStringList &CmdArgs) const; + /// Extract offload options from the driver arguments and add them to /// the command arguments. /// \param [in] C The current compilation for the driver invocation diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp b/clang/lib/Driver/ToolChains/Gnu.cpp index dd0dd13883d83acc38920e66b9fa2fdb20835ef3..5a1d40478295d6caa049539416250809f2ad60f4 100644 --- a/clang/lib/Driver/ToolChains/Gnu.cpp +++ b/clang/lib/Driver/ToolChains/Gnu.cpp @@ -2256,6 +2256,15 @@ void Generic_GCC::GCCInstallationDetector::init( return; } + // If --gcc-triple is specified use this instead of trying to + // auto-detect a triple. + if (const Arg *A = + Args.getLastArg(clang::driver::options::OPT_gcc_triple_EQ)) { + StringRef GCCTriple = A->getValue(); + CandidateTripleAliases.clear(); + CandidateTripleAliases.push_back(GCCTriple); + } + // Compute the set of prefixes for our search. SmallVector Prefixes; StringRef GCCToolchainDir = getGCCToolchainDir(Args, D.SysRoot); @@ -2664,7 +2673,9 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes( case llvm::Triple::arm: case llvm::Triple::thumb: LibDirs.append(begin(ARMLibDirs), end(ARMLibDirs)); - if (TargetTriple.getEnvironment() == llvm::Triple::GNUEABIHF) { + if (TargetTriple.getEnvironment() == llvm::Triple::GNUEABIHF || + TargetTriple.getEnvironment() == llvm::Triple::MuslEABIHF || + TargetTriple.getEnvironment() == llvm::Triple::EABIHF) { TripleAliases.append(begin(ARMHFTriples), end(ARMHFTriples)); } else { TripleAliases.append(begin(ARMTriples), end(ARMTriples)); @@ -2673,7 +2684,9 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes( case llvm::Triple::armeb: case llvm::Triple::thumbeb: LibDirs.append(begin(ARMebLibDirs), end(ARMebLibDirs)); - if (TargetTriple.getEnvironment() == llvm::Triple::GNUEABIHF) { + if (TargetTriple.getEnvironment() == llvm::Triple::GNUEABIHF || + TargetTriple.getEnvironment() == llvm::Triple::MuslEABIHF || + TargetTriple.getEnvironment() == llvm::Triple::EABIHF) { TripleAliases.append(begin(ARMebHFTriples), end(ARMebHFTriples)); } else { TripleAliases.append(begin(ARMebTriples), end(ARMebTriples)); diff --git a/clang/lib/Driver/ToolChains/Linux.cpp b/clang/lib/Driver/ToolChains/Linux.cpp index 735af54f114cef2f51d63b9c92da265a19782a1e..4300a2bdff179116703f516b6470ecd1a61e55d5 100644 --- a/clang/lib/Driver/ToolChains/Linux.cpp +++ b/clang/lib/Driver/ToolChains/Linux.cpp @@ -61,12 +61,16 @@ std::string Linux::getMultiarchTriple(const Driver &D, case llvm::Triple::thumb: if (IsAndroid) return "arm-linux-androideabi"; - if (TargetEnvironment == llvm::Triple::GNUEABIHF) + if (TargetEnvironment == llvm::Triple::GNUEABIHF || + TargetEnvironment == llvm::Triple::MuslEABIHF || + TargetEnvironment == llvm::Triple::EABIHF) return "arm-linux-gnueabihf"; return "arm-linux-gnueabi"; case llvm::Triple::armeb: case llvm::Triple::thumbeb: - if (TargetEnvironment == llvm::Triple::GNUEABIHF) + if (TargetEnvironment == llvm::Triple::GNUEABIHF || + TargetEnvironment == llvm::Triple::MuslEABIHF || + TargetEnvironment == llvm::Triple::EABIHF) return "armeb-linux-gnueabihf"; return "armeb-linux-gnueabi"; case llvm::Triple::x86: diff --git a/clang/lib/Driver/ToolChains/MinGW.cpp b/clang/lib/Driver/ToolChains/MinGW.cpp index 65512f16357d044d4cbfcda328983bf24b50fe68..18fc9d4b6807e38b40c4d78bb760364a6c7956d1 100644 --- a/clang/lib/Driver/ToolChains/MinGW.cpp +++ b/clang/lib/Driver/ToolChains/MinGW.cpp @@ -471,12 +471,23 @@ findClangRelativeSysroot(const Driver &D, const llvm::Triple &LiteralTriple, return make_error_code(std::errc::no_such_file_or_directory); } +static bool looksLikeMinGWSysroot(const std::string &Directory) { + StringRef Sep = llvm::sys::path::get_separator(); + if (!llvm::sys::fs::exists(Directory + Sep + "include" + Sep + "_mingw.h")) + return false; + if (!llvm::sys::fs::exists(Directory + Sep + "lib" + Sep + "libkernel32.a")) + return false; + return true; +} + toolchains::MinGW::MinGW(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) : ToolChain(D, Triple, Args), CudaInstallation(D, Triple, Args), RocmInstallation(D, Triple, Args) { getProgramPaths().push_back(getDriver().getInstalledDir()); + std::string InstallBase = + std::string(llvm::sys::path::parent_path(getDriver().getInstalledDir())); // The sequence for detecting a sysroot here should be kept in sync with // the testTriple function below. llvm::Triple LiteralTriple = getLiteralTriple(D, getTriple()); @@ -487,13 +498,17 @@ toolchains::MinGW::MinGW(const Driver &D, const llvm::Triple &Triple, else if (llvm::ErrorOr TargetSubdir = findClangRelativeSysroot( getDriver(), LiteralTriple, getTriple(), SubdirName)) Base = std::string(llvm::sys::path::parent_path(TargetSubdir.get())); + // If the install base of Clang seems to have mingw sysroot files directly + // in the toplevel include and lib directories, use this as base instead of + // looking for a triple prefixed GCC in the path. + else if (looksLikeMinGWSysroot(InstallBase)) + Base = InstallBase; else if (llvm::ErrorOr GPPName = findGcc(LiteralTriple, getTriple())) Base = std::string(llvm::sys::path::parent_path( llvm::sys::path::parent_path(GPPName.get()))); else - Base = std::string( - llvm::sys::path::parent_path(getDriver().getInstalledDir())); + Base = InstallBase; Base += llvm::sys::path::get_separator(); findGccLibDir(LiteralTriple); @@ -778,9 +793,15 @@ static bool testTriple(const Driver &D, const llvm::Triple &Triple, if (D.SysRoot.size()) return true; llvm::Triple LiteralTriple = getLiteralTriple(D, Triple); + std::string InstallBase = + std::string(llvm::sys::path::parent_path(D.getInstalledDir())); if (llvm::ErrorOr TargetSubdir = findClangRelativeSysroot(D, LiteralTriple, Triple, SubdirName)) return true; + // If the install base itself looks like a mingw sysroot, we'll use that + // - don't use any potentially unrelated gcc to influence what triple to use. + if (looksLikeMinGWSysroot(InstallBase)) + return false; if (llvm::ErrorOr GPPName = findGcc(LiteralTriple, Triple)) return true; // If we neither found a colocated sysroot or a matching gcc executable, diff --git a/clang/lib/Format/.clang-format b/clang/lib/Format/.clang-format index d7331b3c8cf02ef7944e83a4280476627e33b31d..f95602cab0f7fcdf5d34c485d52b65993dbb83d9 100644 --- a/clang/lib/Format/.clang-format +++ b/clang/lib/Format/.clang-format @@ -1 +1,6 @@ -BasedOnStyle: clang-format +BasedOnStyle: LLVM +InsertBraces: true +InsertNewlineAtEOF: true +LineEnding: LF +RemoveBracesLLVM: true +RemoveParentheses: ReturnStatement diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index f798d555bf9929c247ff77233c78c9c0b8abbd83..ff5ed6c306f383b91277fcbb51a607bac3e9bb3e 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -76,41 +76,39 @@ template <> struct MappingTraits { FormatStyle::AlignConsecutiveStyle( {/*Enabled=*/false, /*AcrossEmptyLines=*/false, /*AcrossComments=*/false, /*AlignCompound=*/false, - /*PadOperators=*/true})); + /*AlignFunctionPointers=*/false, /*PadOperators=*/true})); IO.enumCase(Value, "Consecutive", FormatStyle::AlignConsecutiveStyle( {/*Enabled=*/true, /*AcrossEmptyLines=*/false, /*AcrossComments=*/false, /*AlignCompound=*/false, - /*PadOperators=*/true})); + /*AlignFunctionPointers=*/false, /*PadOperators=*/true})); IO.enumCase(Value, "AcrossEmptyLines", FormatStyle::AlignConsecutiveStyle( {/*Enabled=*/true, /*AcrossEmptyLines=*/true, /*AcrossComments=*/false, /*AlignCompound=*/false, - /*PadOperators=*/true})); + /*AlignFunctionPointers=*/false, /*PadOperators=*/true})); IO.enumCase(Value, "AcrossComments", - FormatStyle::AlignConsecutiveStyle({/*Enabled=*/true, - /*AcrossEmptyLines=*/false, - /*AcrossComments=*/true, - /*AlignCompound=*/false, - /*PadOperators=*/true})); + FormatStyle::AlignConsecutiveStyle( + {/*Enabled=*/true, /*AcrossEmptyLines=*/false, + /*AcrossComments=*/true, /*AlignCompound=*/false, + /*AlignFunctionPointers=*/false, /*PadOperators=*/true})); IO.enumCase(Value, "AcrossEmptyLinesAndComments", - FormatStyle::AlignConsecutiveStyle({/*Enabled=*/true, - /*AcrossEmptyLines=*/true, - /*AcrossComments=*/true, - /*AlignCompound=*/false, - /*PadOperators=*/true})); + FormatStyle::AlignConsecutiveStyle( + {/*Enabled=*/true, /*AcrossEmptyLines=*/true, + /*AcrossComments=*/true, /*AlignCompound=*/false, + /*AlignFunctionPointers=*/false, /*PadOperators=*/true})); // For backward compatibility. IO.enumCase(Value, "true", FormatStyle::AlignConsecutiveStyle( {/*Enabled=*/true, /*AcrossEmptyLines=*/false, /*AcrossComments=*/false, /*AlignCompound=*/false, - /*PadOperators=*/true})); + /*AlignFunctionPointers=*/false, /*PadOperators=*/true})); IO.enumCase(Value, "false", FormatStyle::AlignConsecutiveStyle( {/*Enabled=*/false, /*AcrossEmptyLines=*/false, /*AcrossComments=*/false, /*AlignCompound=*/false, - /*PadOperators=*/true})); + /*AlignFunctionPointers=*/false, /*PadOperators=*/true})); } static void mapping(IO &IO, FormatStyle::AlignConsecutiveStyle &Value) { @@ -118,6 +116,7 @@ template <> struct MappingTraits { IO.mapOptional("AcrossEmptyLines", Value.AcrossEmptyLines); IO.mapOptional("AcrossComments", Value.AcrossComments); IO.mapOptional("AlignCompound", Value.AlignCompound); + IO.mapOptional("AlignFunctionPointers", Value.AlignFunctionPointers); IO.mapOptional("PadOperators", Value.PadOperators); } }; @@ -1432,6 +1431,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) { LLVMStyle.AlignConsecutiveAssignments.AcrossEmptyLines = false; LLVMStyle.AlignConsecutiveAssignments.AcrossComments = false; LLVMStyle.AlignConsecutiveAssignments.AlignCompound = false; + LLVMStyle.AlignConsecutiveAssignments.AlignFunctionPointers = false; LLVMStyle.AlignConsecutiveAssignments.PadOperators = true; LLVMStyle.AlignConsecutiveBitFields = {}; LLVMStyle.AlignConsecutiveDeclarations = {}; diff --git a/clang/lib/Format/FormatToken.cpp b/clang/lib/Format/FormatToken.cpp index 7a2df8c53952f9da6eac42dae5209cefdcf1ef19..b791c5a26bbe3ab081717acf6fd9432aaf160f09 100644 --- a/clang/lib/Format/FormatToken.cpp +++ b/clang/lib/Format/FormatToken.cpp @@ -113,8 +113,8 @@ unsigned CommaSeparatedList::formatAfterToken(LineState &State, if (!State.NextToken || !State.NextToken->Previous) return 0; - if (Formats.size() == 1) - return 0; // Handled by formatFromToken + if (Formats.size() <= 1) + return 0; // Handled by formatFromToken (1) or avoid severe penalty (0). // Ensure that we start on the opening brace. const FormatToken *LBrace = diff --git a/clang/lib/Format/FormatToken.h b/clang/lib/Format/FormatToken.h index 3f9664f8f78a3e4d3329b04cb53ff5d776bc1cd8..d5ef627f1348d31da8a47201ff1c99bb53005000 100644 --- a/clang/lib/Format/FormatToken.h +++ b/clang/lib/Format/FormatToken.h @@ -275,14 +275,15 @@ class AnnotatedLine; struct FormatToken { FormatToken() : HasUnescapedNewline(false), IsMultiline(false), IsFirst(false), - MustBreakBefore(false), IsUnterminatedLiteral(false), - CanBreakBefore(false), ClosesTemplateDeclaration(false), - StartsBinaryExpression(false), EndsBinaryExpression(false), - PartOfMultiVariableDeclStmt(false), ContinuesLineCommentSection(false), - Finalized(false), ClosesRequiresClause(false), - EndsCppAttributeGroup(false), BlockKind(BK_Unknown), - Decision(FD_Unformatted), PackingKind(PPK_Inconclusive), - TypeIsFinalized(false), Type(TT_Unknown) {} + MustBreakBefore(false), MustBreakBeforeFinalized(false), + IsUnterminatedLiteral(false), CanBreakBefore(false), + ClosesTemplateDeclaration(false), StartsBinaryExpression(false), + EndsBinaryExpression(false), PartOfMultiVariableDeclStmt(false), + ContinuesLineCommentSection(false), Finalized(false), + ClosesRequiresClause(false), EndsCppAttributeGroup(false), + BlockKind(BK_Unknown), Decision(FD_Unformatted), + PackingKind(PPK_Inconclusive), TypeIsFinalized(false), + Type(TT_Unknown) {} /// The \c Token. Token Tok; @@ -318,6 +319,10 @@ struct FormatToken { /// before the token. unsigned MustBreakBefore : 1; + /// Whether MustBreakBefore is finalized during parsing and must not + /// be reset between runs. + unsigned MustBreakBeforeFinalized : 1; + /// Set to \c true if this token is an unterminated literal. unsigned IsUnterminatedLiteral : 1; @@ -416,10 +421,14 @@ public: /// to another one please use overwriteFixedType, or even better remove the /// need to reassign the type. void setFinalizedType(TokenType T) { + if (MacroCtx && MacroCtx->Role == MR_UnexpandedArg) + return; Type = T; TypeIsFinalized = true; } void overwriteFixedType(TokenType T) { + if (MacroCtx && MacroCtx->Role == MR_UnexpandedArg) + return; TypeIsFinalized = false; setType(T); } @@ -1202,6 +1211,21 @@ struct AdditionalKeywords { kw_verilogHashHash = &IdentTable.get("##"); kw_apostrophe = &IdentTable.get("\'"); + // TableGen keywords + kw_bit = &IdentTable.get("bit"); + kw_bits = &IdentTable.get("bits"); + kw_code = &IdentTable.get("code"); + kw_dag = &IdentTable.get("dag"); + kw_def = &IdentTable.get("def"); + kw_defm = &IdentTable.get("defm"); + kw_defset = &IdentTable.get("defset"); + kw_defvar = &IdentTable.get("defvar"); + kw_dump = &IdentTable.get("dump"); + kw_include = &IdentTable.get("include"); + kw_list = &IdentTable.get("list"); + kw_multiclass = &IdentTable.get("multiclass"); + kw_then = &IdentTable.get("then"); + // Keep this at the end of the constructor to make sure everything here // is // already initialized. @@ -1294,6 +1318,27 @@ struct AdditionalKeywords { kw_wildcard, kw_wire, kw_with, kw_wor, kw_verilogHash, kw_verilogHashHash}); + + TableGenExtraKeywords = std::unordered_set({ + kw_assert, + kw_bit, + kw_bits, + kw_code, + kw_dag, + kw_def, + kw_defm, + kw_defset, + kw_defvar, + kw_dump, + kw_foreach, + kw_in, + kw_include, + kw_let, + kw_list, + kw_multiclass, + kw_string, + kw_then, + }); } // Context sensitive keywords. @@ -1539,6 +1584,21 @@ struct AdditionalKeywords { // Symbols in Verilog that don't exist in C++. IdentifierInfo *kw_apostrophe; + // TableGen keywords + IdentifierInfo *kw_bit; + IdentifierInfo *kw_bits; + IdentifierInfo *kw_code; + IdentifierInfo *kw_dag; + IdentifierInfo *kw_def; + IdentifierInfo *kw_defm; + IdentifierInfo *kw_defset; + IdentifierInfo *kw_defvar; + IdentifierInfo *kw_dump; + IdentifierInfo *kw_include; + IdentifierInfo *kw_list; + IdentifierInfo *kw_multiclass; + IdentifierInfo *kw_then; + /// Returns \c true if \p Tok is a keyword or an identifier. bool isWordLike(const FormatToken &Tok) const { // getIdentifierinfo returns non-null for keywords as well as identifiers. @@ -1811,6 +1871,27 @@ struct AdditionalKeywords { } } + bool isTableGenDefinition(const FormatToken &Tok) const { + return Tok.isOneOf(kw_def, kw_defm, kw_defset, kw_defvar, kw_multiclass, + kw_let, tok::kw_class); + } + + bool isTableGenKeyword(const FormatToken &Tok) const { + switch (Tok.Tok.getKind()) { + case tok::kw_class: + case tok::kw_else: + case tok::kw_false: + case tok::kw_if: + case tok::kw_int: + case tok::kw_true: + return true; + default: + return Tok.is(tok::identifier) && + TableGenExtraKeywords.find(Tok.Tok.getIdentifierInfo()) != + TableGenExtraKeywords.end(); + } + } + private: /// The JavaScript keywords beyond the C++ keyword set. std::unordered_set JsExtraKeywords; @@ -1820,6 +1901,9 @@ private: /// The Verilog keywords beyond the C++ keyword set. std::unordered_set VerilogExtraKeywords; + + /// The TableGen keywords beyond the C++ keyword set. + std::unordered_set TableGenExtraKeywords; }; inline bool isLineComment(const FormatToken &FormatTok) { diff --git a/clang/lib/Format/FormatTokenLexer.cpp b/clang/lib/Format/FormatTokenLexer.cpp index 61430282c6f88ca09e7e2b14c25103d66a9469c2..a1fd6dd6effe6c3640af814e3ebb5b1cb470fc95 100644 --- a/clang/lib/Format/FormatTokenLexer.cpp +++ b/clang/lib/Format/FormatTokenLexer.cpp @@ -1182,6 +1182,9 @@ FormatToken *FormatTokenLexer::getNextToken() { tok::kw_operator)) { FormatTok->Tok.setKind(tok::identifier); FormatTok->Tok.setIdentifierInfo(nullptr); + } else if (Style.isTableGen() && !Keywords.isTableGenKeyword(*FormatTok)) { + FormatTok->Tok.setKind(tok::identifier); + FormatTok->Tok.setIdentifierInfo(nullptr); } } else if (FormatTok->is(tok::greatergreater)) { FormatTok->Tok.setKind(tok::greater); diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 3ac3aa3c5e3a2258f20408bd4bed5d46602ab4a9..24ce18a64348c1dcf0c1fd36a415efd5e50fa6cb 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -2234,6 +2234,12 @@ private: if (PreviousNotConst->ClosesRequiresClause) return false; + if (Style.isTableGen()) { + // keywords such as let and def* defines names. + if (Keywords.isTableGenDefinition(*PreviousNotConst)) + return true; + } + bool IsPPKeyword = PreviousNotConst->is(tok::identifier) && PreviousNotConst->Previous && PreviousNotConst->Previous->is(tok::hash); @@ -2369,7 +2375,7 @@ private: } } - if (Tok.Next->is(tok::question)) + if (Tok.Next->isOneOf(tok::question, tok::ampamp)) return false; // `foreach((A a, B b) in someList)` should not be seen as a cast. @@ -2769,13 +2775,6 @@ public: // Consume operators with higher precedence. parse(Precedence + 1); - // Do not assign fake parenthesis to tokens that are part of an - // unexpanded macro call. The line within the macro call contains - // the parenthesis and commas, and we will not find operators within - // that structure. - if (Current && Current->MacroParent) - break; - int CurrentPrecedence = getCurrentPrecedence(); if (Precedence == CurrentPrecedence && Current && @@ -2919,6 +2918,13 @@ private: void addFakeParenthesis(FormatToken *Start, prec::Level Precedence, FormatToken *End = nullptr) { + // Do not assign fake parenthesis to tokens that are part of an + // unexpanded macro call. The line within the macro call contains + // the parenthesis and commas, and we will not find operators within + // that structure. + if (Start->MacroParent) + return; + Start->FakeLParens.push_back(Precedence); if (Precedence > prec::Unknown) Start->StartsBinaryExpression = true; @@ -4668,6 +4674,10 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line, } else if (Style.Language == FormatStyle::LK_Java) { if (Left.is(tok::r_square) && Right.is(tok::l_brace)) return true; + // spaces inside square brackets. + if (Left.is(tok::l_square) || Right.is(tok::r_square)) + return Style.SpacesInSquareBrackets; + if (Left.is(Keywords.kw_synchronized) && Right.is(tok::l_paren)) { return Style.SpaceBeforeParensOptions.AfterControlStatements || spaceRequiredBeforeParens(Right); @@ -5151,6 +5161,14 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line, return true; if (Left.IsUnterminatedLiteral) return true; + // FIXME: Breaking after newlines seems useful in general. Turn this into an + // option and recognize more cases like endl etc, and break independent of + // what comes after operator lessless. + if (Right.is(tok::lessless) && Right.Next && + Right.Next->is(tok::string_literal) && Left.is(tok::string_literal) && + Left.TokenText.ends_with("\\n\"")) { + return true; + } if (Right.is(TT_RequiresClause)) { switch (Style.RequiresClausePosition) { case FormatStyle::RCPS_OwnLine: diff --git a/clang/lib/Format/UnwrappedLineFormatter.cpp b/clang/lib/Format/UnwrappedLineFormatter.cpp index 56077499c39d539ab69a94786a202d89af3e264c..27983a330ac40a40616b1bc6b61f320497fad301 100644 --- a/clang/lib/Format/UnwrappedLineFormatter.cpp +++ b/clang/lib/Format/UnwrappedLineFormatter.cpp @@ -954,13 +954,15 @@ static void markFinalized(FormatToken *Tok) { // will be modified as unexpanded arguments (as part of the macro call // formatting) in the next pass. Tok->MacroCtx->Role = MR_UnexpandedArg; - // Reset whether spaces are required before this token, as that is context - // dependent, and that context may change when formatting the macro call. - // For example, given M(x) -> 2 * x, and the macro call M(var), - // the token 'var' will have SpacesRequiredBefore = 1 after being + // Reset whether spaces or a line break are required before this token, as + // that is context dependent, and that context may change when formatting + // the macro call. For example, given M(x) -> 2 * x, and the macro call + // M(var), the token 'var' will have SpacesRequiredBefore = 1 after being // formatted as part of the expanded macro, but SpacesRequiredBefore = 0 // for its position within the macro call. Tok->SpacesRequiredBefore = 0; + if (!Tok->MustBreakBeforeFinalized) + Tok->MustBreakBefore = 0; } else { Tok->Finalized = true; } diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp index 684609747a5513f5e7807f334f71311302c34ff0..50d41c9f57a670c6a8f29b21402066300e3091f5 100644 --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -2308,7 +2308,7 @@ bool UnwrappedLineParser::tryToParseLambdaIntroducer() { LeftSquare->isCppStructuredBinding(Style)) { return false; } - if (FormatTok->is(tok::l_square)) + if (FormatTok->is(tok::l_square) || tok::isLiteral(FormatTok->Tok.getKind())) return false; if (FormatTok->is(tok::r_square)) { const FormatToken *Next = Tokens->peekNextToken(/*SkipComment=*/true); @@ -4675,6 +4675,7 @@ void UnwrappedLineParser::readToken(int LevelDifference) { conditionalCompilationEnd(); FormatTok = Tokens->getNextToken(); FormatTok->MustBreakBefore = true; + FormatTok->MustBreakBeforeFinalized = true; } auto IsFirstNonCommentOnLine = [](bool FirstNonCommentOnLine, @@ -4891,6 +4892,7 @@ void UnwrappedLineParser::pushToken(FormatToken *Tok) { Line->Tokens.push_back(UnwrappedLineNode(Tok)); if (MustBreakBeforeNextToken) { Line->Tokens.back().Tok->MustBreakBefore = true; + Line->Tokens.back().Tok->MustBreakBeforeFinalized = true; MustBreakBeforeNextToken = false; } } diff --git a/clang/lib/Format/WhitespaceManager.cpp b/clang/lib/Format/WhitespaceManager.cpp index 3bc6915b8df0a7083902cfa049c2b153d0e3235a..8415c8d360d6401504a80c450fec14bd258d6428 100644 --- a/clang/lib/Format/WhitespaceManager.cpp +++ b/clang/lib/Format/WhitespaceManager.cpp @@ -978,7 +978,14 @@ void WhitespaceManager::alignConsecutiveDeclarations() { AlignTokens( Style, - [](Change const &C) { + [&](Change const &C) { + if (Style.AlignConsecutiveDeclarations.AlignFunctionPointers) { + for (const auto *Prev = C.Tok->Previous; Prev; Prev = Prev->Previous) + if (Prev->is(tok::equal)) + return false; + if (C.Tok->is(TT_FunctionTypeLParen)) + return true; + } if (C.Tok->is(TT_FunctionDeclarationName)) return true; if (C.Tok->isNot(TT_StartOfName)) @@ -1444,8 +1451,10 @@ WhitespaceManager::CellDescriptions WhitespaceManager::getCells(unsigned Start, } else if (C.Tok->is(tok::comma)) { if (!Cells.empty()) Cells.back().EndIndex = i; - if (C.Tok->getNextNonComment()->isNot(tok::r_brace)) // dangling comma + if (const auto *Next = C.Tok->getNextNonComment(); + Next && Next->isNot(tok::r_brace)) { // dangling comma ++Cell; + } } } else if (Depth == 1) { if (C.Tok == MatchingParen) { diff --git a/clang/lib/Format/WhitespaceManager.h b/clang/lib/Format/WhitespaceManager.h index 24fe492dcb0269b82c18d08e81d2bbeec53baf61..dc6f60e5deeedf41377d237a9f05be28b623c8ff 100644 --- a/clang/lib/Format/WhitespaceManager.h +++ b/clang/lib/Format/WhitespaceManager.h @@ -282,6 +282,7 @@ private: for (auto PrevIter = Start; PrevIter != End; ++PrevIter) { // If we broke the line the initial spaces are already // accounted for. + assert(PrevIter->Index < Changes.size()); if (Changes[PrevIter->Index].NewlinesBefore > 0) NetWidth = 0; NetWidth += diff --git a/clang/lib/Frontend/VerifyDiagnosticConsumer.cpp b/clang/lib/Frontend/VerifyDiagnosticConsumer.cpp index 8a3d2286cd168c3b3f6310e89d8e34d9d68c21a0..f508408ba7062c3cdef39b13adce5222b445afc0 100644 --- a/clang/lib/Frontend/VerifyDiagnosticConsumer.cpp +++ b/clang/lib/Frontend/VerifyDiagnosticConsumer.cpp @@ -611,12 +611,19 @@ static bool ParseDirective(StringRef S, ExpectedData *ED, SourceManager &SM, diag::err_verify_missing_start) << KindStr; continue; } + llvm::SmallString<8> CloseBrace("}}"); + const char *const DelimBegin = PH.C; PH.Advance(); + // Count the number of opening braces for `string` kinds + for (; !D.RegexKind && PH.Next("{"); PH.Advance()) + CloseBrace += '}'; const char* const ContentBegin = PH.C; // mark content begin - // Search for token: }} - if (!PH.SearchClosingBrace("{{", "}}")) { - Diags.Report(Pos.getLocWithOffset(PH.C-PH.Begin), - diag::err_verify_missing_end) << KindStr; + // Search for closing brace + StringRef OpenBrace(DelimBegin, ContentBegin - DelimBegin); + if (!PH.SearchClosingBrace(OpenBrace, CloseBrace)) { + Diags.Report(Pos.getLocWithOffset(PH.C - PH.Begin), + diag::err_verify_missing_end) + << KindStr << CloseBrace; continue; } const char* const ContentEnd = PH.P; // mark content end diff --git a/clang/lib/Headers/arm_acle.h b/clang/lib/Headers/arm_acle.h index 61d80258d166a1d700376732209848f7ae66c949..9aae2285aeb1d82d00a4b40201dcc489ca13991d 100644 --- a/clang/lib/Headers/arm_acle.h +++ b/clang/lib/Headers/arm_acle.h @@ -756,6 +756,65 @@ __arm_st64bv0(void *__addr, data512_t __value) { __builtin_arm_mops_memset_tag(__tagged_address, __value, __size) #endif +/* Coprocessor Intrinsics */ +#if defined(__ARM_FEATURE_COPROC) + +#if (__ARM_FEATURE_COPROC & 0x1) + +#if (__ARM_ARCH < 8) +#define __arm_cdp(coproc, opc1, CRd, CRn, CRm, opc2) \ + __builtin_arm_cdp(coproc, opc1, CRd, CRn, CRm, opc2) +#endif /* __ARM_ARCH < 8 */ + +#define __arm_ldc(coproc, CRd, p) __builtin_arm_ldc(coproc, CRd, p) +#define __arm_stc(coproc, CRd, p) __builtin_arm_stc(coproc, CRd, p) + +#define __arm_mcr(coproc, opc1, value, CRn, CRm, opc2) \ + __builtin_arm_mcr(coproc, opc1, value, CRn, CRm, opc2) +#define __arm_mrc(coproc, opc1, CRn, CRm, opc2) \ + __builtin_arm_mrc(coproc, opc1, CRn, CRm, opc2) + +#if (__ARM_ARCH != 4) && (__ARM_ARCH < 8) +#define __arm_ldcl(coproc, CRd, p) __builtin_arm_ldcl(coproc, CRd, p) +#define __arm_stcl(coproc, CRd, p) __builtin_arm_stcl(coproc, CRd, p) +#endif /* (__ARM_ARCH != 4) && (__ARM_ARCH != 8) */ + +#if (__ARM_ARCH_8M_MAIN__) || (__ARM_ARCH_8_1M_MAIN__) +#define __arm_cdp(coproc, opc1, CRd, CRn, CRm, opc2) \ + __builtin_arm_cdp(coproc, opc1, CRd, CRn, CRm, opc2) +#define __arm_ldcl(coproc, CRd, p) __builtin_arm_ldcl(coproc, CRd, p) +#define __arm_stcl(coproc, CRd, p) __builtin_arm_stcl(coproc, CRd, p) +#endif /* ___ARM_ARCH_8M_MAIN__ */ + +#endif /* __ARM_FEATURE_COPROC & 0x1 */ + +#if (__ARM_FEATURE_COPROC & 0x2) +#define __arm_cdp2(coproc, opc1, CRd, CRn, CRm, opc2) \ + __builtin_arm_cdp2(coproc, opc1, CRd, CRn, CRm, opc2) +#define __arm_ldc2(coproc, CRd, p) __builtin_arm_ldc2(coproc, CRd, p) +#define __arm_stc2(coproc, CRd, p) __builtin_arm_stc2(coproc, CRd, p) +#define __arm_ldc2l(coproc, CRd, p) __builtin_arm_ldc2l(coproc, CRd, p) +#define __arm_stc2l(coproc, CRd, p) __builtin_arm_stc2l(coproc, CRd, p) +#define __arm_mcr2(coproc, opc1, value, CRn, CRm, opc2) \ + __builtin_arm_mcr2(coproc, opc1, value, CRn, CRm, opc2) +#define __arm_mrc2(coproc, opc1, CRn, CRm, opc2) \ + __builtin_arm_mrc2(coproc, opc1, CRn, CRm, opc2) +#endif + +#if (__ARM_FEATURE_COPROC & 0x4) +#define __arm_mcrr(coproc, opc1, value, CRm) \ + __builtin_arm_mcrr(coproc, opc1, value, CRm) +#define __arm_mrrc(coproc, opc1, CRm) __builtin_arm_mrrc(coproc, opc1, CRm) +#endif + +#if (__ARM_FEATURE_COPROC & 0x8) +#define __arm_mcrr2(coproc, opc1, value, CRm) \ + __builtin_arm_mcrr2(coproc, opc1, value, CRm) +#define __arm_mrrc2(coproc, opc1, CRm) __builtin_arm_mrrc2(coproc, opc1, CRm) +#endif + +#endif // __ARM_FEATURE_COPROC + /* Transactional Memory Extension (TME) Intrinsics */ #if defined(__ARM_FEATURE_TME) && __ARM_FEATURE_TME diff --git a/clang/lib/Headers/ia32intrin.h b/clang/lib/Headers/ia32intrin.h index f1904efd71c4c7a03011ea31db72aa6daa3b73e4..a8b59dfaad89801c6032325200b7e4077400276f 100644 --- a/clang/lib/Headers/ia32intrin.h +++ b/clang/lib/Headers/ia32intrin.h @@ -26,51 +26,48 @@ #define __DEFAULT_FN_ATTRS_CONSTEXPR __DEFAULT_FN_ATTRS #endif -/** Find the first set bit starting from the lsb. Result is undefined if - * input is 0. - * - * \headerfile - * - * This intrinsic corresponds to the BSF instruction or the - * TZCNT instruction. - * - * \param __A - * A 32-bit integer operand. - * \returns A 32-bit integer containing the bit number. - */ +/// Find the first set bit starting from the lsb. Result is undefined if +/// input is 0. +/// +/// \headerfile +/// +/// This intrinsic corresponds to the \c BSF instruction or the +/// \c TZCNT instruction. +/// +/// \param __A +/// A 32-bit integer operand. +/// \returns A 32-bit integer containing the bit number. static __inline__ int __DEFAULT_FN_ATTRS_CONSTEXPR __bsfd(int __A) { return __builtin_ctz((unsigned int)__A); } -/** Find the first set bit starting from the msb. Result is undefined if - * input is 0. - * - * \headerfile - * - * This intrinsic corresponds to the BSR instruction or the - * LZCNT instruction and an XOR . - * - * \param __A - * A 32-bit integer operand. - * \returns A 32-bit integer containing the bit number. - */ +/// Find the first set bit starting from the msb. Result is undefined if +/// input is 0. +/// +/// \headerfile +/// +/// This intrinsic corresponds to the \c BSR instruction or the +/// \c LZCNT instruction and an \c XOR. +/// +/// \param __A +/// A 32-bit integer operand. +/// \returns A 32-bit integer containing the bit number. static __inline__ int __DEFAULT_FN_ATTRS_CONSTEXPR __bsrd(int __A) { return 31 - __builtin_clz((unsigned int)__A); } -/** Swaps the bytes in the input. Converting little endian to big endian or - * vice versa. - * - * \headerfile - * - * This intrinsic corresponds to the BSWAP instruction. - * - * \param __A - * A 32-bit integer operand. - * \returns A 32-bit integer containing the swapped bytes. - */ +/// Swaps the bytes in the input. Converting little endian to big endian or +/// vice versa. +/// +/// \headerfile +/// +/// This intrinsic corresponds to the \c BSWAP instruction. +/// +/// \param __A +/// A 32-bit integer operand. +/// \returns A 32-bit integer containing the swapped bytes. static __inline__ int __DEFAULT_FN_ATTRS_CONSTEXPR __bswapd(int __A) { return (int)__builtin_bswap32((unsigned int)__A); @@ -85,51 +82,48 @@ _bswap(int __A) { #define _bit_scan_reverse(A) __bsrd((A)) #ifdef __x86_64__ -/** Find the first set bit starting from the lsb. Result is undefined if - * input is 0. - * - * \headerfile - * - * This intrinsic corresponds to the BSF instruction or the - * TZCNT instruction. - * - * \param __A - * A 64-bit integer operand. - * \returns A 32-bit integer containing the bit number. - */ +/// Find the first set bit starting from the lsb. Result is undefined if +/// input is 0. +/// +/// \headerfile +/// +/// This intrinsic corresponds to the \c BSF instruction or the +/// \c TZCNT instruction. +/// +/// \param __A +/// A 64-bit integer operand. +/// \returns A 32-bit integer containing the bit number. static __inline__ int __DEFAULT_FN_ATTRS_CONSTEXPR __bsfq(long long __A) { return (long long)__builtin_ctzll((unsigned long long)__A); } -/** Find the first set bit starting from the msb. Result is undefined if - * input is 0. - * - * \headerfile - * - * This intrinsic corresponds to the BSR instruction or the - * LZCNT instruction and an XOR . - * - * \param __A - * A 64-bit integer operand. - * \returns A 32-bit integer containing the bit number. - */ +/// Find the first set bit starting from the msb. Result is undefined if +/// input is 0. +/// +/// \headerfile +/// +/// This intrinsic corresponds to the \c BSR instruction or the +/// \c LZCNT instruction and an \c XOR. +/// +/// \param __A +/// A 64-bit integer operand. +/// \returns A 32-bit integer containing the bit number. static __inline__ int __DEFAULT_FN_ATTRS_CONSTEXPR __bsrq(long long __A) { return 63 - __builtin_clzll((unsigned long long)__A); } -/** Swaps the bytes in the input. Converting little endian to big endian or - * vice versa. - * - * \headerfile - * - * This intrinsic corresponds to the BSWAP instruction. - * - * \param __A - * A 64-bit integer operand. - * \returns A 64-bit integer containing the swapped bytes. - */ +/// Swaps the bytes in the input. Converting little endian to big endian or +/// vice versa. +/// +/// \headerfile +/// +/// This intrinsic corresponds to the \c BSWAP instruction. +/// +/// \param __A +/// A 64-bit integer operand. +/// \returns A 64-bit integer containing the swapped bytes. static __inline__ long long __DEFAULT_FN_ATTRS_CONSTEXPR __bswapq(long long __A) { return (long long)__builtin_bswap64((unsigned long long)__A); @@ -138,18 +132,17 @@ __bswapq(long long __A) { #define _bswap64(A) __bswapq((A)) #endif -/** Counts the number of bits in the source operand having a value of 1. - * - * \headerfile - * - * This intrinsic corresponds to the POPCNT instruction or a - * a sequence of arithmetic and logic ops to calculate it. - * - * \param __A - * An unsigned 32-bit integer operand. - * \returns A 32-bit integer containing the number of bits with value 1 in the - * source operand. - */ +/// Counts the number of bits in the source operand having a value of 1. +/// +/// \headerfile +/// +/// This intrinsic corresponds to the \c POPCNT instruction or a +/// a sequence of arithmetic and logic ops to calculate it. +/// +/// \param __A +/// An unsigned 32-bit integer operand. +/// \returns A 32-bit integer containing the number of bits with value 1 in the +/// source operand. static __inline__ int __DEFAULT_FN_ATTRS_CONSTEXPR __popcntd(unsigned int __A) { @@ -159,18 +152,17 @@ __popcntd(unsigned int __A) #define _popcnt32(A) __popcntd((A)) #ifdef __x86_64__ -/** Counts the number of bits in the source operand having a value of 1. - * - * \headerfile - * - * This intrinsic corresponds to the POPCNT instruction or a - * a sequence of arithmetic and logic ops to calculate it. - * - * \param __A - * An unsigned 64-bit integer operand. - * \returns A 64-bit integer containing the number of bits with value 1 in the - * source operand. - */ +/// Counts the number of bits in the source operand having a value of 1. +/// +/// \headerfile +/// +/// This intrinsic corresponds to the \c POPCNT instruction or a +/// a sequence of arithmetic and logic ops to calculate it. +/// +/// \param __A +/// An unsigned 64-bit integer operand. +/// \returns A 64-bit integer containing the number of bits with value 1 in the +/// source operand. static __inline__ long long __DEFAULT_FN_ATTRS_CONSTEXPR __popcntq(unsigned long long __A) { @@ -207,123 +199,120 @@ __writeeflags(unsigned int __f) } #endif /* !__x86_64__ */ -/** Cast a 32-bit float value to a 32-bit unsigned integer value - * - * \headerfile - * This intrinsic corresponds to the VMOVD / MOVD instruction in x86_64, - * and corresponds to the VMOVL / MOVL instruction in ia32. - * - * \param __A - * A 32-bit float value. - * \returns a 32-bit unsigned integer containing the converted value. - */ +/// Cast a 32-bit float value to a 32-bit unsigned integer value. +/// +/// \headerfile +/// +/// This intrinsic corresponds to the \c VMOVD / \c MOVD instruction in x86_64, +/// and corresponds to the \c VMOVL / \c MOVL instruction in ia32. +/// +/// \param __A +/// A 32-bit float value. +/// \returns a 32-bit unsigned integer containing the converted value. static __inline__ unsigned int __DEFAULT_FN_ATTRS_CAST _castf32_u32(float __A) { return __builtin_bit_cast(unsigned int, __A); } -/** Cast a 64-bit float value to a 64-bit unsigned integer value - * - * \headerfile - * This intrinsic corresponds to the VMOVQ / MOVQ instruction in x86_64, - * and corresponds to the VMOVL / MOVL instruction in ia32. - * - * \param __A - * A 64-bit float value. - * \returns a 64-bit unsigned integer containing the converted value. - */ +/// Cast a 64-bit float value to a 64-bit unsigned integer value. +/// +/// \headerfile +/// +/// This intrinsic corresponds to the \c VMOVQ / \c MOVQ instruction in x86_64, +/// and corresponds to the \c VMOVL / \c MOVL instruction in ia32. +/// +/// \param __A +/// A 64-bit float value. +/// \returns a 64-bit unsigned integer containing the converted value. static __inline__ unsigned long long __DEFAULT_FN_ATTRS_CAST _castf64_u64(double __A) { return __builtin_bit_cast(unsigned long long, __A); } -/** Cast a 32-bit unsigned integer value to a 32-bit float value - * - * \headerfile - * This intrinsic corresponds to the VMOVQ / MOVQ instruction in x86_64, - * and corresponds to the FLDS instruction in ia32. - * - * \param __A - * A 32-bit unsigned integer value. - * \returns a 32-bit float value containing the converted value. - */ +/// Cast a 32-bit unsigned integer value to a 32-bit float value. +/// +/// \headerfile +/// +/// This intrinsic corresponds to the \c VMOVQ / \c MOVQ instruction in x86_64, +/// and corresponds to the \c FLDS instruction in ia32. +/// +/// \param __A +/// A 32-bit unsigned integer value. +/// \returns a 32-bit float value containing the converted value. static __inline__ float __DEFAULT_FN_ATTRS_CAST _castu32_f32(unsigned int __A) { return __builtin_bit_cast(float, __A); } -/** Cast a 64-bit unsigned integer value to a 64-bit float value - * - * \headerfile - * This intrinsic corresponds to the VMOVQ / MOVQ instruction in x86_64, - * and corresponds to the FLDL instruction in ia32. - * - * \param __A - * A 64-bit unsigned integer value. - * \returns a 64-bit float value containing the converted value. - */ +/// Cast a 64-bit unsigned integer value to a 64-bit float value. +/// +/// \headerfile +/// +/// This intrinsic corresponds to the \c VMOVQ / \c MOVQ instruction in x86_64, +/// and corresponds to the \c FLDL instruction in ia32. +/// +/// \param __A +/// A 64-bit unsigned integer value. +/// \returns a 64-bit float value containing the converted value. static __inline__ double __DEFAULT_FN_ATTRS_CAST _castu64_f64(unsigned long long __A) { return __builtin_bit_cast(double, __A); } -/** Adds the unsigned integer operand to the CRC-32C checksum of the - * unsigned char operand. - * - * \headerfile - * - * This intrinsic corresponds to the CRC32B instruction. - * - * \param __C - * An unsigned integer operand to add to the CRC-32C checksum of operand - * \a __D. - * \param __D - * An unsigned 8-bit integer operand used to compute the CRC-32C checksum. - * \returns The result of adding operand \a __C to the CRC-32C checksum of - * operand \a __D. - */ +/// Adds the unsigned integer operand to the CRC-32C checksum of the +/// unsigned char operand. +/// +/// \headerfile +/// +/// This intrinsic corresponds to the \c CRC32B instruction. +/// +/// \param __C +/// An unsigned integer operand to add to the CRC-32C checksum of operand +/// \a __D. +/// \param __D +/// An unsigned 8-bit integer operand used to compute the CRC-32C checksum. +/// \returns The result of adding operand \a __C to the CRC-32C checksum of +/// operand \a __D. static __inline__ unsigned int __DEFAULT_FN_ATTRS_CRC32 __crc32b(unsigned int __C, unsigned char __D) { return __builtin_ia32_crc32qi(__C, __D); } -/** Adds the unsigned integer operand to the CRC-32C checksum of the - * unsigned short operand. - * - * \headerfile - * - * This intrinsic corresponds to the CRC32W instruction. - * - * \param __C - * An unsigned integer operand to add to the CRC-32C checksum of operand - * \a __D. - * \param __D - * An unsigned 16-bit integer operand used to compute the CRC-32C checksum. - * \returns The result of adding operand \a __C to the CRC-32C checksum of - * operand \a __D. - */ +/// Adds the unsigned integer operand to the CRC-32C checksum of the +/// unsigned short operand. +/// +/// \headerfile +/// +/// This intrinsic corresponds to the \c CRC32W instruction. +/// +/// \param __C +/// An unsigned integer operand to add to the CRC-32C checksum of operand +/// \a __D. +/// \param __D +/// An unsigned 16-bit integer operand used to compute the CRC-32C checksum. +/// \returns The result of adding operand \a __C to the CRC-32C checksum of +/// operand \a __D. static __inline__ unsigned int __DEFAULT_FN_ATTRS_CRC32 __crc32w(unsigned int __C, unsigned short __D) { return __builtin_ia32_crc32hi(__C, __D); } -/** Adds the unsigned integer operand to the CRC-32C checksum of the - * second unsigned integer operand. - * - * \headerfile - * - * This intrinsic corresponds to the CRC32D instruction. - * - * \param __C - * An unsigned integer operand to add to the CRC-32C checksum of operand - * \a __D. - * \param __D - * An unsigned 32-bit integer operand used to compute the CRC-32C checksum. - * \returns The result of adding operand \a __C to the CRC-32C checksum of - * operand \a __D. - */ +/// Adds the unsigned integer operand to the CRC-32C checksum of the +/// second unsigned integer operand. +/// +/// \headerfile +/// +/// This intrinsic corresponds to the \c CRC32D instruction. +/// +/// \param __C +/// An unsigned integer operand to add to the CRC-32C checksum of operand +/// \a __D. +/// \param __D +/// An unsigned 32-bit integer operand used to compute the CRC-32C checksum. +/// \returns The result of adding operand \a __C to the CRC-32C checksum of +/// operand \a __D. static __inline__ unsigned int __DEFAULT_FN_ATTRS_CRC32 __crc32d(unsigned int __C, unsigned int __D) { @@ -331,21 +320,20 @@ __crc32d(unsigned int __C, unsigned int __D) } #ifdef __x86_64__ -/** Adds the unsigned integer operand to the CRC-32C checksum of the - * unsigned 64-bit integer operand. - * - * \headerfile - * - * This intrinsic corresponds to the CRC32Q instruction. - * - * \param __C - * An unsigned integer operand to add to the CRC-32C checksum of operand - * \a __D. - * \param __D - * An unsigned 64-bit integer operand used to compute the CRC-32C checksum. - * \returns The result of adding operand \a __C to the CRC-32C checksum of - * operand \a __D. - */ +/// Adds the unsigned integer operand to the CRC-32C checksum of the +/// unsigned 64-bit integer operand. +/// +/// \headerfile +/// +/// This intrinsic corresponds to the \c CRC32Q instruction. +/// +/// \param __C +/// An unsigned integer operand to add to the CRC-32C checksum of operand +/// \a __D. +/// \param __D +/// An unsigned 64-bit integer operand used to compute the CRC-32C checksum. +/// \returns The result of adding operand \a __C to the CRC-32C checksum of +/// operand \a __D. static __inline__ unsigned long long __DEFAULT_FN_ATTRS_CRC32 __crc32q(unsigned long long __C, unsigned long long __D) { diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp index c9fcef5b5b5af1398e1290551ae4eb6afe07f64b..734fe90d0d89b464f367b63531bcde814392f768 100644 --- a/clang/lib/Interpreter/Interpreter.cpp +++ b/clang/lib/Interpreter/Interpreter.cpp @@ -148,6 +148,7 @@ IncrementalCompilerBuilder::create(std::vector &ClangArgv) { // We do C++ by default; append right after argv[0] if no "-x" given ClangArgv.insert(ClangArgv.end(), "-Xclang"); ClangArgv.insert(ClangArgv.end(), "-fincremental-extensions"); + ClangArgv.insert(ClangArgv.end(), "-mcpu=native"); ClangArgv.insert(ClangArgv.end(), "-c"); // Put a dummy C++ file on to ensure there's at least one compile job for the diff --git a/clang/lib/Lex/ModuleMap.cpp b/clang/lib/Lex/ModuleMap.cpp index ea5d13deb11470325a4e54974a1366e528566daf..42d55d09ea5a13635037eaa0aa9a43f879342e1d 100644 --- a/clang/lib/Lex/ModuleMap.cpp +++ b/clang/lib/Lex/ModuleMap.cpp @@ -984,7 +984,9 @@ static void inferFrameworkLink(Module *Mod) { assert(!Mod->isSubFramework() && "Can only infer linking for top-level frameworks"); - Mod->LinkLibraries.push_back(Module::LinkLibrary(Mod->Name, + StringRef FrameworkName(Mod->Name); + FrameworkName.consume_back("_Private"); + Mod->LinkLibraries.push_back(Module::LinkLibrary(FrameworkName.str(), /*IsFramework=*/true)); } diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index b60ae293ef8c209178baac556856a49345bb1dcd..ed684c5d57b1ee060048e27b5276eb77b6a878f1 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -2661,7 +2661,12 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes( // ProduceConstructorSignatureHelp only on VarDecls. ExpressionStarts = SetPreferredType; } - if (ParseExpressionList(Exprs, ExpressionStarts)) { + + bool SawError = ParseExpressionList(Exprs, ExpressionStarts); + + InitScope.pop(); + + if (SawError) { if (ThisVarDecl && PP.isCodeCompletionReached() && !CalledSignatureHelp) { Actions.ProduceConstructorSignatureHelp( ThisVarDecl->getType()->getCanonicalTypeInternal(), @@ -2674,7 +2679,6 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes( } else { // Match the ')'. T.consumeClose(); - InitScope.pop(); ExprResult Initializer = Actions.ActOnParenListExpr(T.getOpenLocation(), T.getCloseLocation(), diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index 897810557976151ac35c4a117cc09e306d3bd746..dcfd290d39cc48a21b7151c4e80992020c770a40 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -1974,10 +1974,11 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { PreferredType.enterSubscript(Actions, Tok.getLocation(), LHS.get()); // We try to parse a list of indexes in all language mode first - // and, in we find 0 or one index, we try to parse an OpenMP array + // and, in we find 0 or one index, we try to parse an OpenMP/OpenACC array // section. This allow us to support C++23 multi dimensional subscript and - // OpenMp sections in the same language mode. - if (!getLangOpts().OpenMP || Tok.isNot(tok::colon)) { + // OpenMP/OpenACC sections in the same language mode. + if ((!getLangOpts().OpenMP && !AllowOpenACCArraySections) || + Tok.isNot(tok::colon)) { if (!getLangOpts().CPlusPlus23) { ExprResult Idx; if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) { @@ -2001,7 +2002,18 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { } } - if (ArgExprs.size() <= 1 && getLangOpts().OpenMP) { + // Handle OpenACC first, since 'AllowOpenACCArraySections' is only enabled + // when actively parsing a 'var' in a 'var-list' during clause/'cache' + // parsing, so it is the most specific, and best allows us to handle + // OpenACC and OpenMP at the same time. + if (ArgExprs.size() <= 1 && AllowOpenACCArraySections) { + ColonProtectionRAIIObject RAII(*this); + if (Tok.is(tok::colon)) { + // Consume ':' + ColonLocFirst = ConsumeToken(); + Length = Actions.CorrectDelayedTyposInExpr(ParseExpression()); + } + } else if (ArgExprs.size() <= 1 && getLangOpts().OpenMP) { ColonProtectionRAIIObject RAII(*this); if (Tok.is(tok::colon)) { // Consume ':' @@ -2031,6 +2043,12 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { if (!LHS.isInvalid() && !HasError && !Length.isInvalid() && !Stride.isInvalid() && Tok.is(tok::r_square)) { if (ColonLocFirst.isValid() || ColonLocSecond.isValid()) { + // FIXME: OpenACC hasn't implemented Sema/Array section handling at a + // semantic level yet. For now, just reuse the OpenMP implementation + // as it gets the parsing/type management mostly right, and we can + // replace this call to ActOnOpenACCArraySectionExpr in the future. + // Eventually we'll genericize the OPenMPArraySectionExpr type as + // well. LHS = Actions.ActOnOMPArraySectionExpr( LHS.get(), Loc, ArgExprs.empty() ? nullptr : ArgExprs[0], ColonLocFirst, ColonLocSecond, Length.get(), Stride.get(), RLoc); diff --git a/clang/lib/Parse/ParseOpenACC.cpp b/clang/lib/Parse/ParseOpenACC.cpp index 94c3d0c4e164cdf25fc30ec8135c63365e80698b..05087a6565a11c38f865147fb2a71b1db36a23a2 100644 --- a/clang/lib/Parse/ParseOpenACC.cpp +++ b/clang/lib/Parse/ParseOpenACC.cpp @@ -80,18 +80,38 @@ OpenACCClauseKind getOpenACCClauseKind(Token Tok) { if (Tok.is(tok::kw_default)) return OpenACCClauseKind::Default; + // if is also a keyword, make sure we parse it correctly. + if (Tok.is(tok::kw_if)) + return OpenACCClauseKind::If; + if (!Tok.is(tok::identifier)) return OpenACCClauseKind::Invalid; return llvm::StringSwitch( Tok.getIdentifierInfo()->getName()) + .Case("attach", OpenACCClauseKind::Attach) .Case("auto", OpenACCClauseKind::Auto) + .Case("copy", OpenACCClauseKind::Copy) .Case("default", OpenACCClauseKind::Default) + .Case("delete", OpenACCClauseKind::Delete) + .Case("detach", OpenACCClauseKind::Detach) + .Case("device", OpenACCClauseKind::Device) + .Case("device_resident", OpenACCClauseKind::DeviceResident) + .Case("deviceptr", OpenACCClauseKind::DevicePtr) .Case("finalize", OpenACCClauseKind::Finalize) + .Case("firstprivate", OpenACCClauseKind::FirstPrivate) + .Case("host", OpenACCClauseKind::Host) + .Case("if", OpenACCClauseKind::If) .Case("if_present", OpenACCClauseKind::IfPresent) .Case("independent", OpenACCClauseKind::Independent) + .Case("link", OpenACCClauseKind::Link) + .Case("no_create", OpenACCClauseKind::NoCreate) .Case("nohost", OpenACCClauseKind::NoHost) + .Case("present", OpenACCClauseKind::Present) + .Case("private", OpenACCClauseKind::Private) + .Case("self", OpenACCClauseKind::Self) .Case("seq", OpenACCClauseKind::Seq) + .Case("use_device", OpenACCClauseKind::UseDevice) .Case("vector", OpenACCClauseKind::Vector) .Case("worker", OpenACCClauseKind::Worker) .Default(OpenACCClauseKind::Invalid); @@ -323,68 +343,63 @@ OpenACCDirectiveKind ParseOpenACCDirectiveKind(Parser &P) { return DirKind; } -bool ClauseHasRequiredParens(OpenACCClauseKind Kind) { - return Kind == OpenACCClauseKind::Default; -} - -bool ParseOpenACCClauseParams(Parser &P, OpenACCClauseKind Kind) { - BalancedDelimiterTracker Parens(P, tok::l_paren, - tok::annot_pragma_openacc_end); - - if (ClauseHasRequiredParens(Kind)) { - if (Parens.expectAndConsume()) { - // We are missing a paren, so assume that the person just forgot the - // parameter. Return 'false' so we try to continue on and parse the next - // clause. - P.SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openacc_end, - Parser::StopBeforeMatch); - return false; - } - - switch (Kind) { - case OpenACCClauseKind::Default: { - Token DefKindTok = P.getCurToken(); - - if (expectIdentifierOrKeyword(P)) - break; - - P.ConsumeToken(); - - if (getOpenACCDefaultClauseKind(DefKindTok) == - OpenACCDefaultClauseKind::Invalid) - P.Diag(DefKindTok, diag::err_acc_invalid_default_clause_kind); - - break; - } - default: - llvm_unreachable("Not a required parens type?"); - } +enum ClauseParensKind { + None, + Optional, + Required +}; - return Parens.consumeClose(); +ClauseParensKind getClauseParensKind(OpenACCClauseKind Kind) { + switch (Kind) { + case OpenACCClauseKind::Self: + return ClauseParensKind::Optional; + + case OpenACCClauseKind::Default: + case OpenACCClauseKind::If: + case OpenACCClauseKind::Copy: + case OpenACCClauseKind::UseDevice: + case OpenACCClauseKind::NoCreate: + case OpenACCClauseKind::Present: + case OpenACCClauseKind::DevicePtr: + case OpenACCClauseKind::Attach: + case OpenACCClauseKind::Detach: + case OpenACCClauseKind::Private: + case OpenACCClauseKind::FirstPrivate: + case OpenACCClauseKind::Delete: + case OpenACCClauseKind::DeviceResident: + case OpenACCClauseKind::Device: + case OpenACCClauseKind::Link: + case OpenACCClauseKind::Host: + return ClauseParensKind::Required; + + case OpenACCClauseKind::Auto: + case OpenACCClauseKind::Finalize: + case OpenACCClauseKind::IfPresent: + case OpenACCClauseKind::Independent: + case OpenACCClauseKind::Invalid: + case OpenACCClauseKind::NoHost: + case OpenACCClauseKind::Seq: + case OpenACCClauseKind::Worker: + case OpenACCClauseKind::Vector: + return ClauseParensKind::None; } - // FIXME: Handle optional parens - return false; + llvm_unreachable("Unhandled clause kind"); } -// The OpenACC Clause List is a comma or space-delimited list of clauses (see -// the comment on ParseOpenACCClauseList). The concept of a 'clause' doesn't -// really have its owner grammar and each individual one has its own definition. -// However, they all are named with a single-identifier (or auto/default!) -// token, followed in some cases by either braces or parens. -bool ParseOpenACCClause(Parser &P) { - if (!P.getCurToken().isOneOf(tok::identifier, tok::kw_auto, tok::kw_default)) - return P.Diag(P.getCurToken(), diag::err_expected) << tok::identifier; - - OpenACCClauseKind Kind = getOpenACCClauseKind(P.getCurToken()); - - if (Kind == OpenACCClauseKind::Invalid) - return P.Diag(P.getCurToken(), diag::err_acc_invalid_clause) - << P.getCurToken().getIdentifierInfo(); +bool ClauseHasOptionalParens(OpenACCClauseKind Kind) { + return getClauseParensKind(Kind) == ClauseParensKind::Optional; +} - // Consume the clause name. - P.ConsumeToken(); +bool ClauseHasRequiredParens(OpenACCClauseKind Kind) { + return getClauseParensKind(Kind) == ClauseParensKind::Required; +} - return ParseOpenACCClauseParams(P, Kind); +ExprResult ParseOpenACCConditionalExpr(Parser &P) { + // FIXME: It isn't clear if the spec saying 'condition' means the same as + // it does in an if/while/etc (See ParseCXXCondition), however as it was + // written with Fortran/C in mind, we're going to assume it just means an + // 'expression evaluating to boolean'. + return P.getActions().CorrectDelayedTyposInExpr(P.ParseExpression()); } // Skip until we see the end of pragma token, but don't consume it. This is us @@ -396,29 +411,152 @@ void SkipUntilEndOfDirective(Parser &P) { P.ConsumeAnyToken(); } +} // namespace + // OpenACC 3.3, section 1.7: // To simplify the specification and convey appropriate constraint information, // a pqr-list is a comma-separated list of pdr items. The one exception is a // clause-list, which is a list of one or more clauses optionally separated by // commas. -void ParseOpenACCClauseList(Parser &P) { +void Parser::ParseOpenACCClauseList() { bool FirstClause = true; - while (P.getCurToken().isNot(tok::annot_pragma_openacc_end)) { + while (getCurToken().isNot(tok::annot_pragma_openacc_end)) { // Comma is optional in a clause-list. - if (!FirstClause && P.getCurToken().is(tok::comma)) - P.ConsumeToken(); + if (!FirstClause && getCurToken().is(tok::comma)) + ConsumeToken(); FirstClause = false; // Recovering from a bad clause is really difficult, so we just give up on // error. - if (ParseOpenACCClause(P)) { - SkipUntilEndOfDirective(P); + if (ParseOpenACCClause()) { + SkipUntilEndOfDirective(*this); return; } } } -} // namespace +bool Parser::ParseOpenACCClauseVarList(OpenACCClauseKind Kind) { + // FIXME: Future clauses will require 'special word' parsing, check for one, + // then parse it based on whether it is a clause that requires a 'special + // word'. + (void)Kind; + + // If the var parsing fails, skip until the end of the directive as this is + // an expression and gets messy if we try to continue otherwise. + if (ParseOpenACCVar()) + return true; + + while (!getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) { + ExpectAndConsume(tok::comma); + + // If the var parsing fails, skip until the end of the directive as this is + // an expression and gets messy if we try to continue otherwise. + if (ParseOpenACCVar()) + return true; + } + return false; +} +// The OpenACC Clause List is a comma or space-delimited list of clauses (see +// the comment on ParseOpenACCClauseList). The concept of a 'clause' doesn't +// really have its owner grammar and each individual one has its own definition. +// However, they all are named with a single-identifier (or auto/default!) +// token, followed in some cases by either braces or parens. +bool Parser::ParseOpenACCClause() { + // A number of clause names are actually keywords, so accept a keyword that + // can be converted to a name. + if (expectIdentifierOrKeyword(*this)) + return true; + + OpenACCClauseKind Kind = getOpenACCClauseKind(getCurToken()); + + if (Kind == OpenACCClauseKind::Invalid) + return Diag(getCurToken(), diag::err_acc_invalid_clause) + << getCurToken().getIdentifierInfo(); + + // Consume the clause name. + ConsumeToken(); + + return ParseOpenACCClauseParams(Kind); +} + +bool Parser::ParseOpenACCClauseParams(OpenACCClauseKind Kind) { + BalancedDelimiterTracker Parens(*this, tok::l_paren, + tok::annot_pragma_openacc_end); + + if (ClauseHasRequiredParens(Kind)) { + if (Parens.expectAndConsume()) { + // We are missing a paren, so assume that the person just forgot the + // parameter. Return 'false' so we try to continue on and parse the next + // clause. + SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openacc_end, + Parser::StopBeforeMatch); + return false; + } + + switch (Kind) { + case OpenACCClauseKind::Default: { + Token DefKindTok = getCurToken(); + + if (expectIdentifierOrKeyword(*this)) + break; + + ConsumeToken(); + + if (getOpenACCDefaultClauseKind(DefKindTok) == + OpenACCDefaultClauseKind::Invalid) + Diag(DefKindTok, diag::err_acc_invalid_default_clause_kind); + + break; + } + case OpenACCClauseKind::If: { + ExprResult CondExpr = ParseOpenACCConditionalExpr(*this); + // An invalid expression can be just about anything, so just give up on + // this clause list. + if (CondExpr.isInvalid()) + return true; + break; + } + case OpenACCClauseKind::Attach: + case OpenACCClauseKind::Copy: + case OpenACCClauseKind::Delete: + case OpenACCClauseKind::Detach: + case OpenACCClauseKind::Device: + case OpenACCClauseKind::DeviceResident: + case OpenACCClauseKind::DevicePtr: + case OpenACCClauseKind::FirstPrivate: + case OpenACCClauseKind::Host: + case OpenACCClauseKind::Link: + case OpenACCClauseKind::NoCreate: + case OpenACCClauseKind::Present: + case OpenACCClauseKind::Private: + case OpenACCClauseKind::UseDevice: + if (ParseOpenACCClauseVarList(Kind)) + return true; + break; + default: + llvm_unreachable("Not a required parens type?"); + } + + return Parens.consumeClose(); + } else if (ClauseHasOptionalParens(Kind)) { + if (!Parens.consumeOpen()) { + switch (Kind) { + case OpenACCClauseKind::Self: { + ExprResult CondExpr = ParseOpenACCConditionalExpr(*this); + // An invalid expression can be just about anything, so just give up on + // this clause list. + if (CondExpr.isInvalid()) + return true; + break; + } + default: + llvm_unreachable("Not an optional parens type?"); + } + Parens.consumeClose(); + } + } + return false; +} /// OpenACC 3.3, section 2.16: /// In this section and throughout the specification, the term wait-argument @@ -511,49 +649,17 @@ ExprResult Parser::ParseOpenACCIDExpression() { return getActions().CorrectDelayedTyposInExpr(Res); } -/// OpenACC 3.3, section 2.10: -/// A 'var' in a cache directive must be a single array element or a simple -/// subarray. In C and C++, a simple subarray is an array name followed by an -/// extended array range specification in brackets, with a start and length such -/// as: -/// -/// arr[lower:length] -/// -bool Parser::ParseOpenACCCacheVar() { - ExprResult ArrayName = ParseOpenACCIDExpression(); - if (ArrayName.isInvalid()) - return true; - - // If the expression is invalid, just continue parsing the brackets, there - // is likely other useful diagnostics we can emit inside of those. - - BalancedDelimiterTracker SquareBrackets(*this, tok::l_square, - tok::annot_pragma_openacc_end); - - // Square brackets are required, so error here, and try to recover by moving - // until the next comma, or the close paren/end of pragma. - if (SquareBrackets.expectAndConsume()) { - SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openacc_end, - Parser::StopBeforeMatch); - return true; - } - - ExprResult Lower = getActions().CorrectDelayedTyposInExpr(ParseExpression()); - if (Lower.isInvalid()) - return true; - - // The 'length' expression is optional, as this could be a single array - // element. If there is no colon, we can treat it as that. - if (getCurToken().is(tok::colon)) { - ConsumeToken(); - ExprResult Length = - getActions().CorrectDelayedTyposInExpr(ParseExpression()); - if (Length.isInvalid()) - return true; - } - - // Diagnose the square bracket being in the wrong place and continue. - return SquareBrackets.consumeClose(); +/// OpenACC 3.3, section 1.6: +/// In this spec, a 'var' (in italics) is one of the following: +/// - a variable name (a scalar, array, or compisite variable name) +/// - a subarray specification with subscript ranges +/// - an array element +/// - a member of a composite variable +/// - a common block name between slashes (fortran only) +bool Parser::ParseOpenACCVar() { + OpenACCArraySectionRAII ArraySections(*this); + ExprResult Res = ParseAssignmentExpression(); + return Res.isInvalid(); } /// OpenACC 3.3, section 2.10: @@ -584,7 +690,16 @@ void Parser::ParseOpenACCCacheVarList() { if (!FirstArray) ExpectAndConsume(tok::comma); FirstArray = false; - if (ParseOpenACCCacheVar()) + + // OpenACC 3.3, section 2.10: + // A 'var' in a cache directive must be a single array element or a simple + // subarray. In C and C++, a simple subarray is an array name followed by + // an extended array range specification in brackets, with a start and + // length such as: + // + // arr[lower:length] + // + if (ParseOpenACCVar()) SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end, tok::comma, StopBeforeMatch); } @@ -644,7 +759,7 @@ void Parser::ParseOpenACCDirective() { } // Parses the list of clauses, if present. - ParseOpenACCClauseList(*this); + ParseOpenACCClauseList(); Diag(getCurToken(), diag::warn_pragma_acc_unimplemented); assert(Tok.is(tok::annot_pragma_openacc_end) && diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index f13164dc063866986de0fd47dba0e032eb4e6c6b..74f8f626fb1637c75c29b04af08b956e1fab4589 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -18376,7 +18376,7 @@ static bool isSetterLikeSelector(Selector sel) { if (sel.isUnarySelector()) return false; StringRef str = sel.getNameForSlot(0); - while (!str.empty() && str.front() == '_') str = str.substr(1); + str = str.ltrim('_'); if (str.starts_with("set")) str = str.substr(3); else if (str.starts_with("add")) { diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 8e46c4984d93dc9464c850c0899a061974a3c18c..e92fd104d78eb57e97c519664af221e790e2527c 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -2315,6 +2315,12 @@ void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) { } ShadowingDecls.erase(ShadowI); } + + if (!getLangOpts().CPlusPlus && S->isClassScope()) { + if (auto *FD = dyn_cast(TmpD); + FD && FD->hasAttr()) + CheckCountedByAttr(S, FD); + } } llvm::sort(DeclDiags, diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index d059b406ef86e0d8c967459edfc0922b3befb156..1a58cfd8e4179e7853ef0248b8fcc1beca726333 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -8460,6 +8460,135 @@ static void handleZeroCallUsedRegsAttr(Sema &S, Decl *D, const ParsedAttr &AL) { D->addAttr(ZeroCallUsedRegsAttr::Create(S.Context, Kind, AL)); } +static void handleCountedByAttr(Sema &S, Decl *D, const ParsedAttr &AL) { + if (!AL.isArgIdent(0)) { + S.Diag(AL.getLoc(), diag::err_attribute_argument_type) + << AL << AANT_ArgumentIdentifier; + return; + } + + IdentifierLoc *IL = AL.getArgAsIdent(0); + CountedByAttr *CBA = + ::new (S.Context) CountedByAttr(S.Context, AL, IL->Ident); + CBA->setCountedByFieldLoc(IL->Loc); + D->addAttr(CBA); +} + +static const FieldDecl * +FindFieldInTopLevelOrAnonymousStruct(const RecordDecl *RD, + const IdentifierInfo *FieldName) { + for (const Decl *D : RD->decls()) { + if (const auto *FD = dyn_cast(D)) + if (FD->getName() == FieldName->getName()) + return FD; + + if (const auto *R = dyn_cast(D)) + if (const FieldDecl *FD = + FindFieldInTopLevelOrAnonymousStruct(R, FieldName)) + return FD; + } + + return nullptr; +} + +bool Sema::CheckCountedByAttr(Scope *S, const FieldDecl *FD) { + LangOptions::StrictFlexArraysLevelKind StrictFlexArraysLevel = + LangOptions::StrictFlexArraysLevelKind::IncompleteOnly; + if (!Decl::isFlexibleArrayMemberLike(Context, FD, FD->getType(), + StrictFlexArraysLevel, true)) { + // The "counted_by" attribute must be on a flexible array member. + SourceRange SR = FD->getLocation(); + Diag(SR.getBegin(), diag::err_counted_by_attr_not_on_flexible_array_member) + << SR; + return true; + } + + const auto *CBA = FD->getAttr(); + const IdentifierInfo *FieldName = CBA->getCountedByField(); + + auto GetNonAnonStructOrUnion = [](const RecordDecl *RD) { + while (RD && !RD->getDeclName()) + if (const auto *R = dyn_cast(RD->getDeclContext())) + RD = R; + else + break; + + return RD; + }; + + const RecordDecl *EnclosingRD = GetNonAnonStructOrUnion(FD->getParent()); + const FieldDecl *CountFD = + FindFieldInTopLevelOrAnonymousStruct(EnclosingRD, FieldName); + + if (!CountFD) { + DeclarationNameInfo NameInfo(FieldName, + CBA->getCountedByFieldLoc().getBegin()); + LookupResult MemResult(*this, NameInfo, Sema::LookupMemberName); + LookupName(MemResult, S); + + if (!MemResult.empty()) { + SourceRange SR = CBA->getCountedByFieldLoc(); + Diag(SR.getBegin(), diag::err_flexible_array_count_not_in_same_struct) + << CBA->getCountedByField() << SR; + + if (auto *ND = MemResult.getAsSingle()) { + SR = ND->getLocation(); + Diag(SR.getBegin(), diag::note_flexible_array_counted_by_attr_field) + << ND << SR; + } + + return true; + } else { + // The "counted_by" field needs to exist in the struct. + LookupResult OrdResult(*this, NameInfo, Sema::LookupOrdinaryName); + LookupName(OrdResult, S); + + if (!OrdResult.empty()) { + SourceRange SR = FD->getLocation(); + Diag(SR.getBegin(), diag::err_counted_by_must_be_in_structure) + << FieldName << SR; + + if (auto *ND = OrdResult.getAsSingle()) { + SR = ND->getLocation(); + Diag(SR.getBegin(), diag::note_flexible_array_counted_by_attr_field) + << ND << SR; + } + + return true; + } + } + + CXXScopeSpec SS; + DeclFilterCCC Filter(FieldName); + return DiagnoseEmptyLookup(S, SS, MemResult, Filter, nullptr, std::nullopt, + const_cast(FD->getDeclContext())); + } + + if (CountFD->hasAttr()) { + // The "counted_by" field can't point to the flexible array member. + SourceRange SR = CBA->getCountedByFieldLoc(); + Diag(SR.getBegin(), diag::err_counted_by_attr_refers_to_flexible_array) + << CBA->getCountedByField() << SR; + return true; + } + + if (!CountFD->getType()->isIntegerType() || + CountFD->getType()->isBooleanType()) { + // The "counted_by" field must have an integer type. + SourceRange SR = CBA->getCountedByFieldLoc(); + Diag(SR.getBegin(), + diag::err_flexible_array_counted_by_attr_field_not_integer) + << CBA->getCountedByField() << SR; + + SR = CountFD->getLocation(); + Diag(SR.getBegin(), diag::note_flexible_array_counted_by_attr_field) + << CountFD << SR; + return true; + } + + return false; +} + static void handleFunctionReturnThunksAttr(Sema &S, Decl *D, const ParsedAttr &AL) { StringRef KindStr; @@ -9420,6 +9549,10 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL, handleAvailableOnlyInDefaultEvalMethod(S, D, AL); break; + case ParsedAttr::AT_CountedBy: + handleCountedByAttr(S, D, AL); + break; + // Microsoft attributes: case ParsedAttr::AT_LayoutVersion: handleLayoutVersion(S, D, AL); diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 960f513d1111b2c71d0b001855106d2a52d02b33..2f48ea237cdfa4236849207301cda80c1a671275 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -2469,7 +2469,8 @@ bool Sema::DiagnoseDependentMemberLookup(const LookupResult &R) { bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, CorrectionCandidateCallback &CCC, TemplateArgumentListInfo *ExplicitTemplateArgs, - ArrayRef Args, TypoExpr **Out) { + ArrayRef Args, DeclContext *LookupCtx, + TypoExpr **Out) { DeclarationName Name = R.getLookupName(); unsigned diagnostic = diag::err_undeclared_var_use; @@ -2485,7 +2486,8 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, // unqualified lookup. This is useful when (for example) the // original lookup would not have found something because it was a // dependent name. - DeclContext *DC = SS.isEmpty() ? CurContext : nullptr; + DeclContext *DC = + LookupCtx ? LookupCtx : (SS.isEmpty() ? CurContext : nullptr); while (DC) { if (isa(DC)) { LookupQualifiedName(R, DC); @@ -2528,12 +2530,12 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, emitEmptyLookupTypoDiagnostic(TC, *this, SS, Name, TypoLoc, Args, diagnostic, diagnostic_suggest); }, - nullptr, CTK_ErrorRecovery); + nullptr, CTK_ErrorRecovery, LookupCtx); if (*Out) return true; - } else if (S && - (Corrected = CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(), - S, &SS, CCC, CTK_ErrorRecovery))) { + } else if (S && (Corrected = + CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(), S, + &SS, CCC, CTK_ErrorRecovery, LookupCtx))) { std::string CorrectedStr(Corrected.getAsString(getLangOpts())); bool DroppedSpecifier = Corrected.WillReplaceSpecifier() && Name.getAsString() == CorrectedStr; @@ -2823,7 +2825,7 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS, // a template name, but we happen to have always already looked up the name // before we get here if it must be a template name. if (DiagnoseEmptyLookup(S, SS, R, CCC ? *CCC : DefaultValidator, nullptr, - std::nullopt, &TE)) { + std::nullopt, nullptr, &TE)) { if (TE && KeywordReplacement) { auto &State = getTypoExprState(TE); auto BestTC = State.Consumer->getNextCorrection(); @@ -8691,10 +8693,10 @@ ExprResult Sema::ActOnParenListExpr(SourceLocation L, /// Emit a specialized diagnostic when one expression is a null pointer /// constant and the other is not a pointer. Returns true if a diagnostic is /// emitted. -bool Sema::DiagnoseConditionalForNull(Expr *LHSExpr, Expr *RHSExpr, +bool Sema::DiagnoseConditionalForNull(const Expr *LHSExpr, const Expr *RHSExpr, SourceLocation QuestionLoc) { - Expr *NullExpr = LHSExpr; - Expr *NonPointerExpr = RHSExpr; + const Expr *NullExpr = LHSExpr; + const Expr *NonPointerExpr = RHSExpr; Expr::NullPointerConstantKind NullKind = NullExpr->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull); @@ -8730,7 +8732,8 @@ bool Sema::DiagnoseConditionalForNull(Expr *LHSExpr, Expr *RHSExpr, } /// Return false if the condition expression is valid, true otherwise. -static bool checkCondition(Sema &S, Expr *Cond, SourceLocation QuestionLoc) { +static bool checkCondition(Sema &S, const Expr *Cond, + SourceLocation QuestionLoc) { QualType CondTy = Cond->getType(); // OpenCL v1.1 s6.3.i says the condition cannot be a floating point type. @@ -9542,28 +9545,27 @@ static bool IsArithmeticOp(BinaryOperatorKind Opc) { /// expression, either using a built-in or overloaded operator, /// and sets *OpCode to the opcode and *RHSExprs to the right-hand side /// expression. -static bool IsArithmeticBinaryExpr(Expr *E, BinaryOperatorKind *Opcode, - Expr **RHSExprs) { +static bool IsArithmeticBinaryExpr(const Expr *E, BinaryOperatorKind *Opcode, + const Expr **RHSExprs) { // Don't strip parenthesis: we should not warn if E is in parenthesis. E = E->IgnoreImpCasts(); E = E->IgnoreConversionOperatorSingleStep(); E = E->IgnoreImpCasts(); - if (auto *MTE = dyn_cast(E)) { + if (const auto *MTE = dyn_cast(E)) { E = MTE->getSubExpr(); E = E->IgnoreImpCasts(); } // Built-in binary operator. - if (BinaryOperator *OP = dyn_cast(E)) { - if (IsArithmeticOp(OP->getOpcode())) { - *Opcode = OP->getOpcode(); - *RHSExprs = OP->getRHS(); - return true; - } + if (const auto *OP = dyn_cast(E); + OP && IsArithmeticOp(OP->getOpcode())) { + *Opcode = OP->getOpcode(); + *RHSExprs = OP->getRHS(); + return true; } // Overloaded operator. - if (CXXOperatorCallExpr *Call = dyn_cast(E)) { + if (const auto *Call = dyn_cast(E)) { if (Call->getNumArgs() != 2) return false; @@ -9588,14 +9590,14 @@ static bool IsArithmeticBinaryExpr(Expr *E, BinaryOperatorKind *Opcode, /// ExprLooksBoolean - Returns true if E looks boolean, i.e. it has boolean type /// or is a logical expression such as (x==y) which has int type, but is /// commonly interpreted as boolean. -static bool ExprLooksBoolean(Expr *E) { +static bool ExprLooksBoolean(const Expr *E) { E = E->IgnoreParenImpCasts(); if (E->getType()->isBooleanType()) return true; - if (BinaryOperator *OP = dyn_cast(E)) + if (const auto *OP = dyn_cast(E)) return OP->isComparisonOp() || OP->isLogicalOp(); - if (UnaryOperator *OP = dyn_cast(E)) + if (const auto *OP = dyn_cast(E)) return OP->getOpcode() == UO_LNot; if (E->getType()->isPointerType()) return true; @@ -9609,13 +9611,11 @@ static bool ExprLooksBoolean(Expr *E) { /// and binary operator are mixed in a way that suggests the programmer assumed /// the conditional operator has higher precedence, for example: /// "int x = a + someBinaryCondition ? 1 : 2". -static void DiagnoseConditionalPrecedence(Sema &Self, - SourceLocation OpLoc, - Expr *Condition, - Expr *LHSExpr, - Expr *RHSExpr) { +static void DiagnoseConditionalPrecedence(Sema &Self, SourceLocation OpLoc, + Expr *Condition, const Expr *LHSExpr, + const Expr *RHSExpr) { BinaryOperatorKind CondOpcode; - Expr *CondRHS; + const Expr *CondRHS; if (!IsArithmeticBinaryExpr(Condition, &CondOpcode, &CondRHS)) return; diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp index 2abec3d86a27d99927210119ea588c53b56c3666..32998ae60eafe2b3836b6bf8af40c1fc0d623079 100644 --- a/clang/lib/Sema/SemaExprMember.cpp +++ b/clang/lib/Sema/SemaExprMember.cpp @@ -782,7 +782,8 @@ Sema::BuildMemberReferenceExpr(Expr *Base, QualType BaseType, const Scope *S, ActOnMemberAccessExtraArgs *ExtraArgs) { if (BaseType->isDependentType() || - (SS.isSet() && isDependentScopeSpecifier(SS))) + (SS.isSet() && isDependentScopeSpecifier(SS)) || + NameInfo.getName().isDependentName()) return ActOnDependentMemberExpr(Base, BaseType, IsArrow, OpLoc, SS, TemplateKWLoc, FirstQualifierInScope, diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index e469e420f14f0326493fe0cd427646f2f4f558c7..408ee5f775804b6a512975be98218cce7da4f4e9 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -10377,11 +10377,6 @@ void InitializationSequence::dump() const { dump(llvm::errs()); } -static bool NarrowingErrs(const LangOptions &L) { - return L.CPlusPlus11 && - (!L.MicrosoftExt || L.isCompatibleWithMSVC(LangOptions::MSVC2015)); -} - static void DiagnoseNarrowingInInitList(Sema &S, const ImplicitConversionSequence &ICS, QualType PreNarrowingType, @@ -10402,6 +10397,19 @@ static void DiagnoseNarrowingInInitList(Sema &S, return; } + auto MakeDiag = [&](bool IsConstRef, unsigned DefaultDiagID, + unsigned ConstRefDiagID, unsigned WarnDiagID) { + unsigned DiagID; + auto &L = S.getLangOpts(); + if (L.CPlusPlus11 && + (!L.MicrosoftExt || L.isCompatibleWithMSVC(LangOptions::MSVC2015))) + DiagID = IsConstRef ? ConstRefDiagID : DefaultDiagID; + else + DiagID = WarnDiagID; + return S.Diag(PostInit->getBeginLoc(), DiagID) + << PostInit->getSourceRange(); + }; + // C++11 [dcl.init.list]p7: Check whether this is a narrowing conversion. APValue ConstantValue; QualType ConstantType; @@ -10417,13 +10425,9 @@ static void DiagnoseNarrowingInInitList(Sema &S, // narrowing conversion even if the value is a constant and can be // represented exactly as an integer. QualType T = EntityType.getNonReferenceType(); - S.Diag(PostInit->getBeginLoc(), - NarrowingErrs(S.getLangOpts()) - ? (T == EntityType - ? diag::ext_init_list_type_narrowing - : diag::ext_init_list_type_narrowing_const_reference) - : diag::warn_init_list_type_narrowing) - << PostInit->getSourceRange() + MakeDiag(T != EntityType, diag::ext_init_list_type_narrowing, + diag::ext_init_list_type_narrowing_const_reference, + diag::warn_init_list_type_narrowing) << PreNarrowingType.getLocalUnqualifiedType() << T.getLocalUnqualifiedType(); break; @@ -10431,14 +10435,10 @@ static void DiagnoseNarrowingInInitList(Sema &S, case NK_Constant_Narrowing: { // A constant value was narrowed. - QualType T = EntityType.getNonReferenceType(); - S.Diag(PostInit->getBeginLoc(), - NarrowingErrs(S.getLangOpts()) - ? (T == EntityType - ? diag::ext_init_list_constant_narrowing - : diag::ext_init_list_constant_narrowing_const_reference) - : diag::warn_init_list_constant_narrowing) - << PostInit->getSourceRange() + MakeDiag(EntityType.getNonReferenceType() != EntityType, + diag::ext_init_list_constant_narrowing, + diag::ext_init_list_constant_narrowing_const_reference, + diag::warn_init_list_constant_narrowing) << ConstantValue.getAsString(S.getASTContext(), ConstantType) << EntityType.getNonReferenceType().getLocalUnqualifiedType(); break; @@ -10446,14 +10446,10 @@ static void DiagnoseNarrowingInInitList(Sema &S, case NK_Variable_Narrowing: { // A variable's value may have been narrowed. - QualType T = EntityType.getNonReferenceType(); - S.Diag(PostInit->getBeginLoc(), - NarrowingErrs(S.getLangOpts()) - ? (T == EntityType - ? diag::ext_init_list_variable_narrowing - : diag::ext_init_list_variable_narrowing_const_reference) - : diag::warn_init_list_variable_narrowing) - << PostInit->getSourceRange() + MakeDiag(EntityType.getNonReferenceType() != EntityType, + diag::ext_init_list_variable_narrowing, + diag::ext_init_list_variable_narrowing_const_reference, + diag::warn_init_list_variable_narrowing) << PreNarrowingType.getLocalUnqualifiedType() << EntityType.getNonReferenceType().getLocalUnqualifiedType(); break; diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index f34d2959dc619143cb7e2987947af6d4baba42ea..365032c964212395d03d0f27ffa2d027124284fa 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -5072,6 +5072,18 @@ static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack, CurrentRegion != OMPD_cancellation_point && CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_scan) return false; + // Checks needed for mapping "loop" construct. Please check mapLoopConstruct + // for a detailed explanation + if (SemaRef.LangOpts.OpenMP >= 50 && CurrentRegion == OMPD_loop && + (BindKind == OMPC_BIND_parallel || BindKind == OMPC_BIND_teams) && + (isOpenMPWorksharingDirective(ParentRegion) || + ParentRegion == OMPD_loop)) { + int ErrorMsgNumber = (BindKind == OMPC_BIND_parallel) ? 1 : 4; + SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region) + << true << getOpenMPDirectiveName(ParentRegion) << ErrorMsgNumber + << getOpenMPDirectiveName(CurrentRegion); + return true; + } if (CurrentRegion == OMPD_cancellation_point || CurrentRegion == OMPD_cancel) { // OpenMP [2.16, Nesting of Regions] @@ -6124,21 +6136,25 @@ processImplicitMapsWithDefaultMappers(Sema &S, DSAStackTy *Stack, bool Sema::mapLoopConstruct(llvm::SmallVector &ClausesWithoutBind, ArrayRef Clauses, - OpenMPBindClauseKind BindKind, + OpenMPBindClauseKind &BindKind, OpenMPDirectiveKind &Kind, - OpenMPDirectiveKind &PrevMappedDirective) { + OpenMPDirectiveKind &PrevMappedDirective, + SourceLocation StartLoc, SourceLocation EndLoc, + const DeclarationNameInfo &DirName, + OpenMPDirectiveKind CancelRegion) { bool UseClausesWithoutBind = false; // Restricting to "#pragma omp loop bind" if (getLangOpts().OpenMP >= 50 && Kind == OMPD_loop) { + + const OpenMPDirectiveKind ParentDirective = DSAStack->getParentDirective(); + if (BindKind == OMPC_BIND_unknown) { // Setting the enclosing teams or parallel construct for the loop // directive without bind clause. BindKind = OMPC_BIND_thread; // Default bind(thread) if binding is unknown - const OpenMPDirectiveKind ParentDirective = - DSAStack->getParentDirective(); if (ParentDirective == OMPD_unknown) { Diag(DSAStack->getDefaultDSALocation(), diag::err_omp_bind_required_on_loop); @@ -6150,9 +6166,10 @@ bool Sema::mapLoopConstruct(llvm::SmallVector &ClausesWithoutBind, BindKind = OMPC_BIND_teams; } } else { - // bind clause is present, so we should set flag indicating to only - // use the clauses that aren't the bind clause for the new directive that - // loop is lowered to. + // bind clause is present in loop directive. When the loop directive is + // changed to a new directive the bind clause is not used. So, we should + // set flag indicating to only use the clauses that aren't the + // bind clause. UseClausesWithoutBind = true; } @@ -6213,26 +6230,35 @@ StmtResult Sema::ActOnOpenMPExecutableDirective( OpenMPDirectiveKind PrevMappedDirective) { StmtResult Res = StmtError(); OpenMPBindClauseKind BindKind = OMPC_BIND_unknown; + llvm::SmallVector ClausesWithoutBind; + bool UseClausesWithoutBind = false; + if (const OMPBindClause *BC = OMPExecutableDirective::getSingleClause(Clauses)) BindKind = BC->getBindKind(); + + // Variable used to note down the DirectiveKind because mapLoopConstruct may + // change "Kind" variable, due to mapping of "omp loop" to other directives. + OpenMPDirectiveKind DK = Kind; + if (Kind == OMPD_loop || PrevMappedDirective == OMPD_loop) { + UseClausesWithoutBind = mapLoopConstruct( + ClausesWithoutBind, Clauses, BindKind, Kind, PrevMappedDirective, + StartLoc, EndLoc, DirName, CancelRegion); + DK = OMPD_loop; + } + // First check CancelRegion which is then used in checkNestingOfRegions. if (checkCancelRegion(*this, Kind, CancelRegion, StartLoc) || - checkNestingOfRegions(*this, DSAStack, Kind, DirName, CancelRegion, - BindKind, StartLoc)) + checkNestingOfRegions(*this, DSAStack, DK, DirName, CancelRegion, + BindKind, StartLoc)) { return StmtError(); + } // Report affected OpenMP target offloading behavior when in HIP lang-mode. if (getLangOpts().HIP && (isOpenMPTargetExecutionDirective(Kind) || isOpenMPTargetDataManagementDirective(Kind))) Diag(StartLoc, diag::warn_hip_omp_target_directives); - llvm::SmallVector ClausesWithoutBind; - bool UseClausesWithoutBind = false; - - UseClausesWithoutBind = mapLoopConstruct(ClausesWithoutBind, Clauses, - BindKind, Kind, PrevMappedDirective); - llvm::SmallVector ClausesWithImplicit; VarsWithInheritedDSAType VarsWithInheritedDSA; bool ErrorFound = false; diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 9fb767101e1eb7aa14c6866d48e976da27dc8966..23b9bc0fe2d6e2e16588432b00d58e3234f59a08 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -1259,6 +1259,43 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, FunctionDecl *New, if ((OldTemplate == nullptr) != (NewTemplate == nullptr)) return true; + if (NewTemplate) { + // C++ [temp.over.link]p4: + // The signature of a function template consists of its function + // signature, its return type and its template parameter list. The names + // of the template parameters are significant only for establishing the + // relationship between the template parameters and the rest of the + // signature. + // + // We check the return type and template parameter lists for function + // templates first; the remaining checks follow. + bool SameTemplateParameterList = SemaRef.TemplateParameterListsAreEqual( + NewTemplate, NewTemplate->getTemplateParameters(), OldTemplate, + OldTemplate->getTemplateParameters(), false, Sema::TPL_TemplateMatch); + bool SameReturnType = SemaRef.Context.hasSameType( + Old->getDeclaredReturnType(), New->getDeclaredReturnType()); + // FIXME(GH58571): Match template parameter list even for non-constrained + // template heads. This currently ensures that the code prior to C++20 is + // not newly broken. + bool ConstraintsInTemplateHead = + NewTemplate->getTemplateParameters()->hasAssociatedConstraints() || + OldTemplate->getTemplateParameters()->hasAssociatedConstraints(); + // C++ [namespace.udecl]p11: + // The set of declarations named by a using-declarator that inhabits a + // class C does not include member functions and member function + // templates of a base class that "correspond" to (and thus would + // conflict with) a declaration of a function or function template in + // C. + // Comparing return types is not required for the "correspond" check to + // decide whether a member introduced by a shadow declaration is hidden. + if (UseMemberUsingDeclRules && ConstraintsInTemplateHead && + !SameTemplateParameterList) + return true; + if (!UseMemberUsingDeclRules && + (!SameTemplateParameterList || !SameReturnType)) + return true; + } + // Is the function New an overload of the function Old? QualType OldQType = SemaRef.Context.getCanonicalType(Old->getType()); QualType NewQType = SemaRef.Context.getCanonicalType(New->getType()); @@ -1410,43 +1447,6 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, FunctionDecl *New, } } - if (NewTemplate) { - // C++ [temp.over.link]p4: - // The signature of a function template consists of its function - // signature, its return type and its template parameter list. The names - // of the template parameters are significant only for establishing the - // relationship between the template parameters and the rest of the - // signature. - // - // We check the return type and template parameter lists for function - // templates first; the remaining checks follow. - bool SameTemplateParameterList = SemaRef.TemplateParameterListsAreEqual( - NewTemplate, NewTemplate->getTemplateParameters(), OldTemplate, - OldTemplate->getTemplateParameters(), false, Sema::TPL_TemplateMatch); - bool SameReturnType = SemaRef.Context.hasSameType( - Old->getDeclaredReturnType(), New->getDeclaredReturnType()); - // FIXME(GH58571): Match template parameter list even for non-constrained - // template heads. This currently ensures that the code prior to C++20 is - // not newly broken. - bool ConstraintsInTemplateHead = - NewTemplate->getTemplateParameters()->hasAssociatedConstraints() || - OldTemplate->getTemplateParameters()->hasAssociatedConstraints(); - // C++ [namespace.udecl]p11: - // The set of declarations named by a using-declarator that inhabits a - // class C does not include member functions and member function - // templates of a base class that "correspond" to (and thus would - // conflict with) a declaration of a function or function template in - // C. - // Comparing return types is not required for the "correspond" check to - // decide whether a member introduced by a shadow declaration is hidden. - if (UseMemberUsingDeclRules && ConstraintsInTemplateHead && - !SameTemplateParameterList) - return true; - if (!UseMemberUsingDeclRules && - (!SameTemplateParameterList || !SameReturnType)) - return true; - } - if (!UseOverrideRules) { Expr *NewRC = New->getTrailingRequiresClause(), *OldRC = Old->getTrailingRequiresClause(); @@ -6056,6 +6056,16 @@ static ExprResult BuildConvertedConstantExpression(Sema &S, Expr *From, diag::err_typecheck_converted_constant_expression_indirect) << From->getType() << From->getSourceRange() << T; } + // 'TryCopyInitialization' returns incorrect info for attempts to bind + // a reference to a bit-field due to C++ [over.ics.ref]p4. Namely, + // 'SCS->DirectBinding' occurs to be set to 'true' despite it is not + // the direct binding according to C++ [dcl.init.ref]p5. Hence, check this + // case explicitly. + if (From->refersToBitField() && T.getTypePtr()->isReferenceType()) { + return S.Diag(From->getBeginLoc(), + diag::err_reference_bind_to_bitfield_in_cce) + << From->getSourceRange(); + } // Usually we can simply apply the ImplicitConversionSequence we formed // earlier, but that's not guaranteed to work when initializing an object of @@ -7713,9 +7723,19 @@ bool Sema::CheckNonDependentConversions( ++I) { QualType ParamType = ParamTypes[I + Offset]; if (!ParamType->isDependentType()) { - unsigned ConvIdx = PO == OverloadCandidateParamOrder::Reversed - ? 0 - : (ThisConversions + I); + unsigned ConvIdx; + if (PO == OverloadCandidateParamOrder::Reversed) { + ConvIdx = Args.size() - 1 - I; + assert(Args.size() + ThisConversions == 2 && + "number of args (including 'this') must be exactly 2 for " + "reversed order"); + // For members, there would be only one arg 'Args[0]' whose ConvIdx + // would also be 0. 'this' got ConvIdx = 1 previously. + assert(!HasThisConversion || (ConvIdx == 0 && I == 0)); + } else { + // For members, 'this' got ConvIdx = 0 previously. + ConvIdx = ThisConversions + I; + } Conversions[ConvIdx] = TryCopyInitialization(*this, Args[I], ParamType, SuppressUserConversions, @@ -10111,11 +10131,23 @@ getImplicitObjectParamType(ASTContext &Context, const FunctionDecl *F) { return M->getFunctionObjectParameterReferenceType(); } -static bool haveSameParameterTypes(ASTContext &Context, const FunctionDecl *F1, - const FunctionDecl *F2) { +// As a Clang extension, allow ambiguity among F1 and F2 if they represent +// represent the same entity. +static bool allowAmbiguity(ASTContext &Context, const FunctionDecl *F1, + const FunctionDecl *F2) { if (declaresSameEntity(F1, F2)) return true; - + auto PT1 = F1->getPrimaryTemplate(); + auto PT2 = F2->getPrimaryTemplate(); + if (PT1 && PT2) { + if (declaresSameEntity(PT1, PT2) || + declaresSameEntity(PT1->getInstantiatedFromMemberTemplate(), + PT2->getInstantiatedFromMemberTemplate())) + return true; + } + // TODO: It is not clear whether comparing parameters is necessary (i.e. + // different functions with same params). Consider removing this (as no test + // fail w/o it). auto NextParam = [&](const FunctionDecl *F, unsigned &I, bool First) { if (First) { if (std::optional T = getImplicitObjectParamType(Context, F)) @@ -10319,14 +10351,14 @@ bool clang::isBetterOverloadCandidate( case ImplicitConversionSequence::Worse: if (Cand1.Function && Cand2.Function && Cand1.isReversed() != Cand2.isReversed() && - haveSameParameterTypes(S.Context, Cand1.Function, Cand2.Function)) { + allowAmbiguity(S.Context, Cand1.Function, Cand2.Function)) { // Work around large-scale breakage caused by considering reversed // forms of operator== in C++20: // - // When comparing a function against a reversed function with the same - // parameter types, if we have a better conversion for one argument and - // a worse conversion for the other, the implicit conversion sequences - // are treated as being equally good. + // When comparing a function against a reversed function, if we have a + // better conversion for one argument and a worse conversion for the + // other, the implicit conversion sequences are treated as being equally + // good. // // This prevents a comparison function from being considered ambiguous // with a reversed form that is written in the same way. @@ -13994,21 +14026,19 @@ ExprResult Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn, OverloadCandidateSet::iterator Best; OverloadingResult OverloadResult = CandidateSet.BestViableFunction(*this, Fn->getBeginLoc(), Best); - FunctionDecl *FDecl = Best->Function; // Model the case with a call to a templated function whose definition // encloses the call and whose return type contains a placeholder type as if // the UnresolvedLookupExpr was type-dependent. - if (OverloadResult == OR_Success && FDecl && - FDecl->isTemplateInstantiation() && - FDecl->getReturnType()->isUndeducedType()) { - if (auto TP = FDecl->getTemplateInstantiationPattern(false)) { - if (TP->willHaveBody()) { - CallExpr *CE = - CallExpr::Create(Context, Fn, Args, Context.DependentTy, VK_PRValue, - RParenLoc, CurFPFeatureOverrides()); - result = CE; - return result; + if (OverloadResult == OR_Success) { + const FunctionDecl *FDecl = Best->Function; + if (FDecl && FDecl->isTemplateInstantiation() && + FDecl->getReturnType()->isUndeducedType()) { + if (const auto *TP = + FDecl->getTemplateInstantiationPattern(/*ForDefinition=*/false); + TP && TP->willHaveBody()) { + return CallExpr::Create(Context, Fn, Args, Context.DependentTy, + VK_PRValue, RParenLoc, CurFPFeatureOverrides()); } } } @@ -14518,7 +14548,7 @@ ExprResult Sema::CreateOverloadedBinOp(SourceLocation OpLoc, llvm::SmallVector AmbiguousWith; for (OverloadCandidate &Cand : CandidateSet) { if (Cand.Viable && Cand.Function && Cand.isReversed() && - haveSameParameterTypes(Context, Cand.Function, FnDecl)) { + allowAmbiguity(Context, Cand.Function, FnDecl)) { for (unsigned ArgIdx = 0; ArgIdx < 2; ++ArgIdx) { if (CompareImplicitConversionSequences( *this, OpLoc, Cand.Conversions[ArgIdx], diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index f0b03db690843a4219f02008aa8c57e8be94eb03..21efe25ed84a3d2d218c805465b96183b5bc4859 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -3200,7 +3200,7 @@ static void DiagnoseForRangeConstVariableCopies(Sema &SemaRef, // (The function `getTypeSize` returns the size in bits.) ASTContext &Ctx = SemaRef.Context; if (Ctx.getTypeSize(VariableType) <= 64 * 8 && - (VariableType.isTriviallyCopyableType(Ctx) || + (VariableType.isTriviallyCopyConstructibleType(Ctx) || hasTrivialABIAttr(VariableType))) return; diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 7f20413c104e9746b895f5dfcdd877b298303fa3..fc80515b45e35b43a0b871507a11325f8fe0db1a 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -223,6 +223,9 @@ Response HandleFunction(const FunctionDecl *Function, (!Pattern || !Pattern->getLexicalDeclContext()->isFileContext())) { return Response::ChangeDecl(Function->getLexicalDeclContext()); } + + if (ForConstraintInstantiation && Function->getFriendObjectKind()) + return Response::ChangeDecl(Function->getLexicalDeclContext()); return Response::UseNextDecl(Function); } diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index c8c5a51bf9f94e7d33a4862679237c346327854a..1a1bc87d2b3203c7f610c51df6ecf8fa4a9377fe 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -6192,6 +6192,13 @@ bool TreeTransform::TransformExceptionSpec( // Instantiate a dynamic noexcept expression, if any. if (isComputedNoexcept(ESI.Type)) { + // Update this scrope because ContextDecl in Sema will be used in + // TransformExpr. + auto *Method = dyn_cast_if_present(ESI.SourceTemplate); + Sema::CXXThisScopeRAII ThisScope( + SemaRef, Method ? Method->getParent() : nullptr, + Method ? Method->getMethodQualifiers() : Qualifiers{}, + Method != nullptr); EnterExpressionEvaluationContext Unevaluated( getSema(), Sema::ExpressionEvaluationContext::ConstantEvaluated); ExprResult NoexceptExpr = getDerived().TransformExpr(ESI.NoexceptExpr); @@ -7732,7 +7739,11 @@ TreeTransform::TransformIfStmt(IfStmt *S) { if (Then.isInvalid()) return StmtError(); } else { - Then = new (getSema().Context) NullStmt(S->getThen()->getBeginLoc()); + // Discarded branch is replaced with empty CompoundStmt so we can keep + // proper source location for start and end of original branch, so + // subsequent transformations like CoverageMapping work properly + Then = new (getSema().Context) + CompoundStmt(S->getThen()->getBeginLoc(), S->getThen()->getEndLoc()); } // Transform the "else" branch. @@ -7741,6 +7752,13 @@ TreeTransform::TransformIfStmt(IfStmt *S) { Else = getDerived().TransformStmt(S->getElse()); if (Else.isInvalid()) return StmtError(); + } else if (S->getElse() && ConstexprConditionValue && + *ConstexprConditionValue) { + // Same thing here as with branch, we are discarding it, we can't + // replace it with NULL nor NullStmt as we need to keep for source location + // range, for CoverageMapping + Else = new (getSema().Context) + CompoundStmt(S->getElse()->getBeginLoc(), S->getElse()->getEndLoc()); } if (!getDerived().AlwaysRebuild() && diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 9effd333daccdb2061e2e7c52929984dd3d32407..287f9a0300be5cb93fa06cf85cc7b00a099876bf 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -3037,12 +3037,17 @@ ASTReader::ReadControlBlock(ModuleFile &F, // location info are setup, in ReadAST. SourceLocation ImportLoc = ReadUntranslatedSourceLocation(Record[Idx++]); - off_t StoredSize = (off_t)Record[Idx++]; - time_t StoredModTime = (time_t)Record[Idx++]; - auto FirstSignatureByte = Record.begin() + Idx; - ASTFileSignature StoredSignature = ASTFileSignature::create( - FirstSignatureByte, FirstSignatureByte + ASTFileSignature::size); - Idx += ASTFileSignature::size; + off_t StoredSize = !IsImportingStdCXXModule ? (off_t)Record[Idx++] : 0; + time_t StoredModTime = + !IsImportingStdCXXModule ? (time_t)Record[Idx++] : 0; + + ASTFileSignature StoredSignature; + if (!IsImportingStdCXXModule) { + auto FirstSignatureByte = Record.begin() + Idx; + StoredSignature = ASTFileSignature::create( + FirstSignatureByte, FirstSignatureByte + ASTFileSignature::size); + Idx += ASTFileSignature::size; + } std::string ImportedName = ReadString(Record, Idx); std::string ImportedFile; @@ -3057,18 +3062,19 @@ ASTReader::ReadControlBlock(ModuleFile &F, ImportedFile = PP.getHeaderSearchInfo().getPrebuiltModuleFileName( ImportedName, /*FileMapOnly*/ !IsImportingStdCXXModule); - if (ImportedFile.empty()) { - // It is deprecated for C++20 Named modules to use the implicitly - // paths. - if (IsImportingStdCXXModule) - Diag(clang::diag::warn_reading_std_cxx_module_by_implicit_paths) - << ImportedName; - - // Use BaseDirectoryAsWritten to ensure we use the same path in the - // ModuleCache as when writing. - ImportedFile = ReadPath(BaseDirectoryAsWritten, Record, Idx); - } else - SkipPath(Record, Idx); + // For C++20 Modules, we won't record the path to the imported modules + // in the BMI + if (!IsImportingStdCXXModule) { + if (ImportedFile.empty()) { + // Use BaseDirectoryAsWritten to ensure we use the same path in the + // ModuleCache as when writing. + ImportedFile = ReadPath(BaseDirectoryAsWritten, Record, Idx); + } else + SkipPath(Record, Idx); + } else if (ImportedFile.empty()) { + Diag(clang::diag::err_failed_to_find_module_file) << ImportedName; + return Missing; + } // If our client can't cope with us being out of date, we can't cope with // our dependency being missing. @@ -5584,8 +5590,23 @@ bool ASTReader::readASTFileControlBlock( while (Idx < N) { // Read information about the AST file. - // Kind, StandardCXXModule, ImportLoc, Size, ModTime, Signature - Idx += 1 + 1 + 1 + 1 + 1 + ASTFileSignature::size; + // Skip Kind + Idx++; + bool IsStandardCXXModule = Record[Idx++]; + + // Skip ImportLoc + Idx++; + + // In C++20 Modules, we don't record the path to imported + // modules in the BMI files. + if (IsStandardCXXModule) { + std::string ModuleName = ReadString(Record, Idx); + Listener.visitImport(ModuleName, /*Filename=*/""); + continue; + } + + // Skip Size, ModTime and Signature + Idx += 1 + 1 + ASTFileSignature::size; std::string ModuleName = ReadString(Record, Idx); std::string Filename = ReadString(Record, Idx); ResolveImportedPath(Filename, ModuleDir); diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 78939bfd533ffa541ec43ee3421414cdb5fb5de8..9950fa9c08faaad63200742b9c6d2c76b6fb32ed 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -1411,15 +1411,20 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context, Record.push_back(M.StandardCXXModule); AddSourceLocation(M.ImportLoc, Record); - // 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 : getTimestampForOutput(M.File)); - - llvm::append_range(Record, M.Signature); + // We don't want to hard code the information about imported modules + // in the C++20 named modules. + if (!M.StandardCXXModule) { + // 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 : getTimestampForOutput(M.File)); + llvm::append_range(Record, M.Signature); + } AddString(M.ModuleName, Record); - AddPath(M.FileName, Record); + + if (!M.StandardCXXModule) + AddPath(M.FileName, Record); } Stream.EmitRecord(IMPORTS, Record); } diff --git a/clang/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp index de9efe17d220b16d3ccd47600eeaf6e4c0a26ba5..812d787e2e37c494538eff648588081f038fa611 100644 --- a/clang/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp @@ -712,7 +712,7 @@ void NonLocalizedStringChecker::setNonLocalizedState(const SVal S, static bool isDebuggingName(std::string name) { - return StringRef(name).lower().find("debug") != StringRef::npos; + return StringRef(name).contains_insensitive("debug"); } /// Returns true when, heuristically, the analyzer may be analyzing debugging @@ -1248,8 +1248,8 @@ bool PluralMisuseChecker::MethodCrawler::isCheckingPlurality( BO = B; } } - if (VD->getName().lower().find("plural") != StringRef::npos || - VD->getName().lower().find("singular") != StringRef::npos) { + if (VD->getName().contains_insensitive("plural") || + VD->getName().contains_insensitive("singular")) { return true; } } diff --git a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp index 20068653d530a38aa5c96d9b18627f392e12f537..3b36565681a7f33e2ddb1ce9801c11480818eb89 100644 --- a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp @@ -2201,6 +2201,25 @@ void StdLibraryFunctionsChecker::initFunctionSummaries( ErrnoNEZeroIrrelevant, GenericFailureMsg) .ArgConstraint(NotNull(ArgNo(0)))); + // int ungetc(int c, FILE *stream); + addToFunctionSummaryMap( + "ungetc", Signature(ArgTypes{IntTy, FilePtrTy}, RetType{IntTy}), + Summary(NoEvalCall) + .Case({ReturnValueCondition(BO_EQ, ArgNo(0)), + ArgumentCondition(0, WithinRange, {{0, UCharRangeMax}})}, + ErrnoMustNotBeChecked, GenericSuccessMsg) + .Case({ReturnValueCondition(WithinRange, SingleValue(EOFv)), + ArgumentCondition(0, WithinRange, {{EOFv, EOFv}})}, + ErrnoNEZeroIrrelevant, + "Assuming that 'ungetc' fails because EOF was passed as " + "character") + .Case({ReturnValueCondition(WithinRange, SingleValue(EOFv)), + ArgumentCondition(0, WithinRange, {{0, UCharRangeMax}})}, + ErrnoNEZeroIrrelevant, GenericFailureMsg) + .ArgConstraint(ArgumentCondition( + 0, WithinRange, {{EOFv, EOFv}, {0, UCharRangeMax}})) + .ArgConstraint(NotNull(ArgNo(1)))); + // int fseek(FILE *stream, long offset, int whence); // FIXME: It can be possible to get the 'SEEK_' values (like EOFv) and use // these for condition of arg 2. @@ -2255,7 +2274,7 @@ void StdLibraryFunctionsChecker::initFunctionSummaries( addToFunctionSummaryMap( "ftell", Signature(ArgTypes{FilePtrTy}, RetType{LongTy}), Summary(NoEvalCall) - .Case({ReturnValueCondition(WithinRange, Range(1, LongMax))}, + .Case({ReturnValueCondition(WithinRange, Range(0, LongMax))}, ErrnoUnchanged, GenericSuccessMsg) .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant, GenericFailureMsg) .ArgConstraint(NotNull(ArgNo(0)))); @@ -2516,10 +2535,21 @@ void StdLibraryFunctionsChecker::initFunctionSummaries( .ArgConstraint(NotNull(ArgNo(0)))); // char *getcwd(char *buf, size_t size); - // FIXME: Improve for errno modeling. addToFunctionSummaryMap( "getcwd", Signature(ArgTypes{CharPtrTy, SizeTy}, RetType{CharPtrTy}), Summary(NoEvalCall) + .Case({ArgumentCondition(1, WithinRange, Range(1, SizeMax)), + ReturnValueCondition(BO_EQ, ArgNo(0))}, + ErrnoMustNotBeChecked, GenericSuccessMsg) + .Case({ArgumentCondition(1, WithinRange, SingleValue(0)), + IsNull(Ret)}, + ErrnoNEZeroIrrelevant, "Assuming that argument 'size' is 0") + .Case({ArgumentCondition(1, WithinRange, Range(1, SizeMax)), + IsNull(Ret)}, + ErrnoNEZeroIrrelevant, GenericFailureMsg) + .ArgConstraint(NotNull(ArgNo(0))) + .ArgConstraint( + BufferSize(/*Buffer*/ ArgNo(0), /*BufSize*/ ArgNo(1))) .ArgConstraint( ArgumentCondition(1, WithinRange, Range(0, SizeMax)))); diff --git a/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp index 25da3c18e8519fe82fbf75b3f83df7524be40e9e..95c7503e49e0d32fdf1743f5dd2282b49d82caef 100644 --- a/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp @@ -263,10 +263,20 @@ private: {{{"fputs"}, 2}, {std::bind(&StreamChecker::preReadWrite, _1, _2, _3, _4, false), std::bind(&StreamChecker::evalFputx, _1, _2, _3, _4, false), 1}}, + {{{"fprintf"}}, + {std::bind(&StreamChecker::preReadWrite, _1, _2, _3, _4, false), + std::bind(&StreamChecker::evalFprintf, _1, _2, _3, _4), 0}}, + {{{"ungetc"}, 2}, + {std::bind(&StreamChecker::preReadWrite, _1, _2, _3, _4, false), + std::bind(&StreamChecker::evalUngetc, _1, _2, _3, _4), 1}}, {{{"fseek"}, 3}, {&StreamChecker::preFseek, &StreamChecker::evalFseek, 0}}, + {{{"fseeko"}, 3}, + {&StreamChecker::preFseek, &StreamChecker::evalFseek, 0}}, {{{"ftell"}, 1}, {&StreamChecker::preDefault, &StreamChecker::evalFtell, 0}}, + {{{"ftello"}, 1}, + {&StreamChecker::preDefault, &StreamChecker::evalFtell, 0}}, {{{"fflush"}, 1}, {&StreamChecker::preFflush, &StreamChecker::evalFflush, 0}}, {{{"rewind"}, 1}, @@ -332,6 +342,12 @@ private: void evalFputx(const FnDescription *Desc, const CallEvent &Call, CheckerContext &C, bool IsSingleChar) const; + void evalFprintf(const FnDescription *Desc, const CallEvent &Call, + CheckerContext &C) const; + + void evalUngetc(const FnDescription *Desc, const CallEvent &Call, + CheckerContext &C) const; + void preFseek(const FnDescription *Desc, const CallEvent &Call, CheckerContext &C) const; void evalFseek(const FnDescription *Desc, const CallEvent &Call, @@ -916,6 +932,88 @@ void StreamChecker::evalFputx(const FnDescription *Desc, const CallEvent &Call, C.addTransition(StateFailed); } +void StreamChecker::evalFprintf(const FnDescription *Desc, + const CallEvent &Call, + CheckerContext &C) const { + ProgramStateRef State = C.getState(); + if (Call.getNumArgs() < 2) + return; + SymbolRef StreamSym = getStreamArg(Desc, Call).getAsSymbol(); + if (!StreamSym) + return; + + const CallExpr *CE = dyn_cast_or_null(Call.getOriginExpr()); + if (!CE) + return; + + const StreamState *OldSS = State->get(StreamSym); + if (!OldSS) + return; + + assertStreamStateOpened(OldSS); + + NonLoc RetVal = makeRetVal(C, CE).castAs(); + State = State->BindExpr(CE, C.getLocationContext(), RetVal); + SValBuilder &SVB = C.getSValBuilder(); + auto &ACtx = C.getASTContext(); + auto Cond = SVB.evalBinOp(State, BO_GE, RetVal, SVB.makeZeroVal(ACtx.IntTy), + SVB.getConditionType()) + .getAs(); + if (!Cond) + return; + ProgramStateRef StateNotFailed, StateFailed; + std::tie(StateNotFailed, StateFailed) = State->assume(*Cond); + + StateNotFailed = + StateNotFailed->set(StreamSym, StreamState::getOpened(Desc)); + C.addTransition(StateNotFailed); + + // Add transition for the failed state. The resulting value of the file + // position indicator for the stream is indeterminate. + StateFailed = StateFailed->set( + StreamSym, StreamState::getOpened(Desc, ErrorFError, true)); + C.addTransition(StateFailed); +} + +void StreamChecker::evalUngetc(const FnDescription *Desc, const CallEvent &Call, + CheckerContext &C) const { + ProgramStateRef State = C.getState(); + SymbolRef StreamSym = getStreamArg(Desc, Call).getAsSymbol(); + if (!StreamSym) + return; + + const CallExpr *CE = dyn_cast_or_null(Call.getOriginExpr()); + if (!CE) + return; + + const StreamState *OldSS = State->get(StreamSym); + if (!OldSS) + return; + + assertStreamStateOpened(OldSS); + + // Generate a transition for the success state. + std::optional PutVal = Call.getArgSVal(0).getAs(); + if (!PutVal) + return; + ProgramStateRef StateNotFailed = + State->BindExpr(CE, C.getLocationContext(), *PutVal); + StateNotFailed = + StateNotFailed->set(StreamSym, StreamState::getOpened(Desc)); + C.addTransition(StateNotFailed); + + // Add transition for the failed state. + // Failure of 'ungetc' does not result in feof or ferror state. + // If the PutVal has value of EofVal the function should "fail", but this is + // the same transition as the success state. + // In this case only one state transition is added by the analyzer (the two + // new states may be similar). + ProgramStateRef StateFailed = bindInt(*EofVal, State, C, CE); + StateFailed = + StateFailed->set(StreamSym, StreamState::getOpened(Desc)); + C.addTransition(StateFailed); +} + void StreamChecker::preFseek(const FnDescription *Desc, const CallEvent &Call, CheckerContext &C) const { ProgramStateRef State = C.getState(); @@ -1068,10 +1166,10 @@ void StreamChecker::evalFtell(const FnDescription *Desc, const CallEvent &Call, NonLoc RetVal = makeRetVal(C, CE).castAs(); ProgramStateRef StateNotFailed = State->BindExpr(CE, C.getLocationContext(), RetVal); - auto Cond = SVB.evalBinOp(State, BO_GE, RetVal, - SVB.makeZeroVal(C.getASTContext().LongTy), - SVB.getConditionType()) - .getAs(); + auto Cond = + SVB.evalBinOp(State, BO_GE, RetVal, SVB.makeZeroVal(Call.getResultType()), + SVB.getConditionType()) + .getAs(); if (!Cond) return; StateNotFailed = StateNotFailed->assume(*Cond, true); @@ -1079,7 +1177,7 @@ void StreamChecker::evalFtell(const FnDescription *Desc, const CallEvent &Call, return; ProgramStateRef StateFailed = State->BindExpr( - CE, C.getLocationContext(), SVB.makeIntVal(-1, C.getASTContext().LongTy)); + CE, C.getLocationContext(), SVB.makeIntVal(-1, Call.getResultType())); // This function does not affect the stream state. // Still we add success and failure state with the appropriate return value. diff --git a/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp b/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp index 69d25120dcd43bfb70dc329baebded35b35fda8e..86947b7929e9b6964ad3eb4f43b600253d3bdcda 100644 --- a/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp +++ b/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp @@ -68,6 +68,7 @@ class HTMLDiagnostics : public PathDiagnosticConsumer { bool noDir = false; const Preprocessor &PP; const bool SupportsCrossFileDiagnostics; + llvm::StringSet<> EmittedHashes; public: HTMLDiagnostics(PathDiagnosticConsumerOptions DiagOpts, @@ -301,6 +302,17 @@ void HTMLDiagnostics::ReportDiag(const PathDiagnostic& D, } } + SmallString<32> IssueHash = getIssueHash(D, PP); + auto [It, IsNew] = EmittedHashes.insert(IssueHash); + if (!IsNew) { + // We've already emitted a duplicate issue. It'll get overwritten anyway. + return; + } + + // FIXME: This causes each file to be re-parsed and syntax-highlighted + // and macro-expanded separately for each report. We could cache such rewrites + // across all reports and only re-do the part that's actually different: + // the warning/note bubbles. std::string report = GenerateHTML(D, R, SMgr, path, declName.c_str()); if (report.empty()) { llvm::errs() << "warning: no diagnostics generated for main file.\n"; @@ -332,7 +344,7 @@ void HTMLDiagnostics::ReportDiag(const PathDiagnostic& D, << declName.c_str() << "-" << offsetDecl << "-"; } - FileName << StringRef(getIssueHash(D, PP)).substr(0, 6).str() << ".html"; + FileName << StringRef(IssueHash).substr(0, 6).str() << ".html"; SmallString<128> ResultPath; llvm::sys::path::append(ResultPath, Directory, FileName.str()); diff --git a/clang/test/AST/Interp/arrays.cpp b/clang/test/AST/Interp/arrays.cpp index c455731e76699ffca179adae6f2eee2b05d39edc..4aa10da55dd3aea42ac5ff2729d5597ae654158c 100644 --- a/clang/test/AST/Interp/arrays.cpp +++ b/clang/test/AST/Interp/arrays.cpp @@ -72,6 +72,14 @@ constexpr int getElementFromEnd(const int *Arr, int size, int index) { static_assert(getElementFromEnd(data, 5, 0) == 1, ""); static_assert(getElementFromEnd(data, 5, 4) == 5, ""); +constexpr int getFirstElem(const int *a) { + return a[0]; // expected-note {{read of dereferenced null pointer}} \ + // ref-note {{read of dereferenced null pointer}} +} +static_assert(getFirstElem(nullptr) == 1, ""); // expected-error {{not an integral constant expression}} \ + // expected-note {{in call to}} \ + // ref-error {{not an integral constant expression}} \ + // ref-note {{in call to}} constexpr static int arr[2] = {1,2}; constexpr static int arr2[2] = {3,4}; diff --git a/clang/test/AST/Interp/functions.cpp b/clang/test/AST/Interp/functions.cpp index 179a195098b1327879b16d80791e876be90d3c43..75f3c5d192b2cf2b6ed5a13ca7146634ccaf3262 100644 --- a/clang/test/AST/Interp/functions.cpp +++ b/clang/test/AST/Interp/functions.cpp @@ -389,3 +389,27 @@ namespace Packs { static_assert(foo() == 2, ""); static_assert(foo<>() == 0, ""); } + +namespace AddressOf { + struct S {} s; + static_assert(__builtin_addressof(s) == &s, ""); + + struct T { constexpr T *operator&() const { return nullptr; } int n; } t; + constexpr T *pt = __builtin_addressof(t); + static_assert(&pt->n == &t.n, ""); + + struct U { int n : 5; } u; + int *pbf = __builtin_addressof(u.n); // expected-error {{address of bit-field requested}} \ + // ref-error {{address of bit-field requested}} + + S *ptmp = __builtin_addressof(S{}); // expected-error {{taking the address of a temporary}} \ + // expected-warning {{temporary whose address is used as value of local variable 'ptmp' will be destroyed at the end of the full-expression}} \ + // ref-error {{taking the address of a temporary}} \ + // ref-warning {{temporary whose address is used as value of local variable 'ptmp' will be destroyed at the end of the full-expression}} + + constexpr int foo() {return 1;} + static_assert(__builtin_addressof(foo) == foo, ""); + + constexpr _Complex float F = {3, 4}; + static_assert(__builtin_addressof(F) == &F, ""); +} diff --git a/clang/test/AST/Interp/literals.cpp b/clang/test/AST/Interp/literals.cpp index 85adfe551384d27413f522233eafd640725652cf..61825bc11438f6875df2ecddd5cdad493971c21e 100644 --- a/clang/test/AST/Interp/literals.cpp +++ b/clang/test/AST/Interp/literals.cpp @@ -1024,6 +1024,10 @@ namespace DiscardExprs { __null; __builtin_offsetof(A, a); 1,2; + (int)1.0; + (float)1; + (double)1.0f; + (signed)4u; return 0; } diff --git a/clang/test/AST/ast-dump-coroutine.cpp b/clang/test/AST/ast-dump-coroutine.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5e7736300f9fee8e5155673abc84c3076cad81d4 --- /dev/null +++ b/clang/test/AST/ast-dump-coroutine.cpp @@ -0,0 +1,69 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown %s -std=c++20 \ +// RUN: -fsyntax-only -ast-dump -ast-dump-filter test | FileCheck %s + +#include "Inputs/std-coroutine.h" + +using namespace std; + +struct Task { + struct promise_type { + std::suspend_always initial_suspend() { return {}; } + Task get_return_object() { + return std::coroutine_handle::from_promise(*this); + } + std::suspend_always final_suspend() noexcept { return {}; } + std::suspend_always return_void() { return {}; } + void unhandled_exception() {} + + auto await_transform(int s) { + struct awaiter { + promise_type *promise; + bool await_ready() { return true; } + int await_resume() { return 1; } + void await_suspend(std::coroutine_handle<>) {} + }; + + return awaiter{this}; + } + }; + + Task(std::coroutine_handle promise); + + std::coroutine_handle handle; +}; + +Task test() { + co_await 1; +// Writen souce code, verify no implicit bit for the co_await expr. +// CHECK: CompoundStmt {{.*}} +// CHECK-NEXT: | `-ExprWithCleanups {{.*}} 'int' +// CHECK-NEXT: | `-CoawaitExpr {{.*}} 'int'{{$}} +// CHECK-NEXT: | |-IntegerLiteral {{.*}} 'int' 1 +// CHECK-NEXT: | |-MaterializeTemporaryExpr {{.*}} 'awaiter' +// CHECK-NEXT: | | `-CXXMemberCallExpr {{.*}} 'awaiter' +// CHECK-NEXT: | | |-MemberExpr {{.*}} .await_transform +} +// Verify the implicit AST nodes for coroutines. +// CHECK: |-DeclStmt {{.*}} +// CHECK-NEXT: | `-VarDecl {{.*}} implicit used __promise +// CHECK-NEXT: | `-CXXConstructExpr {{.*}} +// CHECK-NEXT: |-ExprWithCleanups {{.*}} 'void' +// CHECK-NEXT: | `-CoawaitExpr {{.*}} 'void' implicit +// CHECK-NEXT: |-CXXMemberCallExpr {{.*}} 'std::suspend_always' +// CHECK-NEXT: | | `-MemberExpr {{.*}} .initial_suspend +// ... +// FIXME: the CoreturnStmt should be marked as implicit +// CHECK: CoreturnStmt {{.*}} {{$}} + +Task test2() { +// Writen souce code, verify no implicit bit for the co_return expr. +// CHECK: CompoundStmt {{.*}} +// CHECK-NEXT: | `-CoreturnStmt {{.*}} {{$}} + co_return; +} +// Verify the implicit AST nodes for coroutines. +// CHECK: |-DeclStmt {{.*}} +// CHECK-NEXT: | `-VarDecl {{.*}} implicit used __promise +// ... +// FIXME: the CoreturnStmt should be marked as implicit +// CHECK: CoreturnStmt {{.*}} {{$}} diff --git a/clang/test/Analysis/Inputs/system-header-simulator.h b/clang/test/Analysis/Inputs/system-header-simulator.h index 8c43c48c6a3e453ca77d573afe1e45068fe00663..cd7ac616bcc67fa97055164e7ddd7a071f19bcee 100644 --- a/clang/test/Analysis/Inputs/system-header-simulator.h +++ b/clang/test/Analysis/Inputs/system-header-simulator.h @@ -13,6 +13,7 @@ typedef __typeof(sizeof(int)) size_t; typedef long long __int64_t; typedef __int64_t __darwin_off_t; typedef __darwin_off_t fpos_t; +typedef int off_t; typedef struct _FILE FILE; #define SEEK_SET 0 /* Seek from beginning of file. */ @@ -53,8 +54,11 @@ int fgetc(FILE *stream); char *fgets(char *restrict str, int count, FILE *restrict stream); int fputc(int ch, FILE *stream); int fputs(const char *restrict s, FILE *restrict stream); +int ungetc(int c, FILE *stream); int fseek(FILE *__stream, long int __off, int __whence); +int fseeko(FILE *__stream, off_t __off, int __whence); long int ftell(FILE *__stream); +off_t ftello(FILE *__stream); void rewind(FILE *__stream); int fgetpos(FILE *restrict stream, fpos_t *restrict pos); int fsetpos(FILE *stream, const fpos_t *pos); diff --git a/clang/test/Analysis/errno-stdlibraryfunctions.c b/clang/test/Analysis/errno-stdlibraryfunctions.c index 80e14c4e2923cabe2998e0fe6e526d2ae8e2db53..9e3d07e7aa88a0a930da904eed993a7df3dddd00 100644 --- a/clang/test/Analysis/errno-stdlibraryfunctions.c +++ b/clang/test/Analysis/errno-stdlibraryfunctions.c @@ -74,3 +74,18 @@ void errno_mkdtemp(char *template) { if (errno) {} // expected-warning{{An undefined value may be read from 'errno'}} } } + +void errno_getcwd(char *Buf, size_t Sz) { + char *Path = getcwd(Buf, Sz); + if (Sz == 0) { + clang_analyzer_eval(errno != 0); // expected-warning{{TRUE}} + clang_analyzer_eval(Path == NULL); // expected-warning{{TRUE}} + if (errno) {} // no warning + } else if (Path == NULL) { + clang_analyzer_eval(errno != 0); // expected-warning{{TRUE}} + if (errno) {} // no warning + } else { + clang_analyzer_eval(Path == Buf); // expected-warning{{TRUE}} + if (errno) {} // expected-warning{{An undefined value may be read from 'errno'}} + } +} diff --git a/clang/test/Analysis/stream-error.c b/clang/test/Analysis/stream-error.c index 13c6684b5840afcf92773055f4eb48f11edfac04..0f7fdddc0dd4cd775eecebd08a668d4f3e19b9b6 100644 --- a/clang/test/Analysis/stream-error.c +++ b/clang/test/Analysis/stream-error.c @@ -191,6 +191,39 @@ void error_fputs(void) { fputs("ABC", F); // expected-warning {{Stream might be already closed}} } +void error_fprintf(void) { + FILE *F = tmpfile(); + if (!F) + return; + int Ret = fprintf(F, "aaa"); + if (Ret >= 0) { + clang_analyzer_eval(feof(F) || ferror(F)); // expected-warning {{FALSE}} + fprintf(F, "bbb"); // no-warning + } else { + clang_analyzer_eval(ferror(F)); // expected-warning {{TRUE}} + clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}} + fprintf(F, "bbb"); // expected-warning {{might be 'indeterminate'}} + } + fclose(F); + fprintf(F, "ccc"); // expected-warning {{Stream might be already closed}} +} + +void error_ungetc() { + FILE *F = tmpfile(); + if (!F) + return; + int Ret = ungetc('X', F); + clang_analyzer_eval(feof(F) || ferror(F)); // expected-warning {{FALSE}} + if (Ret == EOF) { + clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}} + } else { + clang_analyzer_eval(Ret == 'X'); // expected-warning {{TRUE}} + } + fputc('Y', F); // no-warning + fclose(F); + ungetc('A', F); // expected-warning {{Stream might be already closed}} +} + void write_after_eof_is_allowed(void) { FILE *F = tmpfile(); if (!F) @@ -279,6 +312,25 @@ void error_fseek(void) { fclose(F); } +void error_fseeko(void) { + FILE *F = fopen("file", "r"); + if (!F) + return; + int rc = fseeko(F, 1, SEEK_SET); + if (rc) { + int IsFEof = feof(F), IsFError = ferror(F); + // Get feof or ferror or no error. + clang_analyzer_eval(IsFEof || IsFError); + // expected-warning@-1 {{FALSE}} + // expected-warning@-2 {{TRUE}} + clang_analyzer_eval(IsFEof && IsFError); // expected-warning {{FALSE}} + } else { + clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}} + clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}} + } + fclose(F); +} + void error_fseek_0(void) { FILE *F = fopen("file", "r"); if (!F) @@ -308,6 +360,68 @@ void error_fseek_0(void) { fclose(F); } +void error_fseeko_0(void) { + FILE *F = fopen("file", "r"); + if (!F) + return; + int rc = fseeko(F, 0, SEEK_SET); + if (rc) { + int IsFEof = feof(F), IsFError = ferror(F); + // Get ferror or no error, but not feof. + clang_analyzer_eval(IsFError); + // expected-warning@-1 {{FALSE}} + // expected-warning@-2 {{TRUE}} + clang_analyzer_eval(IsFEof); + // expected-warning@-1 {{FALSE}} + } else { + clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}} + clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}} + } + fclose(F); +} + +void error_ftell(void) { + FILE *F = fopen("file", "r"); + if (!F) + return; + long rc = ftell(F); + if (rc >= 0) + clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}} + else + clang_analyzer_eval(rc == -1); // expected-warning {{TRUE}} + clang_analyzer_eval(feof(F) && ferror(F)); // expected-warning {{FALSE}} + StreamTesterChecker_make_feof_stream(F); + rc = ftell(F); + clang_analyzer_eval(feof(F)); // expected-warning {{TRUE}} + clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}} + StreamTesterChecker_make_ferror_stream(F); + rc = ftell(F); + clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}} + clang_analyzer_eval(ferror(F)); // expected-warning {{TRUE}} + fclose(F); +} + +void error_ftello(void) { + FILE *F = fopen("file", "r"); + if (!F) + return; + off_t rc = ftello(F); + if (rc >= 0) + clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}} + else + clang_analyzer_eval(rc == -1); // expected-warning {{TRUE}} + clang_analyzer_eval(feof(F) && ferror(F)); // expected-warning {{FALSE}} + StreamTesterChecker_make_feof_stream(F); + rc = ftello(F); + clang_analyzer_eval(feof(F)); // expected-warning {{TRUE}} + clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}} + StreamTesterChecker_make_ferror_stream(F); + rc = ftello(F); + clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}} + clang_analyzer_eval(ferror(F)); // expected-warning {{TRUE}} + fclose(F); +} + void error_fflush_after_fclose(void) { FILE *F = tmpfile(); int Ret; diff --git a/clang/test/Analysis/stream-noopen.c b/clang/test/Analysis/stream-noopen.c index 2daf640c18a1d433f0b6eb71ebbc58ba16ad18e3..8ad101ee1e8c135002c15796e06941fb32b37384 100644 --- a/clang/test/Analysis/stream-noopen.c +++ b/clang/test/Analysis/stream-noopen.c @@ -138,6 +138,31 @@ void test_rewind(FILE *F) { rewind(F); } +void test_ungetc(FILE *F) { + int Ret = ungetc('X', F); + clang_analyzer_eval(F != NULL); // expected-warning {{TRUE}} + if (Ret == 'X') { + if (errno) {} // expected-warning {{undefined}} + } else { + clang_analyzer_eval(Ret == EOF); // expected-warning {{TRUE}} + clang_analyzer_eval(errno != 0); // expected-warning {{TRUE}} + } + clang_analyzer_eval(feof(F)); // expected-warning {{UNKNOWN}} + clang_analyzer_eval(ferror(F)); // expected-warning {{UNKNOWN}} +} + +void test_ungetc_EOF(FILE *F, int C) { + int Ret = ungetc(EOF, F); + clang_analyzer_eval(F != NULL); // expected-warning {{TRUE}} + clang_analyzer_eval(Ret == EOF); // expected-warning {{TRUE}} + clang_analyzer_eval(errno != 0); // expected-warning {{TRUE}} + Ret = ungetc(C, F); + if (Ret == EOF) { + clang_analyzer_eval(C == EOF); // expected-warning {{TRUE}} + // expected-warning@-1{{FALSE}} + } +} + void test_feof(FILE *F) { errno = 0; feof(F); diff --git a/clang/test/Analysis/stream.c b/clang/test/Analysis/stream.c index 060d561c1fe1c225b07c174ecd2715c11747db00..e8f06922bdb2f37d73683993d911178e142cab41 100644 --- a/clang/test/Analysis/stream.c +++ b/clang/test/Analysis/stream.c @@ -39,6 +39,18 @@ void check_fputs(void) { fclose(fp); } +void check_fprintf(void) { + FILE *fp = tmpfile(); + fprintf(fp, "ABC"); // expected-warning {{Stream pointer might be NULL}} + fclose(fp); +} + +void check_ungetc(void) { + FILE *fp = tmpfile(); + ungetc('A', fp); // expected-warning {{Stream pointer might be NULL}} + fclose(fp); +} + void check_fseek(void) { FILE *fp = tmpfile(); fseek(fp, 0, 0); // expected-warning {{Stream pointer might be NULL}} @@ -265,9 +277,8 @@ void check_escape4(void) { return; fwrite("1", 1, 1, F); // may fail - // no escape at (non-StreamChecker-handled) system call - // FIXME: all such calls should be handled by the checker - fprintf(F, "0"); + // no escape at a non-StreamChecker-handled system call + setbuf(F, "0"); fwrite("1", 1, 1, F); // expected-warning {{might be 'indeterminate'}} fclose(F); diff --git a/clang/test/CXX/drs/dr12xx.cpp b/clang/test/CXX/drs/dr12xx.cpp index adf7f56711c4519b6c8476614dc02a5e9f98dce5..cb4cc5aef17371145f4cc51f76490cd901efa115 100644 --- a/clang/test/CXX/drs/dr12xx.cpp +++ b/clang/test/CXX/drs/dr12xx.cpp @@ -154,7 +154,7 @@ namespace dr1295 { // dr1295: 4 Y y; // #dr1295-y // cxx98-14-error@-1 {{non-type template argument does not refer to any declaration}} // cxx98-14-note@#dr1295-Y {{template parameter is declared here}} - // since-cxx17-error@#dr1295-y {{non-type template argument refers to subobject 'x.bitfield'}} + // since-cxx17-error@#dr1295-y {{reference cannot bind to bit-field in converted constant expression}} #if __cplusplus >= 201103L const unsigned other = 0; diff --git a/clang/test/CXX/drs/dr17xx.cpp b/clang/test/CXX/drs/dr17xx.cpp index 0c44fb231ce51a7d6b5f1634f3451c8b4ebef60a..885ed00ace0f57be6ee7cb8c9f1b26a736a4311d 100644 --- a/clang/test/CXX/drs/dr17xx.cpp +++ b/clang/test/CXX/drs/dr17xx.cpp @@ -89,6 +89,8 @@ S s(q); // #dr1736-s #endif } +// dr1748 is in dr1748.cpp + namespace dr1753 { // dr1753: 11 typedef int T; struct A { typedef int T; }; @@ -159,6 +161,8 @@ namespace dr1762 { // dr1762: 14 #endif } +// dr1772 is in dr177x.cpp + namespace dr1778 { // dr1778: 9 // Superseded by P1286R2. #if __cplusplus >= 201103L @@ -174,6 +178,8 @@ namespace dr1778 { // dr1778: 9 #endif } +// dr1779 is in dr177x.cpp + namespace dr1794 { // dr1794: yes // NB: dup 1710 #if __cplusplus >= 201103L diff --git a/clang/test/CXX/drs/dr18xx.cpp b/clang/test/CXX/drs/dr18xx.cpp index fbe67bd0c2f6dbbd79b26e8df4c249a0c23a74a7..1d76804907a5c11779ee84592ddadef050456c0b 100644 --- a/clang/test/CXX/drs/dr18xx.cpp +++ b/clang/test/CXX/drs/dr18xx.cpp @@ -1,16 +1,169 @@ -// RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -verify=expected,cxx98 -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -verify=expected,cxx11-17,since-cxx11 -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -verify=expected,cxx11-17,since-cxx11,since-cxx14 -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -verify=expected,cxx11-17,since-cxx11,since-cxx14 -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx20,since-cxx11,since-cxx14 -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx20,since-cxx11,since-cxx14 -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -verify=expected,since-cxx20,since-cxx11,since-cxx14 -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors +// 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,cxx11-17,since-cxx11 -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -verify=expected,cxx98-14,cxx11-17,since-cxx11,since-cxx14 -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx17,cxx11-17,since-cxx11,since-cxx14 -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx17,since-cxx20,since-cxx11,since-cxx14 -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx17,since-cxx20,since-cxx11,since-cxx14 -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -verify=expected,since-cxx17,since-cxx20,since-cxx11,since-cxx14 -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors #if __cplusplus == 199711L #define static_assert(...) __extension__ _Static_assert(__VA_ARGS__) // cxx98-error@-1 {{variadic macros are a C99 feature}} #endif +namespace dr1800 { // dr1800: 2.9 +struct A { union { int n; }; }; +static_assert(__is_same(__decltype(&A::n), int A::*), ""); +} // namespace dr1800 + +namespace dr1801 { // dr1801: 2.8 +static union { + int i; +}; + +template struct S {}; // #dr1801-S +S V; // #dr1801-S-i +// cxx98-14-error@-1 {{non-type template argument does not refer to any declaration}} +// cxx98-14-note@#dr1801-S {{template parameter is declared here}} +// since-cxx17-error@#dr1801-S-i {{non-type template argument refers to subobject '.i'}} +} + +namespace dr1802 { // dr1802: 3.1 +#if __cplusplus >= 201103L +// Using a Wikipedia example of surrogate pair: +// https://en.wikipedia.org/wiki/UTF-16#Examples +constexpr char16_t a[3] = u"\U00010437"; +static_assert(a[0] == 0xD801, ""); +static_assert(a[1] == 0xDC37, ""); +static_assert(a[2] == 0x0, ""); +#endif +} // namespace dr1802 + +namespace dr1803 { // dr1803: 2.9 +#if __cplusplus >= 201103L +struct A { + enum E : int; + enum E : int {}; + enum class EC; + enum class EC {}; + enum struct ES; + enum struct ES {}; +}; +#endif +} // namespace dr1803 + +namespace dr1804 { // dr1804: 2.7 +template +struct A { + void f1(); + + template + void f2(V); + + class B { + void f3(); + }; + + template + class C { + void f4(); + }; +}; + +template +struct A { + void f1(); + + template + void f2(V); + + class B { + void f3(); + }; + + template + class C { + void f4(); + }; +}; + +class D { + int i; + + template + friend struct A; +}; + +template +struct A { + void f1(); + + template + void f2(V); + + class B { + void f3(); + }; + + template + class C { + void f4(); + }; +}; + +template +void A::f1() { + D d; + d.i = 0; +} + +template +void A::f1() { + D d; + d.i = 0; +} + +template +template +void A::f2(V) { + D d; + d.i = 0; +} + +template +template +void A::f2(V) { + D d; + d.i = 0; +} + +template +void A::B::f3() { + D d; + d.i = 0; +} + +template +void A::B::f3() { + D d; + d.i = 0; +} + +template +template +void A::C::f4() { + D d; + d.i = 0; +} + +template +template +void A::C::f4() { + D d; + d.i = 0; +} +} // namespace dr1804 + namespace dr1812 { // dr1812: no // NB: dup 1710 #if __cplusplus >= 201103L diff --git a/clang/test/CXX/drs/dr1xx.cpp b/clang/test/CXX/drs/dr1xx.cpp index 064ecace59067a1ee43f602f957df21fa076e9a6..064b69411f0b5fc9c38e2fb4a7593e204ef31308 100644 --- a/clang/test/CXX/drs/dr1xx.cpp +++ b/clang/test/CXX/drs/dr1xx.cpp @@ -283,7 +283,7 @@ namespace dr116 { // dr116: yes } // dr117: na -// dr118 is in its own file. +// dr118 is in dr118.cpp // dr119: na // dr120: na @@ -789,7 +789,7 @@ namespace dr155 { // dr155: dup 632 // expected-warning@-1 {{braces around scalar initializer}} } -// dr158 is in its own file. +// dr158 is in dr158.cpp namespace dr159 { // dr159: 3.5 namespace X { void f(); } diff --git a/clang/test/CXX/drs/dr23xx.cpp b/clang/test/CXX/drs/dr23xx.cpp index 9ced61d2aae30dc5e4ebf0239802f9d4dbf419ce..d2f4e7652ab5681ce5f75ae21a0ebea15ac96fcb 100644 --- a/clang/test/CXX/drs/dr23xx.cpp +++ b/clang/test/CXX/drs/dr23xx.cpp @@ -213,6 +213,8 @@ namespace dr2387 { // dr2387: 9 #endif } +// dr2390 is in dr2390.cpp + namespace dr2394 { // dr2394: 15 struct A {}; diff --git a/clang/test/CXX/drs/dr24xx.cpp b/clang/test/CXX/drs/dr24xx.cpp index b34ceb420788fcd7a71669fa558f87c24eb12444..66e9cf5a677f80098367ad7dc313631443fe15f7 100644 --- a/clang/test/CXX/drs/dr24xx.cpp +++ b/clang/test/CXX/drs/dr24xx.cpp @@ -45,7 +45,7 @@ void fallthrough(int n) { #endif } -namespace dr2450 { // dr2450: 18 drafting +namespace dr2450 { // dr2450: 18 review #if __cplusplus >= 202302L struct S {int a;}; template diff --git a/clang/test/CXX/drs/dr25xx.cpp b/clang/test/CXX/drs/dr25xx.cpp index 8c34b03c22d5b1af7c1340fc1d819f5ca1c748b7..32bbfc63d0df4f3a2be51cb3a5fd742e731317c0 100644 --- a/clang/test/CXX/drs/dr25xx.cpp +++ b/clang/test/CXX/drs/dr25xx.cpp @@ -83,7 +83,7 @@ using ::dr2521::operator""_div; #if __cplusplus >= 202302L -namespace dr2553 { // dr2553: 18 +namespace dr2553 { // dr2553: 18 review struct B { virtual void f(this B&); // since-cxx23-error@-1 {{an explicit object parameter cannot appear in a virtual function}} @@ -143,7 +143,7 @@ void foo() { #endif -namespace dr2565 { // dr2565: 16 +namespace dr2565 { // dr2565: 16 open #if __cplusplus >= 202002L template concept C = requires (typename T::type x) { diff --git a/clang/test/CXX/drs/dr26xx.cpp b/clang/test/CXX/drs/dr26xx.cpp index 8a22dbeb98a3d5ae4548edc5bea0503a43ce2965..47eeddcc5bf2695a93b5861e98461e097444542c 100644 --- a/clang/test/CXX/drs/dr26xx.cpp +++ b/clang/test/CXX/drs/dr26xx.cpp @@ -24,7 +24,7 @@ using enum E; #endif } -namespace dr2628 { // dr2628: no open +namespace dr2628 { // dr2628: no // 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 @@ -197,7 +197,7 @@ J j = { "ghi" }; #endif } -namespace dr2672 { // dr2672: 18 open +namespace dr2672 { // dr2672: 18 #if __cplusplus >= 202002L template void f(T) requires requires { []() { T::invalid; } (); }; diff --git a/clang/test/CXX/drs/dr27xx.cpp b/clang/test/CXX/drs/dr27xx.cpp index 4f7d0d6b44a83ec7844f1ccf5221158d9f23e9e8..dd3fd5a20163faa713467f9f0bc77f95ee917a71 100644 --- a/clang/test/CXX/drs/dr27xx.cpp +++ b/clang/test/CXX/drs/dr27xx.cpp @@ -10,7 +10,7 @@ // expected-no-diagnostics #endif -namespace dr2789 { // dr2789: 18 open +namespace dr2789 { // dr2789: 18 #if __cplusplus >= 202302L template struct Base { @@ -42,7 +42,7 @@ void test() { #endif } -namespace dr2798 { // dr2798: 17 drafting +namespace dr2798 { // dr2798: 17 #if __cpp_static_assert >= 202306 struct string { constexpr string() { diff --git a/clang/test/CXX/drs/dr4xx.cpp b/clang/test/CXX/drs/dr4xx.cpp index fd5c842c1085711d07858ab848cb889a468cc220..fa90764df9b03b201d47fcfc9328c4143f0a161d 100644 --- a/clang/test/CXX/drs/dr4xx.cpp +++ b/clang/test/CXX/drs/dr4xx.cpp @@ -282,7 +282,7 @@ namespace dr410 { // dr410: no // expected-note@#dr410-z {{declared private here}} } -// dr412 is in its own file. +// dr412 is in dr412.cpp namespace dr413 { // dr413: yes struct S { diff --git a/clang/test/CXX/over/over.load/p2-0x.cpp b/clang/test/CXX/over/over.load/p2-0x.cpp index 183f3cb322af7e7e12de1f6bec9275f71dd54f2f..8fd9a1ce1e87ab43fcb3bb1376dae260afd008b2 100644 --- a/clang/test/CXX/over/over.load/p2-0x.cpp +++ b/clang/test/CXX/over/over.load/p2-0x.cpp @@ -24,6 +24,11 @@ class Y { void k() &&; // expected-error{{cannot overload a member function with ref-qualifier '&&' with a member function without a ref-qualifier}} }; +struct GH76358 { + template void f() && {} + template void f() const {} +}; + #if __cplusplus >= 202002L namespace GH58962 { diff --git a/clang/test/CXX/over/over.match/over.match.funcs/over.match.oper/p3-2a.cpp b/clang/test/CXX/over/over.match/over.match.funcs/over.match.oper/p3-2a.cpp index d83a176ec07eec91c6594400182ef93761a21a3f..d757d28860a40e8dd7d9df5a0e8af38286ee39af 100644 --- a/clang/test/CXX/over/over.match/over.match.funcs/over.match.oper/p3-2a.cpp +++ b/clang/test/CXX/over/over.match/over.match.funcs/over.match.oper/p3-2a.cpp @@ -324,6 +324,124 @@ bool x = X() == X(); // expected-warning {{ambiguous}} } } // namespace P2468R2 +namespace GH53954{ +namespace friend_template_1 { +struct P { + template + friend bool operator==(const P&, const T&) { return true; } // expected-note {{candidate}} \ + // expected-note {{ambiguous candidate function with reversed arguments}} +}; +struct A : public P {}; +struct B : public P {}; +bool check(A a, B b) { return a == b; } // expected-warning {{use of overloaded operator '==' (with operand types 'A' and 'B') to be ambiguous}} +} + +namespace friend_template_2 { +struct P { + template + friend bool operator==(const T&, const P&) { return true; } // expected-note {{candidate}} \ + // expected-note {{ambiguous candidate function with reversed arguments}} +}; +struct A : public P {}; +struct B : public P {}; +bool check(A a, B b) { return a == b; } // expected-warning {{use of overloaded operator '==' (with operand types 'A' and 'B') to be ambiguous}} +} + +namespace friend_template_class_template { +template +struct P { + template + friend bool operator==(const T&, const P&) { // expected-note 2 {{candidate}} + return true; + } +}; +struct A : public P {}; +struct B : public P {}; +bool check(A a, B b) { return a == b; } // expected-warning {{ambiguous}} +} + +namespace friend_template_fixme { +// FIXME(GH70210): This should not rewrite operator== and definitely not a hard error. +struct P { + template + friend bool operator==(const T &, const P &) { return true; } // expected-note 2 {{candidate}} + template + friend bool operator!=(const T &, const P &) { return true; } // expected-note {{candidate}} +}; +struct A : public P {}; +struct B : public P {}; +bool check(A a, B b) { return a != b; } // expected-error{{ambiguous}} +} + +namespace member_template_1 { +struct P { + template + bool operator==(const S &) const; // expected-note {{candidate}} \ + // expected-note {{ambiguous candidate function with reversed arguments}} +}; +struct A : public P {}; +struct B : public P {}; +bool check(A a, B b) { return a == b; } // expected-warning {{use of overloaded operator '==' (with operand types 'A' and 'B') to be ambiguous}} +} // namespace member_template + +namespace member_template_2{ +template +class Foo { + public: + template + bool operator==(const Foo& other) const; +}; +bool x = Foo{} == Foo{}; +} // namespace template_member_opeqeq + +namespace non_member_template_1 { +struct P {}; +template +bool operator==(const P&, const S &); // expected-note {{candidate}} \ + // expected-note {{ambiguous candidate function with reversed arguments}} + +struct A : public P {}; +struct B : public P {}; +bool check(A a, B b) { return a == b; } // expected-warning {{use of overloaded operator '==' (with operand types 'A' and 'B') to be ambiguous}} + +template bool operator!=(const P&, const S &); +bool fine(A a, B b) { return a == b; } // Ok. Found a matching operator!=. +} // namespace non_member_template_1 + +namespace non_member_template_2 { +struct P {}; +template +bool operator==(const S&, const P&); // expected-note {{candidate}} \ + // expected-note {{ambiguous candidate function with reversed arguments}} + +struct A : public P {}; +struct B : public P {}; +bool check(A a, B b) { return a == b; } // expected-warning {{use of overloaded operator '==' (with operand types 'A' and 'B') to be ambiguous}} +} // namespace non_member_template_2 + +namespace class_and_member_template { +template +struct S { + template + bool operator==(const OtherT &rhs); // expected-note {{candidate}} \ + // expected-note {{reversed arguments}} +}; +struct A : S {}; +struct B : S {}; +bool x = A{} == B{}; // expected-warning {{ambiguous}} +} // namespace class_and_member_template + +namespace ambiguous_case { +template +struct Foo {}; +template bool operator==(Foo, Foo); // expected-note{{candidate}} +template bool operator==(Foo, Foo); // expected-note{{candidate}} + +void test() { + Foo() == Foo(); // expected-error{{ambiguous}} +} +} // namespace ambiguous_case +} // namespace namespace ADL_GH68901{ namespace test1 { namespace A { diff --git a/clang/test/CodeGen/2006-05-19-SingleEltReturn.c b/clang/test/CodeGen/2006-05-19-SingleEltReturn.c index 16eacf3ec16258f83f0b422c69fd277d55da9ed6..b542242606cc389c8722785e700cd7282b2c5cd6 100644 --- a/clang/test/CodeGen/2006-05-19-SingleEltReturn.c +++ b/clang/test/CodeGen/2006-05-19-SingleEltReturn.c @@ -24,7 +24,7 @@ struct Y bar(void) { // X86_32: define{{.*}} void @foo(ptr noundef %P) -// X86_32: call void @bar(ptr sret(%struct.Y) align 4 %{{[^),]*}}) +// X86_32: call void @bar(ptr dead_on_unwind writable sret(%struct.Y) align 4 %{{[^),]*}}) -// X86_32: define{{.*}} void @bar(ptr noalias sret(%struct.Y) align 4 %{{[^,)]*}}) +// X86_32: define{{.*}} void @bar(ptr dead_on_unwind noalias writable sret(%struct.Y) align 4 %{{[^,)]*}}) // X86_32: ret void diff --git a/clang/test/CodeGen/64bit-swiftcall.c b/clang/test/CodeGen/64bit-swiftcall.c index da6f18248c2af29bb5f96b86fc603a4febc41929..b1c42e3b0a657b0e185b999966515064d20f2936 100644 --- a/clang/test/CodeGen/64bit-swiftcall.c +++ b/clang/test/CodeGen/64bit-swiftcall.c @@ -30,7 +30,7 @@ SWIFTCALL int indirect_result_2(OUT int *arg0, OUT float *arg1) { __builtin_unr typedef struct { char array[1024]; } struct_reallybig; SWIFTCALL struct_reallybig indirect_result_3(OUT int *arg0, OUT float *arg1) { __builtin_unreachable(); } -// CHECK-LABEL: define {{.*}} void @indirect_result_3(ptr noalias sret(%struct.struct_reallybig) {{.*}}, ptr noalias align 4 dereferenceable(4){{.*}}, ptr noalias align 4 dereferenceable(4){{.*}}) +// CHECK-LABEL: define {{.*}} void @indirect_result_3(ptr dead_on_unwind noalias writable sret(%struct.struct_reallybig) {{.*}}, ptr noalias align 4 dereferenceable(4){{.*}}, ptr noalias align 4 dereferenceable(4){{.*}}) SWIFTCALL void context_1(CONTEXT void *self) {} // CHECK-LABEL: define {{.*}} void @context_1(ptr swiftself @@ -238,7 +238,7 @@ typedef struct { } struct_big_1; TEST(struct_big_1) -// CHECK-LABEL: define {{.*}} void @return_struct_big_1({{.*}} noalias sret +// CHECK-LABEL: define {{.*}} void @return_struct_big_1(ptr dead_on_unwind noalias writable sret // Should not be byval. // CHECK-LABEL: define {{.*}} void @take_struct_big_1(ptr{{( %.*)?}}) @@ -522,7 +522,7 @@ typedef struct { double d4; } struct_d5; TEST(struct_d5) -// CHECK: define{{.*}} swiftcc void @return_struct_d5(ptr noalias sret([[STRUCT5:.+]]) +// CHECK: define{{.*}} swiftcc void @return_struct_d5(ptr dead_on_unwind noalias writable sret([[STRUCT5:.+]]) // CHECK: define{{.*}} swiftcc void @take_struct_d5(ptr typedef struct { @@ -709,7 +709,7 @@ typedef struct { long long l4; } struct_l5; TEST(struct_l5) -// CHECK: define{{.*}} swiftcc void @return_struct_l5(ptr noalias sret([[STRUCT5:.+]]) +// CHECK: define{{.*}} swiftcc void @return_struct_l5(ptr dead_on_unwind noalias writable sret([[STRUCT5:.+]]) // CHECK: define{{.*}} swiftcc void @take_struct_l5(ptr typedef struct { @@ -754,7 +754,7 @@ typedef struct { char16 c4; } struct_vc5; TEST(struct_vc5) -// CHECK: define{{.*}} swiftcc void @return_struct_vc5(ptr noalias sret([[STRUCT:.+]]) +// CHECK: define{{.*}} swiftcc void @return_struct_vc5(ptr dead_on_unwind noalias writable sret([[STRUCT:.+]]) // CHECK: define{{.*}} swiftcc void @take_struct_vc5(ptr typedef struct { @@ -799,7 +799,7 @@ typedef struct { short8 c4; } struct_vs5; TEST(struct_vs5) -// CHECK: define{{.*}} swiftcc void @return_struct_vs5(ptr noalias sret([[STRUCT:.+]]) +// CHECK: define{{.*}} swiftcc void @return_struct_vs5(ptr dead_on_unwind noalias writable sret([[STRUCT:.+]]) // CHECK: define{{.*}} swiftcc void @take_struct_vs5(ptr typedef struct { @@ -844,7 +844,7 @@ typedef struct { int4 c4; } struct_vi5; TEST(struct_vi5) -// CHECK: define{{.*}} swiftcc void @return_struct_vi5(ptr noalias sret([[STRUCT:.+]]) +// CHECK: define{{.*}} swiftcc void @return_struct_vi5(ptr dead_on_unwind noalias writable sret([[STRUCT:.+]]) // CHECK: define{{.*}} swiftcc void @take_struct_vi5(ptr typedef struct { @@ -872,7 +872,7 @@ typedef struct { long2 c4; } struct_vl5; TEST(struct_vl5) -// CHECK: define{{.*}} swiftcc void @return_struct_vl5(ptr noalias sret([[STRUCT:.+]]) +// CHECK: define{{.*}} swiftcc void @return_struct_vl5(ptr dead_on_unwind noalias writable sret([[STRUCT:.+]]) // CHECK: define{{.*}} swiftcc void @take_struct_vl5(ptr typedef struct { @@ -900,7 +900,7 @@ typedef struct { double2 c4; } struct_vd5; TEST(struct_vd5) -// CHECK: define{{.*}} swiftcc void @return_struct_vd5(ptr noalias sret([[STRUCT:.+]]) +// CHECK: define{{.*}} swiftcc void @return_struct_vd5(ptr dead_on_unwind noalias writable sret([[STRUCT:.+]]) // CHECK: define{{.*}} swiftcc void @take_struct_vd5(ptr typedef struct { @@ -924,7 +924,7 @@ typedef struct { double4 c2; } struct_vd43; TEST(struct_vd43) -// CHECK: define{{.*}} swiftcc void @return_struct_vd43(ptr noalias sret([[STRUCT:.+]]) +// CHECK: define{{.*}} swiftcc void @return_struct_vd43(ptr dead_on_unwind noalias writable sret([[STRUCT:.+]]) // CHECK: define{{.*}} swiftcc void @take_struct_vd43(ptr typedef struct { @@ -960,7 +960,7 @@ typedef struct { float4 c4; } struct_vf5; TEST(struct_vf5) -// CHECK: define{{.*}} swiftcc void @return_struct_vf5(ptr noalias sret([[STRUCT:.+]]) +// CHECK: define{{.*}} swiftcc void @return_struct_vf5(ptr dead_on_unwind noalias writable sret([[STRUCT:.+]]) // CHECK: define{{.*}} swiftcc void @take_struct_vf5(ptr typedef struct { diff --git a/clang/test/CodeGen/CSKY/csky-abi.c b/clang/test/CodeGen/CSKY/csky-abi.c index a24d4d8d64077d3e2e257f2251211696e38ddb5d..2e549376ba93301b7eef4e746817fc2497843ead 100644 --- a/clang/test/CodeGen/CSKY/csky-abi.c +++ b/clang/test/CodeGen/CSKY/csky-abi.c @@ -117,7 +117,7 @@ void f_agg_large(struct large x) { // The address where the struct should be written to will be the first // argument -// CHECK-LABEL: define{{.*}} void @f_agg_large_ret(ptr noalias sret(%struct.large) align 4 %agg.result, i32 noundef %i, i8 noundef signext %j) +// CHECK-LABEL: define{{.*}} void @f_agg_large_ret(ptr dead_on_unwind noalias writable sret(%struct.large) align 4 %agg.result, i32 noundef %i, i8 noundef signext %j) struct large f_agg_large_ret(int32_t i, int8_t j) { return (struct large){1, 2, 3, 4}; } @@ -144,7 +144,7 @@ int f_scalar_stack_1(struct tiny a, struct small b, struct small_aligned c, // the presence of large return values that consume a register due to the need // to pass a pointer. -// CHECK-LABEL: define{{.*}} void @f_scalar_stack_2(ptr noalias sret(%struct.large) align 4 %agg.result, i32 noundef %a, i64 noundef %b, i64 noundef %c, double noundef %d, i8 noundef zeroext %e, i8 noundef signext %f, i8 noundef zeroext %g) +// CHECK-LABEL: define{{.*}} void @f_scalar_stack_2(ptr dead_on_unwind noalias writable sret(%struct.large) align 4 %agg.result, i32 noundef %a, i64 noundef %b, i64 noundef %c, double noundef %d, i8 noundef zeroext %e, i8 noundef signext %f, i8 noundef zeroext %g) struct large f_scalar_stack_2(int32_t a, int64_t b, int64_t c, long double d, uint8_t e, int8_t f, uint8_t g) { return (struct large){a, e, f, g}; diff --git a/clang/test/CodeGen/CSKY/csky-hard-abi.c b/clang/test/CodeGen/CSKY/csky-hard-abi.c index 2171da8091e2b496449176fbfc85debb0f33d23b..0bc4a5a8808e5199ea1c5d9885199b65b98cd0c5 100644 --- a/clang/test/CodeGen/CSKY/csky-hard-abi.c +++ b/clang/test/CodeGen/CSKY/csky-hard-abi.c @@ -72,7 +72,7 @@ struct double_float_s { // CHECK: define{{.*}} void @f_double_double_s_arg([4 x i32] %a.coerce) void f_double_double_s_arg(struct double_double_s a) {} -// CHECK: define{{.*}} void @f_ret_double_double_s(ptr noalias sret(%struct.double_double_s) align 4 %agg.result) +// CHECK: define{{.*}} void @f_ret_double_double_s(ptr dead_on_unwind noalias writable sret(%struct.double_double_s) align 4 %agg.result) struct double_double_s f_ret_double_double_s(void) { return (struct double_double_s){1.0, 2.0}; } @@ -80,7 +80,7 @@ struct double_double_s f_ret_double_double_s(void) { // CHECK: define{{.*}} void @f_double_float_s_arg([3 x i32] %a.coerce) void f_double_float_s_arg(struct double_float_s a) {} -// CHECK: define{{.*}} void @f_ret_double_float_s(ptr noalias sret(%struct.double_float_s) align 4 %agg.result) +// CHECK: define{{.*}} void @f_ret_double_float_s(ptr dead_on_unwind noalias writable sret(%struct.double_float_s) align 4 %agg.result) struct double_float_s f_ret_double_float_s(void) { return (struct double_float_s){1.0, 2.0}; } @@ -118,7 +118,7 @@ struct double_int8_zbf_s { // CHECK: define{{.*}} @f_double_int8_s_arg([3 x i32] %a.coerce) void f_double_int8_s_arg(struct double_int8_s a) {} -// CHECK: define{{.*}} void @f_ret_double_int8_s(ptr noalias sret(%struct.double_int8_s) align 4 %agg.result) +// CHECK: define{{.*}} void @f_ret_double_int8_s(ptr dead_on_unwind noalias writable sret(%struct.double_int8_s) align 4 %agg.result) struct double_int8_s f_ret_double_int8_s(void) { return (struct double_int8_s){1.0, 2}; } @@ -126,7 +126,7 @@ struct double_int8_s f_ret_double_int8_s(void) { // CHECK: define{{.*}} void @f_double_uint8_s_arg([3 x i32] %a.coerce) void f_double_uint8_s_arg(struct double_uint8_s a) {} -// CHECK: define{{.*}} void @f_ret_double_uint8_s(ptr noalias sret(%struct.double_uint8_s) align 4 %agg.result) +// CHECK: define{{.*}} void @f_ret_double_uint8_s(ptr dead_on_unwind noalias writable sret(%struct.double_uint8_s) align 4 %agg.result) struct double_uint8_s f_ret_double_uint8_s(void) { return (struct double_uint8_s){1.0, 2}; } @@ -134,7 +134,7 @@ struct double_uint8_s f_ret_double_uint8_s(void) { // CHECK: define{{.*}} void @f_double_int32_s_arg([3 x i32] %a.coerce) void f_double_int32_s_arg(struct double_int32_s a) {} -// CHECK: define{{.*}} void @f_ret_double_int32_s(ptr noalias sret(%struct.double_int32_s) align 4 %agg.result) +// CHECK: define{{.*}} void @f_ret_double_int32_s(ptr dead_on_unwind noalias writable sret(%struct.double_int32_s) align 4 %agg.result) struct double_int32_s f_ret_double_int32_s(void) { return (struct double_int32_s){1.0, 2}; } @@ -142,7 +142,7 @@ struct double_int32_s f_ret_double_int32_s(void) { // CHECK: define{{.*}} void @f_double_int64_s_arg([4 x i32] %a.coerce) void f_double_int64_s_arg(struct double_int64_s a) {} -// CHECK: define{{.*}} void @f_ret_double_int64_s(ptr noalias sret(%struct.double_int64_s) align 4 %agg.result) +// CHECK: define{{.*}} void @f_ret_double_int64_s(ptr dead_on_unwind noalias writable sret(%struct.double_int64_s) align 4 %agg.result) struct double_int64_s f_ret_double_int64_s(void) { return (struct double_int64_s){1.0, 2}; } @@ -150,7 +150,7 @@ struct double_int64_s f_ret_double_int64_s(void) { // CHECK: define{{.*}} void @f_double_int64bf_s_arg([3 x i32] %a.coerce) void f_double_int64bf_s_arg(struct double_int64bf_s a) {} -// CHECK: define{{.*}} void @f_ret_double_int64bf_s(ptr noalias sret(%struct.double_int64bf_s) align 4 %agg.result) +// CHECK: define{{.*}} void @f_ret_double_int64bf_s(ptr dead_on_unwind noalias writable sret(%struct.double_int64bf_s) align 4 %agg.result) struct double_int64bf_s f_ret_double_int64bf_s(void) { return (struct double_int64bf_s){1.0, 2}; } @@ -158,7 +158,7 @@ struct double_int64bf_s f_ret_double_int64bf_s(void) { // CHECK: define{{.*}} void @f_double_int8_zbf_s([3 x i32] %a.coerce) void f_double_int8_zbf_s(struct double_int8_zbf_s a) {} -// CHECK: define{{.*}} void @f_ret_double_int8_zbf_s(ptr noalias sret(%struct.double_int8_zbf_s) align 4 %agg.result) +// CHECK: define{{.*}} void @f_ret_double_int8_zbf_s(ptr dead_on_unwind noalias writable sret(%struct.double_int8_zbf_s) align 4 %agg.result) struct double_int8_zbf_s f_ret_double_int8_zbf_s(void) { return (struct double_int8_zbf_s){1.0, 2}; } @@ -179,7 +179,7 @@ void f_struct_double_int8_insufficient_fprs(float a, double b, double c, double // CHECK: define{{.*}} void @f_doublecomplex(double noundef %a.coerce0, double noundef %a.coerce1) void f_doublecomplex(double __complex__ a) {} -// CHECK: define{{.*}} void @f_ret_doublecomplex(ptr noalias sret({ double, double }) align 4 %agg.result) +// CHECK: define{{.*}} void @f_ret_doublecomplex(ptr dead_on_unwind noalias writable sret({ double, double }) align 4 %agg.result) double __complex__ f_ret_doublecomplex(void) { return 1.0; } @@ -191,7 +191,7 @@ struct doublecomplex_s { // CHECK: define{{.*}} void @f_doublecomplex_s_arg([4 x i32] %a.coerce) void f_doublecomplex_s_arg(struct doublecomplex_s a) {} -// CHECK: define{{.*}} void @f_ret_doublecomplex_s(ptr noalias sret(%struct.doublecomplex_s) align 4 %agg.result) +// CHECK: define{{.*}} void @f_ret_doublecomplex_s(ptr dead_on_unwind noalias writable sret(%struct.doublecomplex_s) align 4 %agg.result) struct doublecomplex_s f_ret_doublecomplex_s(void) { return (struct doublecomplex_s){1.0}; } @@ -218,7 +218,7 @@ struct doublearr2_s { // CHECK: define{{.*}} void @f_doublearr2_s_arg([4 x i32] %a.coerce) void f_doublearr2_s_arg(struct doublearr2_s a) {} -// CHECK: define{{.*}} void @f_ret_doublearr2_s(ptr noalias sret(%struct.doublearr2_s) align 4 %agg.result) +// CHECK: define{{.*}} void @f_ret_doublearr2_s(ptr dead_on_unwind noalias writable sret(%struct.doublearr2_s) align 4 %agg.result) struct doublearr2_s f_ret_doublearr2_s(void) { return (struct doublearr2_s){{1.0, 2.0}}; } @@ -232,7 +232,7 @@ struct doublearr2_tricky1_s { // CHECK: define{{.*}} void @f_doublearr2_tricky1_s_arg([4 x i32] %a.coerce) void f_doublearr2_tricky1_s_arg(struct doublearr2_tricky1_s a) {} -// CHECK: define{{.*}} void @f_ret_doublearr2_tricky1_s(ptr noalias sret(%struct.doublearr2_tricky1_s) align 4 %agg.result) +// CHECK: define{{.*}} void @f_ret_doublearr2_tricky1_s(ptr dead_on_unwind noalias writable sret(%struct.doublearr2_tricky1_s) align 4 %agg.result) struct doublearr2_tricky1_s f_ret_doublearr2_tricky1_s(void) { return (struct doublearr2_tricky1_s){{{{1.0}}, {{2.0}}}}; } @@ -247,7 +247,7 @@ struct doublearr2_tricky2_s { // CHECK: define{{.*}} void @f_doublearr2_tricky2_s_arg([4 x i32] %a.coerce) void f_doublearr2_tricky2_s_arg(struct doublearr2_tricky2_s a) {} -// CHECK: define{{.*}} void @f_ret_doublearr2_tricky2_s(ptr noalias sret(%struct.doublearr2_tricky2_s) align 4 %agg.result) +// CHECK: define{{.*}} void @f_ret_doublearr2_tricky2_s(ptr dead_on_unwind noalias writable sret(%struct.doublearr2_tricky2_s) align 4 %agg.result) struct doublearr2_tricky2_s f_ret_doublearr2_tricky2_s(void) { return (struct doublearr2_tricky2_s){{}, {{{1.0}}, {{2.0}}}}; } @@ -262,7 +262,7 @@ struct doublearr2_tricky3_s { // CHECK: define{{.*}} void @f_doublearr2_tricky3_s_arg([4 x i32] %a.coerce) void f_doublearr2_tricky3_s_arg(struct doublearr2_tricky3_s a) {} -// CHECK: define{{.*}} void @f_ret_doublearr2_tricky3_s(ptr noalias sret(%struct.doublearr2_tricky3_s) align 4 %agg.result) +// CHECK: define{{.*}} void @f_ret_doublearr2_tricky3_s(ptr dead_on_unwind noalias writable sret(%struct.doublearr2_tricky3_s) align 4 %agg.result) struct doublearr2_tricky3_s f_ret_doublearr2_tricky3_s(void) { return (struct doublearr2_tricky3_s){{}, {{{1.0}}, {{2.0}}}}; } @@ -278,7 +278,7 @@ struct doublearr2_tricky4_s { // CHECK: define{{.*}} void @f_doublearr2_tricky4_s_arg([4 x i32] %a.coerce) void f_doublearr2_tricky4_s_arg(struct doublearr2_tricky4_s a) {} -// CHECK: define{{.*}} void @f_ret_doublearr2_tricky4_s(ptr noalias sret(%struct.doublearr2_tricky4_s) align 4 %agg.result) +// CHECK: define{{.*}} void @f_ret_doublearr2_tricky4_s(ptr dead_on_unwind noalias writable sret(%struct.doublearr2_tricky4_s) align 4 %agg.result) struct doublearr2_tricky4_s f_ret_doublearr2_tricky4_s(void) { return (struct doublearr2_tricky4_s){{}, {{{}, {1.0}}, {{}, {2.0}}}}; } @@ -292,7 +292,7 @@ struct int_double_int_s { // CHECK: define{{.*}} void @f_int_double_int_s_arg([4 x i32] %a.coerce) void f_int_double_int_s_arg(struct int_double_int_s a) {} -// CHECK: define{{.*}} void @f_ret_int_double_int_s(ptr noalias sret(%struct.int_double_int_s) align 4 %agg.result) +// CHECK: define{{.*}} void @f_ret_int_double_int_s(ptr dead_on_unwind noalias writable sret(%struct.int_double_int_s) align 4 %agg.result) struct int_double_int_s f_ret_int_double_int_s(void) { return (struct int_double_int_s){1, 2.0, 3}; } @@ -305,7 +305,7 @@ struct int64_double_s { // CHECK: define{{.*}} void @f_int64_double_s_arg([4 x i32] %a.coerce) void f_int64_double_s_arg(struct int64_double_s a) {} -// CHECK: define{{.*}} void @f_ret_int64_double_s(ptr noalias sret(%struct.int64_double_s) align 4 %agg.result) +// CHECK: define{{.*}} void @f_ret_int64_double_s(ptr dead_on_unwind noalias writable sret(%struct.int64_double_s) align 4 %agg.result) struct int64_double_s f_ret_int64_double_s(void) { return (struct int64_double_s){1, 2.0}; } @@ -319,7 +319,7 @@ struct char_char_double_s { // CHECK-LABEL: define{{.*}} void @f_char_char_double_s_arg([3 x i32] %a.coerce) void f_char_char_double_s_arg(struct char_char_double_s a) {} -// CHECK: define{{.*}} void @f_ret_char_char_double_s(ptr noalias sret(%struct.char_char_double_s) align 4 %agg.result) +// CHECK: define{{.*}} void @f_ret_char_char_double_s(ptr dead_on_unwind noalias writable sret(%struct.char_char_double_s) align 4 %agg.result) struct char_char_double_s f_ret_char_char_double_s(void) { return (struct char_char_double_s){1, 2, 3.0}; } @@ -338,19 +338,19 @@ union double_u f_ret_double_u(void) { return (union double_u){1.0}; } -// CHECK: define{{.*}} void @f_ret_double_int32_s_double_int32_s_just_sufficient_gprs(ptr noalias sret(%struct.double_int32_s) align 4 %agg.result, i32 noundef %a, i32 noundef %b, i32 noundef %c, i32 noundef %d, i32 noundef %e, i32 noundef %f, i32 noundef %g, [3 x i32] %h.coerce) +// CHECK: define{{.*}} void @f_ret_double_int32_s_double_int32_s_just_sufficient_gprs(ptr dead_on_unwind noalias writable sret(%struct.double_int32_s) align 4 %agg.result, i32 noundef %a, i32 noundef %b, i32 noundef %c, i32 noundef %d, i32 noundef %e, i32 noundef %f, i32 noundef %g, [3 x i32] %h.coerce) struct double_int32_s f_ret_double_int32_s_double_int32_s_just_sufficient_gprs( int a, int b, int c, int d, int e, int f, int g, struct double_int32_s h) { return (struct double_int32_s){1.0, 2}; } -// CHECK: define{{.*}} void @f_ret_double_double_s_double_int32_s_just_sufficient_gprs(ptr noalias sret(%struct.double_double_s) align 4 %agg.result, i32 noundef %a, i32 noundef %b, i32 noundef %c, i32 noundef %d, i32 noundef %e, i32 noundef %f, i32 noundef %g, [3 x i32] %h.coerce) +// CHECK: define{{.*}} void @f_ret_double_double_s_double_int32_s_just_sufficient_gprs(ptr dead_on_unwind noalias writable sret(%struct.double_double_s) align 4 %agg.result, i32 noundef %a, i32 noundef %b, i32 noundef %c, i32 noundef %d, i32 noundef %e, i32 noundef %f, i32 noundef %g, [3 x i32] %h.coerce) struct double_double_s f_ret_double_double_s_double_int32_s_just_sufficient_gprs( int a, int b, int c, int d, int e, int f, int g, struct double_int32_s h) { return (struct double_double_s){1.0, 2.0}; } -// CHECK: define{{.*}} void @f_ret_doublecomplex_double_int32_s_just_sufficient_gprs(ptr noalias sret({ double, double }) align 4 %agg.result, i32 noundef %a, i32 noundef %b, i32 noundef %c, i32 noundef %d, i32 noundef %e, i32 noundef %f, i32 noundef %g, [3 x i32] %h.coerce) +// CHECK: define{{.*}} void @f_ret_doublecomplex_double_int32_s_just_sufficient_gprs(ptr dead_on_unwind noalias writable sret({ double, double }) align 4 %agg.result, i32 noundef %a, i32 noundef %b, i32 noundef %c, i32 noundef %d, i32 noundef %e, i32 noundef %f, i32 noundef %g, [3 x i32] %h.coerce) double __complex__ f_ret_doublecomplex_double_int32_s_just_sufficient_gprs( int a, int b, int c, int d, int e, int f, int g, struct double_int32_s h) { return 1.0; @@ -376,7 +376,7 @@ struct large { // the presence of large return values that consume a register due to the need // to pass a pointer. -// CHECK-LABEL: define{{.*}} void @f_scalar_stack_2(ptr noalias sret(%struct.large) align 4 %agg.result, float noundef %a, i64 noundef %b, double noundef %c, double noundef %d, i8 noundef zeroext %e, i8 noundef signext %f, i8 noundef zeroext %g) +// CHECK-LABEL: define{{.*}} void @f_scalar_stack_2(ptr dead_on_unwind noalias writable sret(%struct.large) align 4 %agg.result, float noundef %a, i64 noundef %b, double noundef %c, double noundef %d, i8 noundef zeroext %e, i8 noundef signext %f, i8 noundef zeroext %g) struct large f_scalar_stack_2(float a, int64_t b, double c, long double d, uint8_t e, int8_t f, uint8_t g) { return (struct large){a, e, f, g}; diff --git a/clang/test/CodeGen/CSKY/csky-soft-abi.c b/clang/test/CodeGen/CSKY/csky-soft-abi.c index 1aba2df1f20a28aeb470aeffcd798e5972cdc2cf..04fb7a494084218302a4d819c2dd1dad6c77c57b 100644 --- a/clang/test/CodeGen/CSKY/csky-soft-abi.c +++ b/clang/test/CodeGen/CSKY/csky-soft-abi.c @@ -72,7 +72,7 @@ struct double_float_s { // CHECK: define{{.*}} void @f_double_double_s_arg([4 x i32] %a.coerce) void f_double_double_s_arg(struct double_double_s a) {} -// CHECK: define{{.*}} void @f_ret_double_double_s(ptr noalias sret(%struct.double_double_s) align 4 %agg.result) +// CHECK: define{{.*}} void @f_ret_double_double_s(ptr dead_on_unwind noalias writable sret(%struct.double_double_s) align 4 %agg.result) struct double_double_s f_ret_double_double_s(void) { return (struct double_double_s){1.0, 2.0}; } @@ -80,7 +80,7 @@ struct double_double_s f_ret_double_double_s(void) { // CHECK: define{{.*}} void @f_double_float_s_arg([3 x i32] %a.coerce) void f_double_float_s_arg(struct double_float_s a) {} -// CHECK: define{{.*}} void @f_ret_double_float_s(ptr noalias sret(%struct.double_float_s) align 4 %agg.result) +// CHECK: define{{.*}} void @f_ret_double_float_s(ptr dead_on_unwind noalias writable sret(%struct.double_float_s) align 4 %agg.result) struct double_float_s f_ret_double_float_s(void) { return (struct double_float_s){1.0, 2.0}; } @@ -118,7 +118,7 @@ struct double_int8_zbf_s { // CHECK: define{{.*}} @f_double_int8_s_arg([3 x i32] %a.coerce) void f_double_int8_s_arg(struct double_int8_s a) {} -// CHECK: define{{.*}} void @f_ret_double_int8_s(ptr noalias sret(%struct.double_int8_s) align 4 %agg.result) +// CHECK: define{{.*}} void @f_ret_double_int8_s(ptr dead_on_unwind noalias writable sret(%struct.double_int8_s) align 4 %agg.result) struct double_int8_s f_ret_double_int8_s(void) { return (struct double_int8_s){1.0, 2}; } @@ -126,7 +126,7 @@ struct double_int8_s f_ret_double_int8_s(void) { // CHECK: define{{.*}} void @f_double_uint8_s_arg([3 x i32] %a.coerce) void f_double_uint8_s_arg(struct double_uint8_s a) {} -// CHECK: define{{.*}} void @f_ret_double_uint8_s(ptr noalias sret(%struct.double_uint8_s) align 4 %agg.result) +// CHECK: define{{.*}} void @f_ret_double_uint8_s(ptr dead_on_unwind noalias writable sret(%struct.double_uint8_s) align 4 %agg.result) struct double_uint8_s f_ret_double_uint8_s(void) { return (struct double_uint8_s){1.0, 2}; } @@ -134,7 +134,7 @@ struct double_uint8_s f_ret_double_uint8_s(void) { // CHECK: define{{.*}} void @f_double_int32_s_arg([3 x i32] %a.coerce) void f_double_int32_s_arg(struct double_int32_s a) {} -// CHECK: define{{.*}} void @f_ret_double_int32_s(ptr noalias sret(%struct.double_int32_s) align 4 %agg.result) +// CHECK: define{{.*}} void @f_ret_double_int32_s(ptr dead_on_unwind noalias writable sret(%struct.double_int32_s) align 4 %agg.result) struct double_int32_s f_ret_double_int32_s(void) { return (struct double_int32_s){1.0, 2}; } @@ -142,7 +142,7 @@ struct double_int32_s f_ret_double_int32_s(void) { // CHECK: define{{.*}} void @f_double_int64_s_arg([4 x i32] %a.coerce) void f_double_int64_s_arg(struct double_int64_s a) {} -// CHECK: define{{.*}} void @f_ret_double_int64_s(ptr noalias sret(%struct.double_int64_s) align 4 %agg.result) +// CHECK: define{{.*}} void @f_ret_double_int64_s(ptr dead_on_unwind noalias writable sret(%struct.double_int64_s) align 4 %agg.result) struct double_int64_s f_ret_double_int64_s(void) { return (struct double_int64_s){1.0, 2}; } @@ -150,7 +150,7 @@ struct double_int64_s f_ret_double_int64_s(void) { // CHECK: define{{.*}} void @f_double_int64bf_s_arg([3 x i32] %a.coerce) void f_double_int64bf_s_arg(struct double_int64bf_s a) {} -// CHECK: define{{.*}} void @f_ret_double_int64bf_s(ptr noalias sret(%struct.double_int64bf_s) align 4 %agg.result) +// CHECK: define{{.*}} void @f_ret_double_int64bf_s(ptr dead_on_unwind noalias writable sret(%struct.double_int64bf_s) align 4 %agg.result) struct double_int64bf_s f_ret_double_int64bf_s(void) { return (struct double_int64bf_s){1.0, 2}; } @@ -158,7 +158,7 @@ struct double_int64bf_s f_ret_double_int64bf_s(void) { // CHECK: define{{.*}} void @f_double_int8_zbf_s([3 x i32] %a.coerce) void f_double_int8_zbf_s(struct double_int8_zbf_s a) {} -// CHECK: define{{.*}} void @f_ret_double_int8_zbf_s(ptr noalias sret(%struct.double_int8_zbf_s) align 4 %agg.result) +// CHECK: define{{.*}} void @f_ret_double_int8_zbf_s(ptr dead_on_unwind noalias writable sret(%struct.double_int8_zbf_s) align 4 %agg.result) struct double_int8_zbf_s f_ret_double_int8_zbf_s(void) { return (struct double_int8_zbf_s){1.0, 2}; } @@ -180,7 +180,7 @@ void f_struct_double_int8_insufficient_fprs(float a, double b, double c, double // CHECK: define{{.*}} void @f_doublecomplex([4 x i32] noundef %a.coerce) void f_doublecomplex(double __complex__ a) {} -// CHECK: define{{.*}} void @f_ret_doublecomplex(ptr noalias sret({ double, double }) align 4 %agg.result) +// CHECK: define{{.*}} void @f_ret_doublecomplex(ptr dead_on_unwind noalias writable sret({ double, double }) align 4 %agg.result) double __complex__ f_ret_doublecomplex(void) { return 1.0; } @@ -192,7 +192,7 @@ struct doublecomplex_s { // CHECK: define{{.*}} void @f_doublecomplex_s_arg([4 x i32] %a.coerce) void f_doublecomplex_s_arg(struct doublecomplex_s a) {} -// CHECK: define{{.*}} void @f_ret_doublecomplex_s(ptr noalias sret(%struct.doublecomplex_s) align 4 %agg.result) +// CHECK: define{{.*}} void @f_ret_doublecomplex_s(ptr dead_on_unwind noalias writable sret(%struct.doublecomplex_s) align 4 %agg.result) struct doublecomplex_s f_ret_doublecomplex_s(void) { return (struct doublecomplex_s){1.0}; } @@ -219,7 +219,7 @@ struct doublearr2_s { // CHECK: define{{.*}} void @f_doublearr2_s_arg([4 x i32] %a.coerce) void f_doublearr2_s_arg(struct doublearr2_s a) {} -// CHECK: define{{.*}} void @f_ret_doublearr2_s(ptr noalias sret(%struct.doublearr2_s) align 4 %agg.result) +// CHECK: define{{.*}} void @f_ret_doublearr2_s(ptr dead_on_unwind noalias writable sret(%struct.doublearr2_s) align 4 %agg.result) struct doublearr2_s f_ret_doublearr2_s(void) { return (struct doublearr2_s){{1.0, 2.0}}; } @@ -233,7 +233,7 @@ struct doublearr2_tricky1_s { // CHECK: define{{.*}} void @f_doublearr2_tricky1_s_arg([4 x i32] %a.coerce) void f_doublearr2_tricky1_s_arg(struct doublearr2_tricky1_s a) {} -// CHECK: define{{.*}} void @f_ret_doublearr2_tricky1_s(ptr noalias sret(%struct.doublearr2_tricky1_s) align 4 %agg.result) +// CHECK: define{{.*}} void @f_ret_doublearr2_tricky1_s(ptr dead_on_unwind noalias writable sret(%struct.doublearr2_tricky1_s) align 4 %agg.result) struct doublearr2_tricky1_s f_ret_doublearr2_tricky1_s(void) { return (struct doublearr2_tricky1_s){{{{1.0}}, {{2.0}}}}; } @@ -248,7 +248,7 @@ struct doublearr2_tricky2_s { // CHECK: define{{.*}} void @f_doublearr2_tricky2_s_arg([4 x i32] %a.coerce) void f_doublearr2_tricky2_s_arg(struct doublearr2_tricky2_s a) {} -// CHECK: define{{.*}} void @f_ret_doublearr2_tricky2_s(ptr noalias sret(%struct.doublearr2_tricky2_s) align 4 %agg.result) +// CHECK: define{{.*}} void @f_ret_doublearr2_tricky2_s(ptr dead_on_unwind noalias writable sret(%struct.doublearr2_tricky2_s) align 4 %agg.result) struct doublearr2_tricky2_s f_ret_doublearr2_tricky2_s(void) { return (struct doublearr2_tricky2_s){{}, {{{1.0}}, {{2.0}}}}; } @@ -263,7 +263,7 @@ struct doublearr2_tricky3_s { // CHECK: define{{.*}} void @f_doublearr2_tricky3_s_arg([4 x i32] %a.coerce) void f_doublearr2_tricky3_s_arg(struct doublearr2_tricky3_s a) {} -// CHECK: define{{.*}} void @f_ret_doublearr2_tricky3_s(ptr noalias sret(%struct.doublearr2_tricky3_s) align 4 %agg.result) +// CHECK: define{{.*}} void @f_ret_doublearr2_tricky3_s(ptr dead_on_unwind noalias writable sret(%struct.doublearr2_tricky3_s) align 4 %agg.result) struct doublearr2_tricky3_s f_ret_doublearr2_tricky3_s(void) { return (struct doublearr2_tricky3_s){{}, {{{1.0}}, {{2.0}}}}; } @@ -279,7 +279,7 @@ struct doublearr2_tricky4_s { // CHECK: define{{.*}} void @f_doublearr2_tricky4_s_arg([4 x i32] %a.coerce) void f_doublearr2_tricky4_s_arg(struct doublearr2_tricky4_s a) {} -// CHECK: define{{.*}} void @f_ret_doublearr2_tricky4_s(ptr noalias sret(%struct.doublearr2_tricky4_s) align 4 %agg.result) +// CHECK: define{{.*}} void @f_ret_doublearr2_tricky4_s(ptr dead_on_unwind noalias writable sret(%struct.doublearr2_tricky4_s) align 4 %agg.result) struct doublearr2_tricky4_s f_ret_doublearr2_tricky4_s(void) { return (struct doublearr2_tricky4_s){{}, {{{}, {1.0}}, {{}, {2.0}}}}; } @@ -293,7 +293,7 @@ struct int_double_int_s { // CHECK: define{{.*}} void @f_int_double_int_s_arg([4 x i32] %a.coerce) void f_int_double_int_s_arg(struct int_double_int_s a) {} -// CHECK: define{{.*}} void @f_ret_int_double_int_s(ptr noalias sret(%struct.int_double_int_s) align 4 %agg.result) +// CHECK: define{{.*}} void @f_ret_int_double_int_s(ptr dead_on_unwind noalias writable sret(%struct.int_double_int_s) align 4 %agg.result) struct int_double_int_s f_ret_int_double_int_s(void) { return (struct int_double_int_s){1, 2.0, 3}; } @@ -306,7 +306,7 @@ struct int64_double_s { // CHECK: define{{.*}} void @f_int64_double_s_arg([4 x i32] %a.coerce) void f_int64_double_s_arg(struct int64_double_s a) {} -// CHECK: define{{.*}} void @f_ret_int64_double_s(ptr noalias sret(%struct.int64_double_s) align 4 %agg.result) +// CHECK: define{{.*}} void @f_ret_int64_double_s(ptr dead_on_unwind noalias writable sret(%struct.int64_double_s) align 4 %agg.result) struct int64_double_s f_ret_int64_double_s(void) { return (struct int64_double_s){1, 2.0}; } @@ -320,7 +320,7 @@ struct char_char_double_s { // CHECK-LABEL: define{{.*}} void @f_char_char_double_s_arg([3 x i32] %a.coerce) void f_char_char_double_s_arg(struct char_char_double_s a) {} -// CHECK: define{{.*}} void @f_ret_char_char_double_s(ptr noalias sret(%struct.char_char_double_s) align 4 %agg.result) +// CHECK: define{{.*}} void @f_ret_char_char_double_s(ptr dead_on_unwind noalias writable sret(%struct.char_char_double_s) align 4 %agg.result) struct char_char_double_s f_ret_char_char_double_s(void) { return (struct char_char_double_s){1, 2, 3.0}; } @@ -339,19 +339,19 @@ union double_u f_ret_double_u(void) { return (union double_u){1.0}; } -// CHECK: define{{.*}} void @f_ret_double_int32_s_double_int32_s_just_sufficient_gprs(ptr noalias sret(%struct.double_int32_s) align 4 %agg.result, i32 noundef %a, i32 noundef %b, i32 noundef %c, i32 noundef %d, i32 noundef %e, i32 noundef %f, i32 noundef %g, [3 x i32] %h.coerce) +// CHECK: define{{.*}} void @f_ret_double_int32_s_double_int32_s_just_sufficient_gprs(ptr dead_on_unwind noalias writable sret(%struct.double_int32_s) align 4 %agg.result, i32 noundef %a, i32 noundef %b, i32 noundef %c, i32 noundef %d, i32 noundef %e, i32 noundef %f, i32 noundef %g, [3 x i32] %h.coerce) struct double_int32_s f_ret_double_int32_s_double_int32_s_just_sufficient_gprs( int a, int b, int c, int d, int e, int f, int g, struct double_int32_s h) { return (struct double_int32_s){1.0, 2}; } -// CHECK: define{{.*}} void @f_ret_double_double_s_double_int32_s_just_sufficient_gprs(ptr noalias sret(%struct.double_double_s) align 4 %agg.result, i32 noundef %a, i32 noundef %b, i32 noundef %c, i32 noundef %d, i32 noundef %e, i32 noundef %f, i32 noundef %g, [3 x i32] %h.coerce) +// CHECK: define{{.*}} void @f_ret_double_double_s_double_int32_s_just_sufficient_gprs(ptr dead_on_unwind noalias writable sret(%struct.double_double_s) align 4 %agg.result, i32 noundef %a, i32 noundef %b, i32 noundef %c, i32 noundef %d, i32 noundef %e, i32 noundef %f, i32 noundef %g, [3 x i32] %h.coerce) struct double_double_s f_ret_double_double_s_double_int32_s_just_sufficient_gprs( int a, int b, int c, int d, int e, int f, int g, struct double_int32_s h) { return (struct double_double_s){1.0, 2.0}; } -// CHECK: define{{.*}} void @f_ret_doublecomplex_double_int32_s_just_sufficient_gprs(ptr noalias sret({ double, double }) align 4 %agg.result, i32 noundef %a, i32 noundef %b, i32 noundef %c, i32 noundef %d, i32 noundef %e, i32 noundef %f, i32 noundef %g, [3 x i32] %h.coerce) +// CHECK: define{{.*}} void @f_ret_doublecomplex_double_int32_s_just_sufficient_gprs(ptr dead_on_unwind noalias writable sret({ double, double }) align 4 %agg.result, i32 noundef %a, i32 noundef %b, i32 noundef %c, i32 noundef %d, i32 noundef %e, i32 noundef %f, i32 noundef %g, [3 x i32] %h.coerce) double __complex__ f_ret_doublecomplex_double_int32_s_just_sufficient_gprs( int a, int b, int c, int d, int e, int f, int g, struct double_int32_s h) { return 1.0; @@ -377,7 +377,7 @@ struct large { // the presence of large return values that consume a register due to the need // to pass a pointer. -// CHECK-LABEL: define{{.*}} void @f_scalar_stack_2(ptr noalias sret(%struct.large) align 4 %agg.result, float noundef %a, i64 noundef %b, double noundef %c, double noundef %d, i8 noundef zeroext %e, i8 noundef signext %f, i8 noundef zeroext %g) +// CHECK-LABEL: define{{.*}} void @f_scalar_stack_2(ptr dead_on_unwind noalias writable sret(%struct.large) align 4 %agg.result, float noundef %a, i64 noundef %b, double noundef %c, double noundef %d, i8 noundef zeroext %e, i8 noundef signext %f, i8 noundef zeroext %g) struct large f_scalar_stack_2(float a, int64_t b, double c, long double d, uint8_t e, int8_t f, uint8_t g) { return (struct large){a, e, f, g}; diff --git a/clang/test/CodeGen/PowerPC/aix-alignment.c b/clang/test/CodeGen/PowerPC/aix-alignment.c index e25fc7ec5599b3ab517ae16572c58528a6e24334..f732e94569ef2fbc9993ee5c8478eb2bd9ca1503 100644 --- a/clang/test/CodeGen/PowerPC/aix-alignment.c +++ b/clang/test/CodeGen/PowerPC/aix-alignment.c @@ -22,8 +22,8 @@ StructDouble d1; // AIX: ret double %0 double retDouble(double x) { return x; } -// AIX32: define void @bar(ptr noalias sret(%struct.StructDouble) align 4 %agg.result, ptr noundef byval(%struct.StructDouble) align 4 %x) -// AIX64: define void @bar(ptr noalias sret(%struct.StructDouble) align 4 %agg.result, ptr noundef byval(%struct.StructDouble) align 8 %x) +// AIX32: define void @bar(ptr dead_on_unwind noalias writable sret(%struct.StructDouble) align 4 %agg.result, ptr noundef byval(%struct.StructDouble) align 4 %x) +// AIX64: define void @bar(ptr dead_on_unwind noalias writable sret(%struct.StructDouble) align 4 %agg.result, ptr noundef byval(%struct.StructDouble) align 8 %x) // AIX32: call void @llvm.memcpy.p0.p0.i32(ptr align 4 %agg.result, ptr align 4 %x, i32 16, i1 false) // AIX64: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %agg.result, ptr align 8 %x, i64 16, i1 false) StructDouble bar(StructDouble x) { return x; } diff --git a/clang/test/CodeGen/PowerPC/powerpc-c99complex.c b/clang/test/CodeGen/PowerPC/powerpc-c99complex.c index f01c7820857e8058fb0e8b30ae068b49ce8c7b59..82b5ac0fdc06cbed0fe688e542dde802e823ef01 100644 --- a/clang/test/CodeGen/PowerPC/powerpc-c99complex.c +++ b/clang/test/CodeGen/PowerPC/powerpc-c99complex.c @@ -9,7 +9,7 @@ _Complex float foo1(_Complex float x) { // CHECK-LABEL: define{{.*}} { float, float } @foo1(float noundef %x.{{.*}}, float noundef %x.{{.*}}) #0 { // CHECK: ret { float, float } -// PPC32LNX-LABEL: define{{.*}} void @foo1(ptr noalias sret({ float, float }) align 4 %agg.result, ptr noundef byval({ float, float }) align 4 %x) #0 { +// PPC32LNX-LABEL: define{{.*}} void @foo1(ptr dead_on_unwind noalias writable sret({ float, float }) align 4 %agg.result, ptr noundef byval({ float, float }) align 4 %x) #0 { // PPC32LNX: [[RETREAL:%.*]] = getelementptr inbounds { float, float }, ptr %agg.result, i32 0, i32 0 // PPC32LNX-NEXT: [[RETIMAG:%.*]] = getelementptr inbounds { float, float }, ptr %agg.result, i32 0, i32 1 // PPC32LNX-NEXT: store float %{{.*}}, ptr [[RETREAL]], align 4 @@ -21,7 +21,7 @@ _Complex double foo2(_Complex double x) { // CHECK-LABEL: define{{.*}} { double, double } @foo2(double noundef %x.{{.*}}, double noundef %x.{{.*}}) #0 { // CHECK: ret { double, double } -// PPC32LNX-LABEL: define{{.*}} void @foo2(ptr noalias sret({ double, double }) align 8 %agg.result, ptr noundef byval({ double, double }) align 8 %x) #0 { +// PPC32LNX-LABEL: define{{.*}} void @foo2(ptr dead_on_unwind noalias writable sret({ double, double }) align 8 %agg.result, ptr noundef byval({ double, double }) align 8 %x) #0 { // PPC32LNX: [[RETREAL:%.*]] = getelementptr inbounds { double, double }, ptr %agg.result, i32 0, i32 0 // PPC32LNX-NEXT: [[RETIMAG:%.*]] = getelementptr inbounds { double, double }, ptr %agg.result, i32 0, i32 1 // PPC32LNX-NEXT: store double %{{.*}}, ptr [[RETREAL]], align 8 @@ -36,7 +36,7 @@ _Complex long double foo3(_Complex long double x) { // CHECK-LDBL128-LABEL: define{{.*}} { ppc_fp128, ppc_fp128 } @foo3(ppc_fp128 noundef %x.{{.*}}, ppc_fp128 noundef %x.{{.*}}) #0 { // CHECK-LDBL128: ret { ppc_fp128, ppc_fp128 } -// PPC32LNX-LABEL: define{{.*}} void @foo3(ptr noalias sret({ ppc_fp128, ppc_fp128 }) align 16 %agg.result, ptr noundef byval({ ppc_fp128, ppc_fp128 }) align 16 %x) #0 { +// PPC32LNX-LABEL: define{{.*}} void @foo3(ptr dead_on_unwind noalias writable sret({ ppc_fp128, ppc_fp128 }) align 16 %agg.result, ptr noundef byval({ ppc_fp128, ppc_fp128 }) align 16 %x) #0 { // PPC32LNX: [[RETREAL:%.*]] = getelementptr inbounds { ppc_fp128, ppc_fp128 }, ptr %agg.result, i32 0, i32 0 // PPC32LNX-NEXT: [[RETIMAG:%.*]] = getelementptr inbounds { ppc_fp128, ppc_fp128 }, ptr %agg.result, i32 0, i32 1 // PPC32LNX-NEXT: store ppc_fp128 %{{.*}}, ptr [[RETREAL]], align 16 diff --git a/clang/test/CodeGen/PowerPC/ppc-aggregate-abi.cpp b/clang/test/CodeGen/PowerPC/ppc-aggregate-abi.cpp index 0c094891fec50300ea7c38fec43d73397634d223..a7f7f3ee558c3d0ef8cb04642bc9474a6ca5e758 100644 --- a/clang/test/CodeGen/PowerPC/ppc-aggregate-abi.cpp +++ b/clang/test/CodeGen/PowerPC/ppc-aggregate-abi.cpp @@ -4,57 +4,57 @@ // RUN: -o - %s | FileCheck %s -check-prefix=CHECK-LE class agg_float_class { float a; }; -// CHECK-BE-LABEL: define{{.*}} void @_Z20pass_agg_float_class15agg_float_class(ptr noalias sret(%class.agg_float_class) align 4 %{{.*}}, float inreg %{{.*}}) +// CHECK-BE-LABEL: define{{.*}} void @_Z20pass_agg_float_class15agg_float_class(ptr dead_on_unwind noalias writable sret(%class.agg_float_class) align 4 %{{.*}}, float inreg %{{.*}}) // CHECK-LE-LABEL: define{{.*}} [1 x float] @_Z20pass_agg_float_class15agg_float_class(float inreg %{{.*}}) agg_float_class pass_agg_float_class(agg_float_class arg) { return arg; } class agg_double_class { double a; }; -// CHECK-BE-LABEL: define{{.*}} void @_Z21pass_agg_double_class16agg_double_class(ptr noalias sret(%class.agg_double_class) align 8 %{{.*}}, double inreg %{{.*}}) +// CHECK-BE-LABEL: define{{.*}} void @_Z21pass_agg_double_class16agg_double_class(ptr dead_on_unwind noalias writable sret(%class.agg_double_class) align 8 %{{.*}}, double inreg %{{.*}}) // CHECK-LE-LABEL: define{{.*}} [1 x double] @_Z21pass_agg_double_class16agg_double_class(double inreg %{{.*}}) agg_double_class pass_agg_double_class(agg_double_class arg) { return arg; } struct agg_float_cpp { float a; int : 0; }; -// CHECK-BE-LABEL: define{{.*}} void @_Z18pass_agg_float_cpp13agg_float_cpp(ptr noalias sret(%struct.agg_float_cpp) align 4 %{{.*}}, float inreg %{{.*}}) +// CHECK-BE-LABEL: define{{.*}} void @_Z18pass_agg_float_cpp13agg_float_cpp(ptr dead_on_unwind noalias writable sret(%struct.agg_float_cpp) align 4 %{{.*}}, float inreg %{{.*}}) // CHECK-LE-LABEL: define{{.*}} [1 x float] @_Z18pass_agg_float_cpp13agg_float_cpp(float inreg %{{.*}}) agg_float_cpp pass_agg_float_cpp(agg_float_cpp arg) { return arg; } struct empty { }; struct agg_nofloat_empty { float a; empty dummy; }; -// CHECK-BE-LABEL: define{{.*}} void @_Z22pass_agg_nofloat_empty17agg_nofloat_empty(ptr noalias sret(%struct.agg_nofloat_empty) align 4 %{{.*}}, i64 %{{.*}}) +// CHECK-BE-LABEL: define{{.*}} void @_Z22pass_agg_nofloat_empty17agg_nofloat_empty(ptr dead_on_unwind noalias writable sret(%struct.agg_nofloat_empty) align 4 %{{.*}}, i64 %{{.*}}) // CHECK-LE-LABEL: define{{.*}} i64 @_Z22pass_agg_nofloat_empty17agg_nofloat_empty(i64 %{{.*}}) agg_nofloat_empty pass_agg_nofloat_empty(agg_nofloat_empty arg) { return arg; } struct agg_float_empty { float a; [[no_unique_address]] empty dummy; }; -// CHECK-BE-LABEL: define{{.*}} void @_Z20pass_agg_float_empty15agg_float_empty(ptr noalias sret(%struct.agg_float_empty) align 4 %{{.*}}, float inreg %{{.*}}) +// CHECK-BE-LABEL: define{{.*}} void @_Z20pass_agg_float_empty15agg_float_empty(ptr dead_on_unwind noalias writable sret(%struct.agg_float_empty) align 4 %{{.*}}, float inreg %{{.*}}) // CHECK-LE-LABEL: define{{.*}} [1 x float] @_Z20pass_agg_float_empty15agg_float_empty(float inreg %{{.*}}) agg_float_empty pass_agg_float_empty(agg_float_empty arg) { return arg; } struct agg_nofloat_emptyarray { float a; [[no_unique_address]] empty dummy[3]; }; -// CHECK-BE-LABEL: define{{.*}} void @_Z27pass_agg_nofloat_emptyarray22agg_nofloat_emptyarray(ptr noalias sret(%struct.agg_nofloat_emptyarray) align 4 %{{.*}}, i64 %{{.*}}) +// CHECK-BE-LABEL: define{{.*}} void @_Z27pass_agg_nofloat_emptyarray22agg_nofloat_emptyarray(ptr dead_on_unwind noalias writable sret(%struct.agg_nofloat_emptyarray) align 4 %{{.*}}, i64 %{{.*}}) // CHECK-LE-LABEL: define{{.*}} i64 @_Z27pass_agg_nofloat_emptyarray22agg_nofloat_emptyarray(i64 %{{.*}}) agg_nofloat_emptyarray pass_agg_nofloat_emptyarray(agg_nofloat_emptyarray arg) { return arg; } struct noemptybase { empty dummy; }; struct agg_nofloat_emptybase : noemptybase { float a; }; -// CHECK-BE-LABEL: define{{.*}} void @_Z26pass_agg_nofloat_emptybase21agg_nofloat_emptybase(ptr noalias sret(%struct.agg_nofloat_emptybase) align 4 %{{.*}}, i64 %{{.*}}) +// CHECK-BE-LABEL: define{{.*}} void @_Z26pass_agg_nofloat_emptybase21agg_nofloat_emptybase(ptr dead_on_unwind noalias writable sret(%struct.agg_nofloat_emptybase) align 4 %{{.*}}, i64 %{{.*}}) // CHECK-LE-LABEL: define{{.*}} i64 @_Z26pass_agg_nofloat_emptybase21agg_nofloat_emptybase(i64 %{{.*}}) agg_nofloat_emptybase pass_agg_nofloat_emptybase(agg_nofloat_emptybase arg) { return arg; } struct emptybase { [[no_unique_address]] empty dummy; }; struct agg_float_emptybase : emptybase { float a; }; -// CHECK-BE-LABEL: define{{.*}} void @_Z24pass_agg_float_emptybase19agg_float_emptybase(ptr noalias sret(%struct.agg_float_emptybase) align 4 %{{.*}}, float inreg %{{.*}}) +// CHECK-BE-LABEL: define{{.*}} void @_Z24pass_agg_float_emptybase19agg_float_emptybase(ptr dead_on_unwind noalias writable sret(%struct.agg_float_emptybase) align 4 %{{.*}}, float inreg %{{.*}}) // CHECK-LE-LABEL: define{{.*}} [1 x float] @_Z24pass_agg_float_emptybase19agg_float_emptybase(float inreg %{{.*}}) agg_float_emptybase pass_agg_float_emptybase(agg_float_emptybase arg) { return arg; } struct noemptybasearray { [[no_unique_address]] empty dummy[3]; }; struct agg_nofloat_emptybasearray : noemptybasearray { float a; }; -// CHECK-BE-LABEL: define{{.*}} void @_Z31pass_agg_nofloat_emptybasearray26agg_nofloat_emptybasearray(ptr noalias sret(%struct.agg_nofloat_emptybasearray) align 4 %{{.*}}, i64 %{{.*}}) +// CHECK-BE-LABEL: define{{.*}} void @_Z31pass_agg_nofloat_emptybasearray26agg_nofloat_emptybasearray(ptr dead_on_unwind noalias writable sret(%struct.agg_nofloat_emptybasearray) align 4 %{{.*}}, i64 %{{.*}}) // CHECK-LE-LABEL: define{{.*}} i64 @_Z31pass_agg_nofloat_emptybasearray26agg_nofloat_emptybasearray(i64 %{{.*}}) agg_nofloat_emptybasearray pass_agg_nofloat_emptybasearray(agg_nofloat_emptybasearray arg) { return arg; } -// CHECK-BE: call void @_Z24pass_agg_float_emptybase19agg_float_emptybase(ptr sret(%struct.agg_float_emptybase) align 4 %{{.*}}, float inreg %{{.*}}) +// CHECK-BE: call void @_Z24pass_agg_float_emptybase19agg_float_emptybase(ptr dead_on_unwind writable sret(%struct.agg_float_emptybase) align 4 %{{.*}}, float inreg %{{.*}}) // CHECK-LE: call [1 x float] @_Z24pass_agg_float_emptybase19agg_float_emptybase(float inreg %{{.*}}) void pass_agg_float_emptybase_ptr(agg_float_emptybase* arg) { pass_agg_float_emptybase(*arg); } -// CHECK-BE: call void @_Z26pass_agg_nofloat_emptybase21agg_nofloat_emptybase(ptr sret(%struct.agg_nofloat_emptybase) align 4 %{{.*}}, i64 %{{.*}}) +// CHECK-BE: call void @_Z26pass_agg_nofloat_emptybase21agg_nofloat_emptybase(ptr dead_on_unwind writable sret(%struct.agg_nofloat_emptybase) align 4 %{{.*}}, i64 %{{.*}}) // CHECK-LE: call i64 @_Z26pass_agg_nofloat_emptybase21agg_nofloat_emptybase(i64 %{{.*}}) void pass_agg_nofloat_emptybase_ptr(agg_nofloat_emptybase* arg) { pass_agg_nofloat_emptybase(*arg); } diff --git a/clang/test/CodeGen/PowerPC/ppc32-and-aix-struct-return.c b/clang/test/CodeGen/PowerPC/ppc32-and-aix-struct-return.c index b0bb089d664c2ec95eb8a92f0ddf86aea0caee0e..cfe5c1ca3e85158d8f2127e5576bfb6a50352357 100644 --- a/clang/test/CodeGen/PowerPC/ppc32-and-aix-struct-return.c +++ b/clang/test/CodeGen/PowerPC/ppc32-and-aix-struct-return.c @@ -59,42 +59,42 @@ typedef struct { char c[9]; } Nine; -// CHECK-AIX-LABEL: define{{.*}} void @ret0(ptr noalias sret(%struct.Zero) {{[^,]*}}) +// CHECK-AIX-LABEL: define{{.*}} void @ret0(ptr dead_on_unwind noalias writable sret(%struct.Zero) {{[^,]*}}) // CHECK-SVR4-LABEL: define{{.*}} void @ret0() Zero ret0(void) { return (Zero){}; } -// CHECK-AIX-LABEL: define{{.*}} void @ret1(ptr noalias sret(%struct.One) {{[^,]*}}) +// CHECK-AIX-LABEL: define{{.*}} void @ret1(ptr dead_on_unwind noalias writable sret(%struct.One) {{[^,]*}}) // CHECK-SVR4-LABEL: define{{.*}} i8 @ret1() One ret1(void) { return (One){'a'}; } -// CHECK-AIX-LABEL: define{{.*}} void @ret2(ptr noalias sret(%struct.Two) {{[^,]*}}) +// CHECK-AIX-LABEL: define{{.*}} void @ret2(ptr dead_on_unwind noalias writable sret(%struct.Two) {{[^,]*}}) // CHECK-SVR4-LABEL: define{{.*}} i16 @ret2() Two ret2(void) { return (Two){123}; } -// CHECK-AIX-LABEL: define{{.*}} void @ret3(ptr noalias sret(%struct.Three) {{[^,]*}}) +// CHECK-AIX-LABEL: define{{.*}} void @ret3(ptr dead_on_unwind noalias writable sret(%struct.Three) {{[^,]*}}) // CHECK-SVR4-LABEL: define{{.*}} i24 @ret3() Three ret3(void) { return (Three){"abc"}; } -// CHECK-AIX-LABEL: define{{.*}} void @ret4(ptr noalias sret(%struct.Four) {{[^,]*}}) +// CHECK-AIX-LABEL: define{{.*}} void @ret4(ptr dead_on_unwind noalias writable sret(%struct.Four) {{[^,]*}}) // CHECK-SVR4-LABEL: define{{.*}} i32 @ret4() Four ret4(void) { return (Four){0.4}; } -// CHECK-AIX-LABEL: define{{.*}} void @ret5(ptr noalias sret(%struct.Five) {{[^,]*}}) +// CHECK-AIX-LABEL: define{{.*}} void @ret5(ptr dead_on_unwind noalias writable sret(%struct.Five) {{[^,]*}}) // CHECK-SVR4-LABEL: define{{.*}} i40 @ret5() Five ret5(void) { return (Five){"abcde"}; } -// CHECK-AIX-LABEL: define{{.*}} void @ret6(ptr noalias sret(%struct.Six) {{[^,]*}}) +// CHECK-AIX-LABEL: define{{.*}} void @ret6(ptr dead_on_unwind noalias writable sret(%struct.Six) {{[^,]*}}) // CHECK-SVR4-LABEL: define{{.*}} i48 @ret6() Six ret6(void) { return (Six){12, 34, 56}; } -// CHECK-AIX-LABEL: define{{.*}} void @ret7(ptr noalias sret(%struct.Seven) {{[^,]*}}) +// CHECK-AIX-LABEL: define{{.*}} void @ret7(ptr dead_on_unwind noalias writable sret(%struct.Seven) {{[^,]*}}) // CHECK-SVR4-LABEL: define{{.*}} i56 @ret7() Seven ret7(void) { return (Seven){"abcdefg"}; } -// CHECK-AIX-LABEL: define{{.*}} void @ret8(ptr noalias sret(%struct.Eight) {{[^,]*}}) +// CHECK-AIX-LABEL: define{{.*}} void @ret8(ptr dead_on_unwind noalias writable sret(%struct.Eight) {{[^,]*}}) // CHECK-SVR4-LABEL: define{{.*}} i64 @ret8() Eight ret8(void) { return (Eight){123, 'a'}; } -// CHECK-AIX-LABEL: define{{.*}} void @ret9(ptr noalias sret(%struct.Nine) {{[^,]*}}) -// CHECK-SVR4-LABEL: define{{.*}} void @ret9(ptr noalias sret(%struct.Nine) {{[^,]*}}) +// CHECK-AIX-LABEL: define{{.*}} void @ret9(ptr dead_on_unwind noalias writable sret(%struct.Nine) {{[^,]*}}) +// CHECK-SVR4-LABEL: define{{.*}} void @ret9(ptr dead_on_unwind noalias writable sret(%struct.Nine) {{[^,]*}}) Nine ret9(void) { return (Nine){"abcdefghi"}; } diff --git a/clang/test/CodeGen/PowerPC/ppc64-align-struct.c b/clang/test/CodeGen/PowerPC/ppc64-align-struct.c index 2476c7149d0767c603b0ae73a3d43b7d088da4e5..50e8330fceaec4818c6a44381ad26e115c1079e0 100644 --- a/clang/test/CodeGen/PowerPC/ppc64-align-struct.c +++ b/clang/test/CodeGen/PowerPC/ppc64-align-struct.c @@ -60,7 +60,7 @@ void test9 (int x, struct test9 y) { } -// CHECK: define{{.*}} void @test1va(ptr noalias sret(%struct.test1) align 4 %[[AGG_RESULT:.*]], i32 noundef signext %x, ...) +// CHECK: define{{.*}} void @test1va(ptr dead_on_unwind noalias writable sret(%struct.test1) align 4 %[[AGG_RESULT:.*]], i32 noundef signext %x, ...) // CHECK: %[[CUR:[^ ]+]] = load ptr, ptr %ap // CHECK: %[[NEXT:[^ ]+]] = getelementptr inbounds i8, ptr %[[CUR]], i64 8 // CHECK: store ptr %[[NEXT]], ptr %ap @@ -75,7 +75,7 @@ struct test1 test1va (int x, ...) return y; } -// CHECK: define{{.*}} void @test2va(ptr noalias sret(%struct.test2) align 16 %[[AGG_RESULT:.*]], i32 noundef signext %x, ...) +// CHECK: define{{.*}} void @test2va(ptr dead_on_unwind noalias writable sret(%struct.test2) align 16 %[[AGG_RESULT:.*]], i32 noundef signext %x, ...) // CHECK: %[[CUR:[^ ]+]] = load ptr, ptr %ap // CHECK: %[[TMP0:[^ ]+]] = getelementptr inbounds i8, ptr %[[CUR]], i32 15 // CHECK: %[[ALIGN:[^ ]+]] = call ptr @llvm.ptrmask.p0.i64(ptr %[[TMP0]], i64 -16) @@ -92,7 +92,7 @@ struct test2 test2va (int x, ...) return y; } -// CHECK: define{{.*}} void @test3va(ptr noalias sret(%struct.test3) align 32 %[[AGG_RESULT:.*]], i32 noundef signext %x, ...) +// CHECK: define{{.*}} void @test3va(ptr dead_on_unwind noalias writable sret(%struct.test3) align 32 %[[AGG_RESULT:.*]], i32 noundef signext %x, ...) // CHECK: %[[CUR:[^ ]+]] = load ptr, ptr %ap // CHECK: %[[TMP0:[^ ]+]] = getelementptr inbounds i8, ptr %[[CUR]], i32 15 // CHECK: %[[ALIGN:[^ ]+]] = call ptr @llvm.ptrmask.p0.i64(ptr %[[TMP0]], i64 -16) @@ -109,7 +109,7 @@ struct test3 test3va (int x, ...) return y; } -// CHECK: define{{.*}} void @test4va(ptr noalias sret(%struct.test4) align 4 %[[AGG_RESULT:.*]], i32 noundef signext %x, ...) +// CHECK: define{{.*}} void @test4va(ptr dead_on_unwind noalias writable sret(%struct.test4) align 4 %[[AGG_RESULT:.*]], i32 noundef signext %x, ...) // CHECK: %[[CUR:[^ ]+]] = load ptr, ptr %ap // CHECK: %[[NEXT:[^ ]+]] = getelementptr inbounds i8, ptr %[[CUR]], i64 16 // CHECK: store ptr %[[NEXT]], ptr %ap @@ -124,7 +124,7 @@ struct test4 test4va (int x, ...) return y; } -// CHECK: define{{.*}} void @test8va(ptr noalias sret(%struct.test8) align 1 %[[AGG_RESULT:.*]], i32 noundef signext %x, ...) +// CHECK: define{{.*}} void @test8va(ptr dead_on_unwind noalias writable sret(%struct.test8) align 1 %[[AGG_RESULT:.*]], i32 noundef signext %x, ...) // CHECK: %[[CUR:[^ ]+]] = load ptr, ptr %ap // CHECK: %[[NEXT:[^ ]+]] = getelementptr inbounds i8, ptr %[[CUR]], i64 8 // CHECK: store ptr %[[NEXT]], ptr %ap @@ -140,7 +140,7 @@ struct test8 test8va (int x, ...) return y; } -// CHECK: define{{.*}} void @test9va(ptr noalias sret(%struct.test9) align 1 %[[AGG_RESULT:.*]], i32 noundef signext %x, ...) +// CHECK: define{{.*}} void @test9va(ptr dead_on_unwind noalias writable sret(%struct.test9) align 1 %[[AGG_RESULT:.*]], i32 noundef signext %x, ...) // CHECK: %[[CUR:[^ ]+]] = load ptr, ptr %ap // CHECK: %[[NEXT:[^ ]+]] = getelementptr inbounds i8, ptr %[[CUR]], i64 8 // CHECK: store ptr %[[NEXT]], ptr %ap @@ -156,7 +156,7 @@ struct test9 test9va (int x, ...) return y; } -// CHECK: define{{.*}} void @testva_longdouble(ptr noalias sret(%struct.test_longdouble) align 16 %[[AGG_RESULT:.*]], i32 noundef signext %x, ...) +// CHECK: define{{.*}} void @testva_longdouble(ptr dead_on_unwind noalias writable sret(%struct.test_longdouble) align 16 %[[AGG_RESULT:.*]], i32 noundef signext %x, ...) // CHECK: %[[CUR:[^ ]+]] = load ptr, ptr %ap // CHECK: %[[NEXT:[^ ]+]] = getelementptr inbounds i8, ptr %[[CUR]], i64 16 // CHECK: store ptr %[[NEXT]], ptr %ap @@ -172,7 +172,7 @@ struct test_longdouble testva_longdouble (int x, ...) return y; } -// CHECK: define{{.*}} void @testva_vector(ptr noalias sret(%struct.test_vector) align 16 %[[AGG_RESULT:.*]], i32 noundef signext %x, ...) +// CHECK: define{{.*}} void @testva_vector(ptr dead_on_unwind noalias writable sret(%struct.test_vector) align 16 %[[AGG_RESULT:.*]], i32 noundef signext %x, ...) // CHECK: %[[CUR:[^ ]+]] = load ptr, ptr %ap // CHECK: %[[TMP0:[^ ]+]] = getelementptr inbounds i8, ptr %[[CUR]], i32 15 // CHECK: %[[ALIGN:[^ ]+]] = call ptr @llvm.ptrmask.p0.i64(ptr %[[TMP0]], i64 -16) diff --git a/clang/test/CodeGen/PowerPC/ppc64-elf-abi.c b/clang/test/CodeGen/PowerPC/ppc64-elf-abi.c index 64bff635af953b7d970a6a91038f9bdd66c3d43f..fa7f79455fda41f01bb9c3e460c14f364d349546 100644 --- a/clang/test/CodeGen/PowerPC/ppc64-elf-abi.c +++ b/clang/test/CodeGen/PowerPC/ppc64-elf-abi.c @@ -15,7 +15,7 @@ // RUN: %clang_cc1 -triple powerpc64le-unknown-linux-gnu -emit-llvm -o - %s \ // RUN: -target-abi elfv2 | FileCheck %s --check-prefix=CHECK-ELFv2 -// CHECK-ELFv1: define{{.*}} void @func_fab(ptr noalias sret(%struct.fab) align 4 %agg.result, i64 %x.coerce) +// CHECK-ELFv1: define{{.*}} void @func_fab(ptr dead_on_unwind noalias writable sret(%struct.fab) align 4 %agg.result, i64 %x.coerce) // CHECK-ELFv2: define{{.*}} [2 x float] @func_fab([2 x float] %x.coerce) struct fab { float a; float b; }; struct fab func_fab(struct fab x) { return x; } diff --git a/clang/test/CodeGen/PowerPC/ppc64-soft-float.c b/clang/test/CodeGen/PowerPC/ppc64-soft-float.c index c2e887ef7ab6e2619ca0424af2d7140915f2abbb..812d9ff5a3509725712a6b098166a79bba674c2a 100644 --- a/clang/test/CodeGen/PowerPC/ppc64-soft-float.c +++ b/clang/test/CodeGen/PowerPC/ppc64-soft-float.c @@ -30,53 +30,53 @@ struct fabc { float a; float b; float c; }; struct f2a2b { float a[2]; float b[2]; }; // CHECK-LE: define{{.*}} i32 @func_f1(float inreg %x.coerce) -// CHECK-BE: define{{.*}} void @func_f1(ptr noalias sret(%struct.f1) align 4 %agg.result, float inreg %x.coerce) +// CHECK-BE: define{{.*}} void @func_f1(ptr dead_on_unwind noalias writable sret(%struct.f1) align 4 %agg.result, float inreg %x.coerce) struct f1 func_f1(struct f1 x) { return x; } // CHECK-LE: define{{.*}} i64 @func_f2(i64 %x.coerce) -// CHECK-BE: define{{.*}} void @func_f2(ptr noalias sret(%struct.f2) align 4 %agg.result, i64 %x.coerce) +// CHECK-BE: define{{.*}} void @func_f2(ptr dead_on_unwind noalias writable sret(%struct.f2) align 4 %agg.result, i64 %x.coerce) struct f2 func_f2(struct f2 x) { return x; } // CHECK-LE: define{{.*}} { i64, i64 } @func_f3([2 x i64] %x.coerce) -// CHECK-BE: define{{.*}} void @func_f3(ptr noalias sret(%struct.f3) align 4 %agg.result, [2 x i64] %x.coerce) +// CHECK-BE: define{{.*}} void @func_f3(ptr dead_on_unwind noalias writable sret(%struct.f3) align 4 %agg.result, [2 x i64] %x.coerce) struct f3 func_f3(struct f3 x) { return x; } // CHECK-LE: define{{.*}} { i64, i64 } @func_f4([2 x i64] %x.coerce) -// CHECK-BE: define{{.*}} void @func_f4(ptr noalias sret(%struct.f4) align 4 %agg.result, [2 x i64] %x.coerce) +// CHECK-BE: define{{.*}} void @func_f4(ptr dead_on_unwind noalias writable sret(%struct.f4) align 4 %agg.result, [2 x i64] %x.coerce) struct f4 func_f4(struct f4 x) { return x; } -// CHECK: define{{.*}} void @func_f5(ptr noalias sret(%struct.f5) align 4 %agg.result, [3 x i64] %x.coerce) +// CHECK: define{{.*}} void @func_f5(ptr dead_on_unwind noalias writable sret(%struct.f5) align 4 %agg.result, [3 x i64] %x.coerce) struct f5 func_f5(struct f5 x) { return x; } -// CHECK: define{{.*}} void @func_f6(ptr noalias sret(%struct.f6) align 4 %agg.result, [3 x i64] %x.coerce) +// CHECK: define{{.*}} void @func_f6(ptr dead_on_unwind noalias writable sret(%struct.f6) align 4 %agg.result, [3 x i64] %x.coerce) struct f6 func_f6(struct f6 x) { return x; } -// CHECK: define{{.*}} void @func_f7(ptr noalias sret(%struct.f7) align 4 %agg.result, [4 x i64] %x.coerce) +// CHECK: define{{.*}} void @func_f7(ptr dead_on_unwind noalias writable sret(%struct.f7) align 4 %agg.result, [4 x i64] %x.coerce) struct f7 func_f7(struct f7 x) { return x; } -// CHECK: define{{.*}} void @func_f8(ptr noalias sret(%struct.f8) align 4 %agg.result, [4 x i64] %x.coerce) +// CHECK: define{{.*}} void @func_f8(ptr dead_on_unwind noalias writable sret(%struct.f8) align 4 %agg.result, [4 x i64] %x.coerce) struct f8 func_f8(struct f8 x) { return x; } -// CHECK: define{{.*}} void @func_f9(ptr noalias sret(%struct.f9) align 4 %agg.result, [5 x i64] %x.coerce) +// CHECK: define{{.*}} void @func_f9(ptr dead_on_unwind noalias writable sret(%struct.f9) align 4 %agg.result, [5 x i64] %x.coerce) struct f9 func_f9(struct f9 x) { return x; } // CHECK-LE: define{{.*}} i64 @func_fab(i64 %x.coerce) -// CHECK-BE: define{{.*}} void @func_fab(ptr noalias sret(%struct.fab) align 4 %agg.result, i64 %x.coerce) +// CHECK-BE: define{{.*}} void @func_fab(ptr dead_on_unwind noalias writable sret(%struct.fab) align 4 %agg.result, i64 %x.coerce) struct fab func_fab(struct fab x) { return x; } // CHECK-LE: define{{.*}} { i64, i64 } @func_fabc([2 x i64] %x.coerce) -// CHECK-BE: define{{.*}} void @func_fabc(ptr noalias sret(%struct.fabc) align 4 %agg.result, [2 x i64] %x.coerce) +// CHECK-BE: define{{.*}} void @func_fabc(ptr dead_on_unwind noalias writable sret(%struct.fabc) align 4 %agg.result, [2 x i64] %x.coerce) struct fabc func_fabc(struct fabc x) { return x; } // CHECK-LE: define{{.*}} { i64, i64 } @func_f2a2b([2 x i64] %x.coerce) -// CHECK-BE: define{{.*}} void @func_f2a2b(ptr noalias sret(%struct.f2a2b) align 4 %agg.result, [2 x i64] %x.coerce) +// CHECK-BE: define{{.*}} void @func_f2a2b(ptr dead_on_unwind noalias writable sret(%struct.f2a2b) align 4 %agg.result, [2 x i64] %x.coerce) struct f2a2b func_f2a2b(struct f2a2b x) { return x; } // CHECK-LABEL: @call_f1 // CHECK-BE: %[[TMP0:[^ ]+]] = alloca %struct.f1, align 4 // CHECK: %[[TMP:[^ ]+]] = load float, ptr @global_f1, align 4 // CHECK-LE: call i32 @func_f1(float inreg %[[TMP]]) -// CHECK-BE: call void @func_f1(ptr sret(%struct.f1) align 4 %[[TMP0]], float inreg %[[TMP]]) +// CHECK-BE: call void @func_f1(ptr dead_on_unwind writable sret(%struct.f1) align 4 %[[TMP0]], float inreg %[[TMP]]) struct f1 global_f1; void call_f1(void) { global_f1 = func_f1(global_f1); } @@ -84,7 +84,7 @@ void call_f1(void) { global_f1 = func_f1(global_f1); } // CHECK-BE: %[[TMP0:[^ ]+]] = alloca %struct.f2, align 4 // CHECK: %[[TMP:[^ ]+]] = load i64, ptr @global_f2, align 4 // CHECK-LE: call i64 @func_f2(i64 %[[TMP]]) -// CHECK-BE: call void @func_f2(ptr sret(%struct.f2) align 4 %[[TMP0]], i64 %[[TMP]]) +// CHECK-BE: call void @func_f2(ptr dead_on_unwind writable sret(%struct.f2) align 4 %[[TMP0]], i64 %[[TMP]]) struct f2 global_f2; void call_f2(void) { global_f2 = func_f2(global_f2); } @@ -94,7 +94,7 @@ void call_f2(void) { global_f2 = func_f2(global_f2); } // CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %[[TMP1]], ptr align 4 @global_f3, i64 12, i1 false) // CHECK: %[[TMP3:[^ ]+]] = load [2 x i64], ptr %[[TMP1]] // CHECK-LE: call { i64, i64 } @func_f3([2 x i64] %[[TMP3]]) -// CHECK-BE: call void @func_f3(ptr sret(%struct.f3) align 4 %[[TMP0]], [2 x i64] %[[TMP3]]) +// CHECK-BE: call void @func_f3(ptr dead_on_unwind writable sret(%struct.f3) align 4 %[[TMP0]], [2 x i64] %[[TMP3]]) struct f3 global_f3; void call_f3(void) { global_f3 = func_f3(global_f3); } @@ -102,7 +102,7 @@ void call_f3(void) { global_f3 = func_f3(global_f3); } // CHECK-BE: %[[TMP0:[^ ]+]] = alloca %struct.f4, align 4 // CHECK: %[[TMP:[^ ]+]] = load [2 x i64], ptr @global_f4, align 4 // CHECK-LE: call { i64, i64 } @func_f4([2 x i64] %[[TMP]]) -// CHECK-BE: call void @func_f4(ptr sret(%struct.f4) align 4 %[[TMP0]], [2 x i64] %[[TMP]]) +// CHECK-BE: call void @func_f4(ptr dead_on_unwind writable sret(%struct.f4) align 4 %[[TMP0]], [2 x i64] %[[TMP]]) struct f4 global_f4; void call_f4(void) { global_f4 = func_f4(global_f4); } @@ -111,14 +111,14 @@ void call_f4(void) { global_f4 = func_f4(global_f4); } // CHECK: %[[TMP1:[^ ]+]] = alloca [3 x i64] // CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %[[TMP1]], ptr align 4 @global_f5, i64 20, i1 false) // CHECK: %[[TMP3:[^ ]+]] = load [3 x i64], ptr %[[TMP1]] -// CHECK: call void @func_f5(ptr sret(%struct.f5) align 4 %[[TMP0]], [3 x i64] %[[TMP3]]) +// CHECK: call void @func_f5(ptr dead_on_unwind writable sret(%struct.f5) align 4 %[[TMP0]], [3 x i64] %[[TMP3]]) struct f5 global_f5; void call_f5(void) { global_f5 = func_f5(global_f5); } // CHECK-LABEL: @call_f6 // CHECK: %[[TMP0:[^ ]+]] = alloca %struct.f6, align 4 // CHECK: %[[TMP:[^ ]+]] = load [3 x i64], ptr @global_f6, align 4 -// CHECK: call void @func_f6(ptr sret(%struct.f6) align 4 %[[TMP0]], [3 x i64] %[[TMP]]) +// CHECK: call void @func_f6(ptr dead_on_unwind writable sret(%struct.f6) align 4 %[[TMP0]], [3 x i64] %[[TMP]]) struct f6 global_f6; void call_f6(void) { global_f6 = func_f6(global_f6); } @@ -127,14 +127,14 @@ void call_f6(void) { global_f6 = func_f6(global_f6); } // CHECK: %[[TMP1:[^ ]+]] = alloca [4 x i64], align 8 // CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %[[TMP1]], ptr align 4 @global_f7, i64 28, i1 false) // CHECK: %[[TMP3:[^ ]+]] = load [4 x i64], ptr %[[TMP1]], align 8 -// CHECK: call void @func_f7(ptr sret(%struct.f7) align 4 %[[TMP0]], [4 x i64] %[[TMP3]]) +// CHECK: call void @func_f7(ptr dead_on_unwind writable sret(%struct.f7) align 4 %[[TMP0]], [4 x i64] %[[TMP3]]) struct f7 global_f7; void call_f7(void) { global_f7 = func_f7(global_f7); } // CHECK-LABEL: @call_f8 // CHECK: %[[TMP0:[^ ]+]] = alloca %struct.f8, align 4 // CHECK: %[[TMP:[^ ]+]] = load [4 x i64], ptr @global_f8, align 4 -// CHECK: call void @func_f8(ptr sret(%struct.f8) align 4 %[[TMP0]], [4 x i64] %[[TMP]]) +// CHECK: call void @func_f8(ptr dead_on_unwind writable sret(%struct.f8) align 4 %[[TMP0]], [4 x i64] %[[TMP]]) struct f8 global_f8; void call_f8(void) { global_f8 = func_f8(global_f8); } @@ -142,7 +142,7 @@ void call_f8(void) { global_f8 = func_f8(global_f8); } // CHECK: %[[TMP1:[^ ]+]] = alloca [5 x i64] // CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %[[TMP1]], ptr align 4 @global_f9, i64 36, i1 false) // CHECK: %[[TMP3:[^ ]+]] = load [5 x i64], ptr %[[TMP1]] -// CHECK: call void @func_f9(ptr sret(%struct.f9) align 4 %{{[^ ]+}}, [5 x i64] %[[TMP3]]) +// CHECK: call void @func_f9(ptr dead_on_unwind writable sret(%struct.f9) align 4 %{{[^ ]+}}, [5 x i64] %[[TMP3]]) struct f9 global_f9; void call_f9(void) { global_f9 = func_f9(global_f9); } @@ -150,7 +150,7 @@ void call_f9(void) { global_f9 = func_f9(global_f9); } // CHECK: %[[TMP0:[^ ]+]] = alloca %struct.fab, align 4 // CHECK: %[[TMP:[^ ]+]] = load i64, ptr @global_fab, align 4 // CHECK-LE: %call = call i64 @func_fab(i64 %[[TMP]]) -// CHECK-BE: call void @func_fab(ptr sret(%struct.fab) align 4 %[[TMP0]], i64 %[[TMP]]) +// CHECK-BE: call void @func_fab(ptr dead_on_unwind writable sret(%struct.fab) align 4 %[[TMP0]], i64 %[[TMP]]) struct fab global_fab; void call_fab(void) { global_fab = func_fab(global_fab); } @@ -160,7 +160,7 @@ void call_fab(void) { global_fab = func_fab(global_fab); } // CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %[[TMP0]], ptr align 4 @global_fabc, i64 12, i1 false) // CHECK: %[[TMP3:[^ ]+]] = load [2 x i64], ptr %[[TMP0]], align 8 // CHECK-LE: %call = call { i64, i64 } @func_fabc([2 x i64] %[[TMP3]]) -// CHECK-BE: call void @func_fabc(ptr sret(%struct.fabc) align 4 %[[TMPX]], [2 x i64] %[[TMP3]]) +// CHECK-BE: call void @func_fabc(ptr dead_on_unwind writable sret(%struct.fabc) align 4 %[[TMPX]], [2 x i64] %[[TMP3]]) struct fabc global_fabc; void call_fabc(void) { global_fabc = func_fabc(global_fabc); } diff --git a/clang/test/CodeGen/PowerPC/ppc64-vector.c b/clang/test/CodeGen/PowerPC/ppc64-vector.c index 2e685799efa0744ecfccb279fe431fb97e4a2fa4..5d3dd86a009d51e58371d55e22dec5dca1a2f25a 100644 --- a/clang/test/CodeGen/PowerPC/ppc64-vector.c +++ b/clang/test/CodeGen/PowerPC/ppc64-vector.c @@ -39,13 +39,13 @@ v8i16 test_v8i16(v8i16 x) return x; } -// CHECK: define{{.*}} void @test_v16i16(ptr noalias sret(<16 x i16>) align 32 %agg.result, ptr noundef %0) +// CHECK: define{{.*}} void @test_v16i16(ptr dead_on_unwind noalias writable sret(<16 x i16>) align 32 %agg.result, ptr noundef %0) v16i16 test_v16i16(v16i16 x) { return x; } -// CHECK: define{{.*}} void @test_struct_v16i16(ptr noalias sret(%struct.v16i16) align 32 %agg.result, [2 x i128] %x.coerce) +// CHECK: define{{.*}} void @test_struct_v16i16(ptr dead_on_unwind noalias writable sret(%struct.v16i16) align 32 %agg.result, [2 x i128] %x.coerce) struct v16i16 test_struct_v16i16(struct v16i16 x) { return x; diff --git a/clang/test/CodeGen/PowerPC/ppc64le-aggregates.c b/clang/test/CodeGen/PowerPC/ppc64le-aggregates.c index 42b179217dd2ec7c20e7a8fd6f6083b1eaa376e4..3ea85a6a8ff3b70d72dabb85d5e2aa87a6e3ce90 100644 --- a/clang/test/CodeGen/PowerPC/ppc64le-aggregates.c +++ b/clang/test/CodeGen/PowerPC/ppc64le-aggregates.c @@ -41,7 +41,7 @@ struct f7 func_f7(struct f7 x) { return x; } // CHECK: define{{.*}} [8 x float] @func_f8([8 x float] %x.coerce) struct f8 func_f8(struct f8 x) { return x; } -// CHECK: define{{.*}} void @func_f9(ptr noalias sret(%struct.f9) align 4 %agg.result, [5 x i64] %x.coerce) +// CHECK: define{{.*}} void @func_f9(ptr dead_on_unwind noalias writable sret(%struct.f9) align 4 %agg.result, [5 x i64] %x.coerce) struct f9 func_f9(struct f9 x) { return x; } // CHECK: define{{.*}} [2 x float] @func_fab([2 x float] %x.coerce) @@ -105,7 +105,7 @@ void call_f8(void) { global_f8 = func_f8(global_f8); } // CHECK: %[[TMP1:[^ ]+]] = alloca [5 x i64] // CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %[[TMP1]], ptr align 4 @global_f9, i64 36, i1 false) // CHECK: %[[TMP3:[^ ]+]] = load [5 x i64], ptr %[[TMP1]] -// CHECK: call void @func_f9(ptr sret(%struct.f9) align 4 %{{[^ ]+}}, [5 x i64] %[[TMP3]]) +// CHECK: call void @func_f9(ptr dead_on_unwind writable sret(%struct.f9) align 4 %{{[^ ]+}}, [5 x i64] %[[TMP3]]) struct f9 global_f9; void call_f9(void) { global_f9 = func_f9(global_f9); } @@ -161,7 +161,7 @@ struct v7 func_v7(struct v7 x) { return x; } // CHECK: define{{.*}} [8 x <4 x i32>] @func_v8([8 x <4 x i32>] %x.coerce) struct v8 func_v8(struct v8 x) { return x; } -// CHECK: define{{.*}} void @func_v9(ptr noalias sret(%struct.v9) align 16 %agg.result, ptr noundef byval(%struct.v9) align 16 %x) +// CHECK: define{{.*}} void @func_v9(ptr dead_on_unwind noalias writable sret(%struct.v9) align 16 %agg.result, ptr noundef byval(%struct.v9) align 16 %x) struct v9 func_v9(struct v9 x) { return x; } // CHECK: define{{.*}} [2 x <4 x i32>] @func_vab([2 x <4 x i32>] %x.coerce) @@ -219,7 +219,7 @@ struct v8 global_v8; void call_v8(void) { global_v8 = func_v8(global_v8); } // CHECK-LABEL: @call_v9 -// CHECK: call void @func_v9(ptr sret(%struct.v9) align 16 %{{[^ ]+}}, ptr noundef byval(%struct.v9) align 16 @global_v9) +// CHECK: call void @func_v9(ptr dead_on_unwind writable sret(%struct.v9) align 16 %{{[^ ]+}}, ptr noundef byval(%struct.v9) align 16 @global_v9) struct v9 global_v9; void call_v9(void) { global_v9 = func_v9(global_v9); } @@ -278,7 +278,7 @@ struct v3f7 func_v3f7(struct v3f7 x) { return x; } // CHECK: define{{.*}} [8 x <4 x float>] @func_v3f8([8 x <4 x float>] %x.coerce) struct v3f8 func_v3f8(struct v3f8 x) { return x; } -// CHECK: define{{.*}} void @func_v3f9(ptr noalias sret(%struct.v3f9) align 16 %agg.result, ptr noundef byval(%struct.v3f9) align 16 %x) +// CHECK: define{{.*}} void @func_v3f9(ptr dead_on_unwind noalias writable sret(%struct.v3f9) align 16 %agg.result, ptr noundef byval(%struct.v3f9) align 16 %x) struct v3f9 func_v3f9(struct v3f9 x) { return x; } // CHECK: define{{.*}} [2 x <4 x float>] @func_v3fab([2 x <4 x float>] %x.coerce) @@ -336,7 +336,7 @@ struct v3f8 global_v3f8; void call_v3f8(void) { global_v3f8 = func_v3f8(global_v3f8); } // CHECK-LABEL: @call_v3f9 -// CHECK: call void @func_v3f9(ptr sret(%struct.v3f9) align 16 %{{[^ ]+}}, ptr noundef byval(%struct.v3f9) align 16 @global_v3f9) +// CHECK: call void @func_v3f9(ptr dead_on_unwind writable sret(%struct.v3f9) align 16 %{{[^ ]+}}, ptr noundef byval(%struct.v3f9) align 16 @global_v3f9) struct v3f9 global_v3f9; void call_v3f9(void) { global_v3f9 = func_v3f9(global_v3f9); } diff --git a/clang/test/CodeGen/PowerPC/ppc64le-f128Aggregates.c b/clang/test/CodeGen/PowerPC/ppc64le-f128Aggregates.c index 27c3b14f0a04b6332296750ae890bc6fefb58e00..b2e79d6be9b87d71e42f0229a77d216a89267813 100644 --- a/clang/test/CodeGen/PowerPC/ppc64le-f128Aggregates.c +++ b/clang/test/CodeGen/PowerPC/ppc64le-f128Aggregates.c @@ -42,7 +42,7 @@ struct fp7 func_f7(struct fp7 x) { return x; } // CHECK: define{{.*}} [8 x fp128] @func_f8([8 x fp128] %x.coerce) struct fp8 func_f8(struct fp8 x) { return x; } -// CHECK: define{{.*}} void @func_f9(ptr noalias sret(%struct.fp9) align 16 %agg.result, ptr noundef byval(%struct.fp9) align 16 %x) +// CHECK: define{{.*}} void @func_f9(ptr dead_on_unwind noalias writable sret(%struct.fp9) align 16 %agg.result, ptr noundef byval(%struct.fp9) align 16 %x) struct fp9 func_f9(struct fp9 x) { return x; } // CHECK: define{{.*}} [2 x fp128] @func_fab([2 x fp128] %x.coerce) @@ -104,7 +104,7 @@ void call_fp8(void) { global_f8 = func_f8(global_f8); } // CHECK-LABEL: @call_fp9 // CHECK: %[[TMP1:[^ ]+]] = alloca %struct.fp9, align 16 -// CHECK: call void @func_f9(ptr sret(%struct.fp9) align 16 %[[TMP2:[^ ]+]], ptr noundef byval(%struct.fp9) align 16 @global_f9 +// CHECK: call void @func_f9(ptr dead_on_unwind writable sret(%struct.fp9) align 16 %[[TMP2:[^ ]+]], ptr noundef byval(%struct.fp9) align 16 @global_f9 // CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 16 @global_f9, ptr align 16 %[[TMP2]], i64 144, i1 false // CHECK: ret void struct fp9 global_f9; diff --git a/clang/test/CodeGen/RISCV/bfloat-abi.c b/clang/test/CodeGen/RISCV/bfloat-abi.c index bfaf1043133b80b021ce73f5a5fec369f3a98625..f38646c8b12ff2d796d26dc71306620df1fad147 100644 --- a/clang/test/CodeGen/RISCV/bfloat-abi.c +++ b/clang/test/CodeGen/RISCV/bfloat-abi.c @@ -467,7 +467,7 @@ struct floatbfloat3 { // CHECK-RV64-NEXT: ret [2 x i64] [[TMP4]] // // CHECK-RV32-LABEL: define dso_local void @fh3 -// CHECK-RV32-SAME: (ptr noalias sret([[STRUCT_FLOATBFLOAT3:%.*]]) align 4 [[AGG_RESULT:%.*]], float noundef [[A:%.*]], bfloat noundef [[B:%.*]], bfloat noundef [[C:%.*]], bfloat noundef [[D:%.*]]) #[[ATTR0]] { +// CHECK-RV32-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_FLOATBFLOAT3:%.*]]) align 4 [[AGG_RESULT:%.*]], float noundef [[A:%.*]], bfloat noundef [[B:%.*]], bfloat noundef [[C:%.*]], bfloat noundef [[D:%.*]]) #[[ATTR0]] { // CHECK-RV32-NEXT: entry: // CHECK-RV32-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 // CHECK-RV32-NEXT: [[A_ADDR:%.*]] = alloca float, align 4 @@ -545,7 +545,7 @@ struct bfloat5 { // CHECK-RV64-NEXT: ret [2 x i64] [[TMP5]] // // CHECK-RV32-LABEL: define dso_local void @h5 -// CHECK-RV32-SAME: (ptr noalias sret([[STRUCT_BFLOAT5:%.*]]) align 2 [[AGG_RESULT:%.*]], bfloat noundef [[A:%.*]], bfloat noundef [[B:%.*]], bfloat noundef [[C:%.*]], bfloat noundef [[D:%.*]], bfloat noundef [[E:%.*]]) #[[ATTR0]] { +// CHECK-RV32-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_BFLOAT5:%.*]]) align 2 [[AGG_RESULT:%.*]], bfloat noundef [[A:%.*]], bfloat noundef [[B:%.*]], bfloat noundef [[C:%.*]], bfloat noundef [[D:%.*]], bfloat noundef [[E:%.*]]) #[[ATTR0]] { // CHECK-RV32-NEXT: entry: // CHECK-RV32-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 // CHECK-RV32-NEXT: [[A_ADDR:%.*]] = alloca bfloat, align 2 diff --git a/clang/test/CodeGen/RISCV/riscv-abi.cpp b/clang/test/CodeGen/RISCV/riscv-abi.cpp index aa18afe41f6dbc5547004cdea7fa9ca4dcd5ecf0..fe1a2b6d8595c078e4a81a2dc64c5d627fc7496c 100644 --- a/clang/test/CodeGen/RISCV/riscv-abi.cpp +++ b/clang/test/CodeGen/RISCV/riscv-abi.cpp @@ -75,7 +75,7 @@ struct child3_int64_s : parent3_float_s { }; // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @_Z30float_int64_struct_inheritance14child3_int64_s -// ILP32-ILP32F-ILP32D-SAME: (ptr noalias sret([[STRUCT_CHILD3_INT64_S:%.*]]) align 8 [[AGG_RESULT:%.*]], ptr noundef [[A:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-ILP32D-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_CHILD3_INT64_S:%.*]]) align 8 [[AGG_RESULT:%.*]], ptr noundef [[A:%.*]]) #[[ATTR0]] { // ILP32-ILP32F-ILP32D: entry: // // LP64-LABEL: define dso_local [2 x i64] @_Z30float_int64_struct_inheritance14child3_int64_s @@ -99,7 +99,7 @@ struct child4_double_s : parent4_double_s { }; // ILP32-ILP32F-LABEL: define dso_local void @_Z32double_double_struct_inheritance15child4_double_s -// ILP32-ILP32F-SAME: (ptr noalias sret([[STRUCT_CHILD4_DOUBLE_S:%.*]]) align 8 [[AGG_RESULT:%.*]], ptr noundef [[A:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_CHILD4_DOUBLE_S:%.*]]) align 8 [[AGG_RESULT:%.*]], ptr noundef [[A:%.*]]) #[[ATTR0]] { // ILP32-ILP32F: entry: // // ILP32D-LABEL: define dso_local { double, double } @_Z32double_double_struct_inheritance15child4_double_s @@ -130,11 +130,11 @@ struct child5_virtual_s : virtual parent5_virtual_s { }; // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @_Z38int32_float_virtual_struct_inheritance16child5_virtual_s -// ILP32-ILP32F-ILP32D-SAME: (ptr noalias sret([[STRUCT_CHILD5_VIRTUAL_S:%.*]]) align 4 [[AGG_RESULT:%.*]], ptr noundef [[A:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-ILP32D-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_CHILD5_VIRTUAL_S:%.*]]) align 4 [[AGG_RESULT:%.*]], ptr noundef [[A:%.*]]) #[[ATTR0]] { // ILP32-ILP32F-ILP32D: entry: // // LP64-LP64F-LP64D-LABEL: define dso_local void @_Z38int32_float_virtual_struct_inheritance16child5_virtual_s -// LP64-LP64F-LP64D-SAME: (ptr noalias sret([[STRUCT_CHILD5_VIRTUAL_S:%.*]]) align 8 [[AGG_RESULT:%.*]], ptr noundef [[A:%.*]]) #[[ATTR0]] { +// LP64-LP64F-LP64D-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_CHILD5_VIRTUAL_S:%.*]]) align 8 [[AGG_RESULT:%.*]], ptr noundef [[A:%.*]]) #[[ATTR0]] { // LP64-LP64F-LP64D: entry: // struct child5_virtual_s int32_float_virtual_struct_inheritance(struct child5_virtual_s a) { diff --git a/clang/test/CodeGen/RISCV/riscv-func-attr-target.c b/clang/test/CodeGen/RISCV/riscv-func-attr-target.c index 506acaba687417ab475ec748b6bfcdb6764e26a0..759c33a2250600470578dab76062caa7c82a230c 100644 --- a/clang/test/CodeGen/RISCV/riscv-func-attr-target.c +++ b/clang/test/CodeGen/RISCV/riscv-func-attr-target.c @@ -40,8 +40,8 @@ __attribute__((target("cpu=sifive-u54"))) void testAttrCpuOnly() {} // 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 #4 = { {{.*}}"target-features"="+64bit,+a,+c,+d,+f,+m,+save-restore,+zbb,+zicsr,+zifencei,-relax" } +// CHECK: attributes #5 = { {{.*}}"target-features"="+64bit,+m,+save-restore,-relax" } // 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" } +// CHECK: attributes #7 = { {{.*}}"target-cpu"="sifive-u54" "target-features"="+64bit,+m,+save-restore,-relax" } +// CHECK: attributes #8 = { {{.*}}"target-cpu"="sifive-u54" "target-features"="+64bit,+a,+c,+d,+f,+m,+save-restore,+zicsr,+zifencei,-relax" } diff --git a/clang/test/CodeGen/RISCV/riscv32-abi.c b/clang/test/CodeGen/RISCV/riscv32-abi.c index 040ae500fc60e43bc4606088cbd10a31eef34e5e..ea1bb3b62ee6fd0419eadc7b32f8d22c99c9fb8d 100644 --- a/clang/test/CodeGen/RISCV/riscv32-abi.c +++ b/clang/test/CodeGen/RISCV/riscv32-abi.c @@ -254,7 +254,7 @@ void f_agg_large(struct large x) { // The address where the struct should be written to will be the first // argument // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_agg_large_ret -// ILP32-ILP32F-ILP32D-SAME: (ptr noalias sret([[STRUCT_LARGE:%.*]]) align 4 [[AGG_RESULT:%.*]], i32 noundef [[I:%.*]], i8 noundef signext [[J:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-ILP32D-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_LARGE:%.*]]) align 4 [[AGG_RESULT:%.*]], i32 noundef [[I:%.*]], i8 noundef signext [[J:%.*]]) #[[ATTR0]] { // ILP32-ILP32F-ILP32D: entry: // struct large f_agg_large_ret(int32_t i, int8_t j) { @@ -272,7 +272,7 @@ void f_vec_large_v16i8(v16i8 x) { } // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_vec_large_v16i8_ret -// ILP32-ILP32F-ILP32D-SAME: (ptr noalias sret(<16 x i8>) align 16 [[AGG_RESULT:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-ILP32D-SAME: (ptr dead_on_unwind noalias writable sret(<16 x i8>) align 16 [[AGG_RESULT:%.*]]) #[[ATTR0]] { // ILP32-ILP32F-ILP32D: entry: // v16i8 f_vec_large_v16i8_ret(void) { @@ -292,7 +292,7 @@ int f_scalar_stack_1(struct tiny a, struct small b, struct small_aligned c, } // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_scalar_stack_2 -// ILP32-ILP32F-ILP32D-SAME: (ptr noalias sret([[STRUCT_LARGE:%.*]]) align 4 [[AGG_RESULT:%.*]], i32 noundef [[A:%.*]], i64 noundef [[B:%.*]], i64 noundef [[C:%.*]], fp128 noundef [[D:%.*]], i8 noundef zeroext [[E:%.*]], i8 noundef signext [[F:%.*]], i8 noundef zeroext [[G:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-ILP32D-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_LARGE:%.*]]) align 4 [[AGG_RESULT:%.*]], i32 noundef [[A:%.*]], i64 noundef [[B:%.*]], i64 noundef [[C:%.*]], fp128 noundef [[D:%.*]], i8 noundef zeroext [[E:%.*]], i8 noundef signext [[F:%.*]], i8 noundef zeroext [[G:%.*]]) #[[ATTR0]] { // ILP32-ILP32F-ILP32D: entry: // struct large f_scalar_stack_2(int32_t a, int64_t b, int64_t c, long double d, @@ -329,7 +329,7 @@ int f_scalar_stack_5(int32_t a, int64_t b, float c, double d, long double e, } // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_scalar_stack_6 -// ILP32-ILP32F-ILP32D-SAME: (ptr noalias sret([[STRUCT_LARGE:%.*]]) align 4 [[AGG_RESULT:%.*]], float noundef [[A:%.*]], i64 noundef [[B:%.*]], double noundef [[C:%.*]], fp128 noundef [[D:%.*]], i8 noundef zeroext [[E:%.*]], i8 noundef signext [[F:%.*]], i8 noundef zeroext [[G:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-ILP32D-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_LARGE:%.*]]) align 4 [[AGG_RESULT:%.*]], float noundef [[A:%.*]], i64 noundef [[B:%.*]], double noundef [[C:%.*]], fp128 noundef [[D:%.*]], i8 noundef zeroext [[E:%.*]], i8 noundef signext [[F:%.*]], i8 noundef zeroext [[G:%.*]]) #[[ATTR0]] { // ILP32-ILP32F-ILP32D: entry: // struct large f_scalar_stack_6(float a, int64_t b, double c, long double d, @@ -374,7 +374,7 @@ struct int_double_s { int a; double b; }; void f_int_double_s_arg(struct int_double_s a) {} // ILP32-ILP32F-LABEL: define dso_local void @f_ret_int_double_s -// ILP32-ILP32F-SAME: (ptr noalias sret([[STRUCT_INT_DOUBLE_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_INT_DOUBLE_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] { // ILP32-ILP32F: entry: // // ILP32D-LABEL: define dso_local { i32, double } @f_ret_int_double_s @@ -490,7 +490,7 @@ struct double_float_s { double f; float g; }; void f_double_double_s_arg(struct double_double_s a) {} // ILP32-ILP32F-LABEL: define dso_local void @f_ret_double_double_s -// ILP32-ILP32F-SAME: (ptr noalias sret([[STRUCT_DOUBLE_DOUBLE_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_DOUBLE_DOUBLE_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] { // ILP32-ILP32F: entry: // // ILP32D-LABEL: define dso_local { double, double } @f_ret_double_double_s @@ -512,7 +512,7 @@ struct double_double_s f_ret_double_double_s(void) { void f_double_float_s_arg(struct double_float_s a) {} // ILP32-ILP32F-LABEL: define dso_local void @f_ret_double_float_s -// ILP32-ILP32F-SAME: (ptr noalias sret([[STRUCT_DOUBLE_FLOAT_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_DOUBLE_FLOAT_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] { // ILP32-ILP32F: entry: // // ILP32D-LABEL: define dso_local { double, float } @f_ret_double_float_s @@ -547,7 +547,7 @@ struct double_int8_zbf_s { double d; int8_t i; int : 0; }; void f_double_int8_s_arg(struct double_int8_s a) {} // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_ret_double_int8_s -// ILP32-ILP32F-ILP32D-SAME: (ptr noalias sret([[STRUCT_DOUBLE_INT8_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-ILP32D-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_DOUBLE_INT8_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] { // ILP32-ILP32F-ILP32D: entry: // struct double_int8_s f_ret_double_int8_s(void) { @@ -565,7 +565,7 @@ struct double_int8_s f_ret_double_int8_s(void) { void f_double_uint8_s_arg(struct double_uint8_s a) {} // ILP32-ILP32F-LABEL: define dso_local void @f_ret_double_uint8_s -// ILP32-ILP32F-SAME: (ptr noalias sret([[STRUCT_DOUBLE_UINT8_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_DOUBLE_UINT8_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] { // ILP32-ILP32F: entry: // // ILP32D-LABEL: define dso_local { double, i8 } @f_ret_double_uint8_s @@ -587,7 +587,7 @@ struct double_uint8_s f_ret_double_uint8_s(void) { void f_double_int32_s_arg(struct double_int32_s a) {} // ILP32-ILP32F-LABEL: define dso_local void @f_ret_double_int32_s -// ILP32-ILP32F-SAME: (ptr noalias sret([[STRUCT_DOUBLE_INT32_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_DOUBLE_INT32_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] { // ILP32-ILP32F: entry: // // ILP32D-LABEL: define dso_local { double, i32 } @f_ret_double_int32_s @@ -605,7 +605,7 @@ struct double_int32_s f_ret_double_int32_s(void) { void f_double_int64_s_arg(struct double_int64_s a) {} // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_ret_double_int64_s -// ILP32-ILP32F-ILP32D-SAME: (ptr noalias sret([[STRUCT_DOUBLE_INT64_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-ILP32D-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_DOUBLE_INT64_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] { // ILP32-ILP32F-ILP32D: entry: // struct double_int64_s f_ret_double_int64_s(void) { @@ -623,7 +623,7 @@ struct double_int64_s f_ret_double_int64_s(void) { void f_double_int64bf_s_arg(struct double_int64bf_s a) {} // ILP32-ILP32F-LABEL: define dso_local void @f_ret_double_int64bf_s -// ILP32-ILP32F-SAME: (ptr noalias sret([[STRUCT_DOUBLE_INT64BF_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_DOUBLE_INT64BF_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] { // ILP32-ILP32F: entry: // // ILP32D-LABEL: define dso_local { double, i32 } @f_ret_double_int64bf_s @@ -648,7 +648,7 @@ struct double_int64bf_s f_ret_double_int64bf_s(void) { void f_double_int8_zbf_s(struct double_int8_zbf_s a) {} // ILP32-ILP32F-LABEL: define dso_local void @f_ret_double_int8_zbf_s -// ILP32-ILP32F-SAME: (ptr noalias sret([[STRUCT_DOUBLE_INT8_ZBF_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_DOUBLE_INT8_ZBF_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] { // ILP32-ILP32F: entry: // // ILP32D-LABEL: define dso_local { double, i8 } @f_ret_double_int8_zbf_s @@ -687,7 +687,7 @@ void f_struct_double_int8_insufficient_fprs(float a, double b, double c, double void f_doublecomplex(double __complex__ a) {} // ILP32-ILP32F-LABEL: define dso_local void @f_ret_doublecomplex -// ILP32-ILP32F-SAME: (ptr noalias sret({ double, double }) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-SAME: (ptr dead_on_unwind noalias writable sret({ double, double }) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] { // ILP32-ILP32F: entry: // // ILP32D-LABEL: define dso_local { double, double } @f_ret_doublecomplex @@ -711,7 +711,7 @@ struct doublecomplex_s { double __complex__ c; }; void f_doublecomplex_s_arg(struct doublecomplex_s a) {} // ILP32-ILP32F-LABEL: define dso_local void @f_ret_doublecomplex_s -// ILP32-ILP32F-SAME: (ptr noalias sret([[STRUCT_DOUBLECOMPLEX_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_DOUBLECOMPLEX_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] { // ILP32-ILP32F: entry: // // ILP32D-LABEL: define dso_local { double, double } @f_ret_doublecomplex_s @@ -762,7 +762,7 @@ struct doublearr2_s { double a[2]; }; void f_doublearr2_s_arg(struct doublearr2_s a) {} // ILP32-ILP32F-LABEL: define dso_local void @f_ret_doublearr2_s -// ILP32-ILP32F-SAME: (ptr noalias sret([[STRUCT_DOUBLEARR2_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_DOUBLEARR2_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] { // ILP32-ILP32F: entry: // // ILP32D-LABEL: define dso_local { double, double } @f_ret_doublearr2_s @@ -786,7 +786,7 @@ struct doublearr2_tricky1_s { struct { double f[1]; } g[2]; }; void f_doublearr2_tricky1_s_arg(struct doublearr2_tricky1_s a) {} // ILP32-ILP32F-LABEL: define dso_local void @f_ret_doublearr2_tricky1_s -// ILP32-ILP32F-SAME: (ptr noalias sret([[STRUCT_DOUBLEARR2_TRICKY1_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_DOUBLEARR2_TRICKY1_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] { // ILP32-ILP32F: entry: // // ILP32D-LABEL: define dso_local { double, double } @f_ret_doublearr2_tricky1_s @@ -810,7 +810,7 @@ struct doublearr2_tricky2_s { struct {}; struct { double f[1]; } g[2]; }; void f_doublearr2_tricky2_s_arg(struct doublearr2_tricky2_s a) {} // ILP32-ILP32F-LABEL: define dso_local void @f_ret_doublearr2_tricky2_s -// ILP32-ILP32F-SAME: (ptr noalias sret([[STRUCT_DOUBLEARR2_TRICKY2_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_DOUBLEARR2_TRICKY2_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] { // ILP32-ILP32F: entry: // // ILP32D-LABEL: define dso_local { double, double } @f_ret_doublearr2_tricky2_s @@ -834,7 +834,7 @@ struct doublearr2_tricky3_s { union {}; struct { double f[1]; } g[2]; }; void f_doublearr2_tricky3_s_arg(struct doublearr2_tricky3_s a) {} // ILP32-ILP32F-LABEL: define dso_local void @f_ret_doublearr2_tricky3_s -// ILP32-ILP32F-SAME: (ptr noalias sret([[STRUCT_DOUBLEARR2_TRICKY3_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_DOUBLEARR2_TRICKY3_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] { // ILP32-ILP32F: entry: // // ILP32D-LABEL: define dso_local { double, double } @f_ret_doublearr2_tricky3_s @@ -858,7 +858,7 @@ struct doublearr2_tricky4_s { union {}; struct { struct {}; double f[1]; } g[2]; void f_doublearr2_tricky4_s_arg(struct doublearr2_tricky4_s a) {} // ILP32-ILP32F-LABEL: define dso_local void @f_ret_doublearr2_tricky4_s -// ILP32-ILP32F-SAME: (ptr noalias sret([[STRUCT_DOUBLEARR2_TRICKY4_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_DOUBLEARR2_TRICKY4_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] { // ILP32-ILP32F: entry: // // ILP32D-LABEL: define dso_local { double, double } @f_ret_doublearr2_tricky4_s @@ -881,7 +881,7 @@ struct int_double_int_s { int a; double b; int c; }; void f_int_double_int_s_arg(struct int_double_int_s a) {} // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_ret_int_double_int_s -// ILP32-ILP32F-ILP32D-SAME: (ptr noalias sret([[STRUCT_INT_DOUBLE_INT_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-ILP32D-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_INT_DOUBLE_INT_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] { // ILP32-ILP32F-ILP32D: entry: // struct int_double_int_s f_ret_int_double_int_s(void) { @@ -897,7 +897,7 @@ struct int64_double_s { int64_t a; double b; }; void f_int64_double_s_arg(struct int64_double_s a) {} // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_ret_int64_double_s -// ILP32-ILP32F-ILP32D-SAME: (ptr noalias sret([[STRUCT_INT64_DOUBLE_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-ILP32D-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_INT64_DOUBLE_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] { // ILP32-ILP32F-ILP32D: entry: // struct int64_double_s f_ret_int64_double_s(void) { @@ -913,7 +913,7 @@ struct char_char_double_s { char a; char b; double c; }; void f_char_char_double_s_arg(struct char_char_double_s a) {} // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_ret_char_char_double_s -// ILP32-ILP32F-ILP32D-SAME: (ptr noalias sret([[STRUCT_CHAR_CHAR_DOUBLE_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-ILP32D-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_CHAR_CHAR_DOUBLE_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] { // ILP32-ILP32F-ILP32D: entry: // struct char_char_double_s f_ret_char_char_double_s(void) { @@ -946,7 +946,7 @@ union double_u f_ret_double_u(void) { // double+double structs by the ABI. // ILP32-ILP32F-LABEL: define dso_local void @f_ret_double_int32_s_double_int32_s_just_sufficient_gprs -// ILP32-ILP32F-SAME: (ptr noalias sret([[STRUCT_DOUBLE_INT32_S:%.*]]) align 8 [[AGG_RESULT:%.*]], i32 noundef [[A:%.*]], i32 noundef [[B:%.*]], i32 noundef [[C:%.*]], i32 noundef [[D:%.*]], i32 noundef [[E:%.*]], i32 noundef [[F:%.*]], i32 noundef [[G:%.*]], ptr noundef [[H:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_DOUBLE_INT32_S:%.*]]) align 8 [[AGG_RESULT:%.*]], i32 noundef [[A:%.*]], i32 noundef [[B:%.*]], i32 noundef [[C:%.*]], i32 noundef [[D:%.*]], i32 noundef [[E:%.*]], i32 noundef [[F:%.*]], i32 noundef [[G:%.*]], ptr noundef [[H:%.*]]) #[[ATTR0]] { // ILP32-ILP32F: entry: // // ILP32D-LABEL: define dso_local { double, i32 } @f_ret_double_int32_s_double_int32_s_just_sufficient_gprs @@ -959,7 +959,7 @@ struct double_int32_s f_ret_double_int32_s_double_int32_s_just_sufficient_gprs( } // ILP32-ILP32F-LABEL: define dso_local void @f_ret_double_double_s_double_int32_s_just_sufficient_gprs -// ILP32-ILP32F-SAME: (ptr noalias sret([[STRUCT_DOUBLE_DOUBLE_S:%.*]]) align 8 [[AGG_RESULT:%.*]], i32 noundef [[A:%.*]], i32 noundef [[B:%.*]], i32 noundef [[C:%.*]], i32 noundef [[D:%.*]], i32 noundef [[E:%.*]], i32 noundef [[F:%.*]], i32 noundef [[G:%.*]], ptr noundef [[H:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_DOUBLE_DOUBLE_S:%.*]]) align 8 [[AGG_RESULT:%.*]], i32 noundef [[A:%.*]], i32 noundef [[B:%.*]], i32 noundef [[C:%.*]], i32 noundef [[D:%.*]], i32 noundef [[E:%.*]], i32 noundef [[F:%.*]], i32 noundef [[G:%.*]], ptr noundef [[H:%.*]]) #[[ATTR0]] { // ILP32-ILP32F: entry: // // ILP32D-LABEL: define dso_local { double, double } @f_ret_double_double_s_double_int32_s_just_sufficient_gprs @@ -972,7 +972,7 @@ struct double_double_s f_ret_double_double_s_double_int32_s_just_sufficient_gprs } // ILP32-ILP32F-LABEL: define dso_local void @f_ret_doublecomplex_double_int32_s_just_sufficient_gprs -// ILP32-ILP32F-SAME: (ptr noalias sret({ double, double }) align 8 [[AGG_RESULT:%.*]], i32 noundef [[A:%.*]], i32 noundef [[B:%.*]], i32 noundef [[C:%.*]], i32 noundef [[D:%.*]], i32 noundef [[E:%.*]], i32 noundef [[F:%.*]], i32 noundef [[G:%.*]], ptr noundef [[H:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-SAME: (ptr dead_on_unwind noalias writable sret({ double, double }) align 8 [[AGG_RESULT:%.*]], i32 noundef [[A:%.*]], i32 noundef [[B:%.*]], i32 noundef [[C:%.*]], i32 noundef [[D:%.*]], i32 noundef [[E:%.*]], i32 noundef [[F:%.*]], i32 noundef [[G:%.*]], ptr noundef [[H:%.*]]) #[[ATTR0]] { // ILP32-ILP32F: entry: // // ILP32D-LABEL: define dso_local { double, double } @f_ret_doublecomplex_double_int32_s_just_sufficient_gprs @@ -1193,7 +1193,7 @@ struct float_int32_s f_ret_float_int32_s(void) { void f_float_int64_s_arg(struct float_int64_s a) {} // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_ret_float_int64_s -// ILP32-ILP32F-ILP32D-SAME: (ptr noalias sret([[STRUCT_FLOAT_INT64_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-ILP32D-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_FLOAT_INT64_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] { // ILP32-ILP32F-ILP32D: entry: // struct float_int64_s f_ret_float_int64_s(void) { @@ -1469,7 +1469,7 @@ struct int_float_int_s { int a; float b; int c; }; void f_int_float_int_s_arg(struct int_float_int_s a) {} // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_ret_int_float_int_s -// ILP32-ILP32F-ILP32D-SAME: (ptr noalias sret([[STRUCT_INT_FLOAT_INT_S:%.*]]) align 4 [[AGG_RESULT:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-ILP32D-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_INT_FLOAT_INT_S:%.*]]) align 4 [[AGG_RESULT:%.*]]) #[[ATTR0]] { // ILP32-ILP32F-ILP32D: entry: // struct int_float_int_s f_ret_int_float_int_s(void) { @@ -1485,7 +1485,7 @@ struct int64_float_s { int64_t a; float b; }; void f_int64_float_s_arg(struct int64_float_s a) {} // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_ret_int64_float_s -// ILP32-ILP32F-ILP32D-SAME: (ptr noalias sret([[STRUCT_INT64_FLOAT_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-ILP32D-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_INT64_FLOAT_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] { // ILP32-ILP32F-ILP32D: entry: // struct int64_float_s f_ret_int64_float_s(void) { @@ -1627,7 +1627,7 @@ struct double_float16_s { double f; _Float16 g; }; void f_double_float16_s_arg(struct double_float16_s a) {} // ILP32-ILP32F-LABEL: define dso_local void @f_ret_double_float16_s -// ILP32-ILP32F-SAME: (ptr noalias sret([[STRUCT_DOUBLE_FLOAT16_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_DOUBLE_FLOAT16_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] { // ILP32-ILP32F: entry: // // ILP32D-LABEL: define dso_local { double, half } @f_ret_double_float16_s @@ -1729,7 +1729,7 @@ struct float16_int32_s f_ret_float16_int32_s(void) { void f_float16_int64_s_arg(struct float16_int64_s a) {} // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_ret_float16_int64_s -// ILP32-ILP32F-ILP32D-SAME: (ptr noalias sret([[STRUCT_FLOAT16_INT64_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-ILP32D-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_FLOAT16_INT64_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] { // ILP32-ILP32F-ILP32D: entry: // struct float16_int64_s f_ret_float16_int64_s(void) { @@ -2005,7 +2005,7 @@ struct int_float16_int_s { int a; _Float16 b; int c; }; void f_int_float16_int_s_arg(struct int_float16_int_s a) {} // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_ret_int_float16_int_s -// ILP32-ILP32F-ILP32D-SAME: (ptr noalias sret([[STRUCT_INT_FLOAT16_INT_S:%.*]]) align 4 [[AGG_RESULT:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-ILP32D-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_INT_FLOAT16_INT_S:%.*]]) align 4 [[AGG_RESULT:%.*]]) #[[ATTR0]] { // ILP32-ILP32F-ILP32D: entry: // struct int_float16_int_s f_ret_int_float16_int_s(void) { @@ -2021,7 +2021,7 @@ struct int64_float16_s { int64_t a; _Float16 b; }; void f_int64_float16_s_arg(struct int64_float16_s a) {} // ILP32-ILP32F-ILP32D-LABEL: define dso_local void @f_ret_int64_float16_s -// ILP32-ILP32F-ILP32D-SAME: (ptr noalias sret([[STRUCT_INT64_FLOAT16_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] { +// ILP32-ILP32F-ILP32D-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_INT64_FLOAT16_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] { // ILP32-ILP32F-ILP32D: entry: // struct int64_float16_s f_ret_int64_float16_s(void) { diff --git a/clang/test/CodeGen/RISCV/riscv64-abi.c b/clang/test/CodeGen/RISCV/riscv64-abi.c index 8c857f86ddfff94ff898f47c5bfad59d02be02e3..3e7654851da0efa2183d06077aee145f394e7d54 100644 --- a/clang/test/CodeGen/RISCV/riscv64-abi.c +++ b/clang/test/CodeGen/RISCV/riscv64-abi.c @@ -250,7 +250,7 @@ void f_agg_large(struct large x) { // The address where the struct should be written to will be the first // argument // LP64-LP64F-LP64D-LABEL: define dso_local void @f_agg_large_ret -// LP64-LP64F-LP64D-SAME: (ptr noalias sret([[STRUCT_LARGE:%.*]]) align 8 [[AGG_RESULT:%.*]], i32 noundef signext [[I:%.*]], i8 noundef signext [[J:%.*]]) #[[ATTR0]] { +// LP64-LP64F-LP64D-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_LARGE:%.*]]) align 8 [[AGG_RESULT:%.*]], i32 noundef signext [[I:%.*]], i8 noundef signext [[J:%.*]]) #[[ATTR0]] { // LP64-LP64F-LP64D: entry: // struct large f_agg_large_ret(int32_t i, int8_t j) { @@ -268,7 +268,7 @@ void f_vec_large_v32i8(v32i8 x) { } // LP64-LP64F-LP64D-LABEL: define dso_local void @f_vec_large_v32i8_ret -// LP64-LP64F-LP64D-SAME: (ptr noalias sret(<32 x i8>) align 32 [[AGG_RESULT:%.*]]) #[[ATTR0]] { +// LP64-LP64F-LP64D-SAME: (ptr dead_on_unwind noalias writable sret(<32 x i8>) align 32 [[AGG_RESULT:%.*]]) #[[ATTR0]] { // LP64-LP64F-LP64D: entry: // v32i8 f_vec_large_v32i8_ret(void) { @@ -310,7 +310,7 @@ int f_scalar_stack_3(int32_t a, __int128_t b, double c, long double d, v32i8 e, // to pass a pointer. // LP64-LP64F-LP64D-LABEL: define dso_local void @f_scalar_stack_4 -// LP64-LP64F-LP64D-SAME: (ptr noalias sret([[STRUCT_LARGE:%.*]]) align 8 [[AGG_RESULT:%.*]], i32 noundef signext [[A:%.*]], i128 noundef [[B:%.*]], fp128 noundef [[C:%.*]], ptr noundef [[TMP0:%.*]], i8 noundef zeroext [[E:%.*]], i8 noundef signext [[F:%.*]], i8 noundef zeroext [[G:%.*]]) #[[ATTR0]] { +// LP64-LP64F-LP64D-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_LARGE:%.*]]) align 8 [[AGG_RESULT:%.*]], i32 noundef signext [[A:%.*]], i128 noundef [[B:%.*]], fp128 noundef [[C:%.*]], ptr noundef [[TMP0:%.*]], i8 noundef zeroext [[E:%.*]], i8 noundef signext [[F:%.*]], i8 noundef zeroext [[G:%.*]]) #[[ATTR0]] { // LP64-LP64F-LP64D: entry: // struct large f_scalar_stack_4(uint32_t a, __int128_t b, long double c, v32i8 d, @@ -319,7 +319,7 @@ struct large f_scalar_stack_4(uint32_t a, __int128_t b, long double c, v32i8 d, } // LP64-LP64F-LP64D-LABEL: define dso_local void @f_scalar_stack_5 -// LP64-LP64F-LP64D-SAME: (ptr noalias sret([[STRUCT_LARGE:%.*]]) align 8 [[AGG_RESULT:%.*]], double noundef [[A:%.*]], i128 noundef [[B:%.*]], fp128 noundef [[C:%.*]], ptr noundef [[TMP0:%.*]], i8 noundef zeroext [[E:%.*]], i8 noundef signext [[F:%.*]], i8 noundef zeroext [[G:%.*]]) #[[ATTR0]] { +// LP64-LP64F-LP64D-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_LARGE:%.*]]) align 8 [[AGG_RESULT:%.*]], double noundef [[A:%.*]], i128 noundef [[B:%.*]], fp128 noundef [[C:%.*]], ptr noundef [[TMP0:%.*]], i8 noundef zeroext [[E:%.*]], i8 noundef signext [[F:%.*]], i8 noundef zeroext [[G:%.*]]) #[[ATTR0]] { // LP64-LP64F-LP64D: entry: // struct large f_scalar_stack_5(double a, __int128_t b, long double c, v32i8 d, @@ -1444,7 +1444,7 @@ struct int_double_int_s { int a; double b; int c; }; void f_int_double_int_s_arg(struct int_double_int_s a) {} // LP64-LP64F-LP64D-LABEL: define dso_local void @f_ret_int_double_int_s -// LP64-LP64F-LP64D-SAME: (ptr noalias sret([[STRUCT_INT_DOUBLE_INT_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] { +// LP64-LP64F-LP64D-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_INT_DOUBLE_INT_S:%.*]]) align 8 [[AGG_RESULT:%.*]]) #[[ATTR0]] { // LP64-LP64F-LP64D: entry: // struct int_double_int_s f_ret_int_double_int_s(void) { diff --git a/clang/test/CodeGen/SystemZ/gnu-atomic-builtins-i128-8Al.c b/clang/test/CodeGen/SystemZ/gnu-atomic-builtins-i128-8Al.c index e38e6572bd58f4e460d2fa92940c390464c51b13..4f6dcbc2c01ec847b76329f911027a7c73cb27e6 100644 --- a/clang/test/CodeGen/SystemZ/gnu-atomic-builtins-i128-8Al.c +++ b/clang/test/CodeGen/SystemZ/gnu-atomic-builtins-i128-8Al.c @@ -20,10 +20,7 @@ __int128 Des; // CHECK-LABEL: @f1( // CHECK-NEXT: entry: -// CHECK-NEXT: [[ATOMIC_TEMP:%.*]] = alloca i128, align 8 -// CHECK-NEXT: call void @__atomic_load(i64 noundef 16, ptr noundef nonnull @Ptr, ptr noundef nonnull [[ATOMIC_TEMP]], i32 noundef signext 5) -// CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr [[ATOMIC_TEMP]], align 8, !tbaa [[TBAA2:![0-9]+]] -// CHECK-NEXT: store i128 [[TMP0]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: tail call void @__atomic_load(i64 noundef 16, ptr noundef nonnull @Ptr, ptr noundef nonnull [[AGG_RESULT:%.*]], i32 noundef signext 5) // CHECK-NEXT: ret void // __int128 f1() { @@ -33,7 +30,7 @@ __int128 f1() { // CHECK-LABEL: @f2( // CHECK-NEXT: entry: // CHECK-NEXT: tail call void @__atomic_load(i64 noundef 16, ptr noundef nonnull @Ptr, ptr noundef nonnull @Ret, i32 noundef signext 5) -// CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Ret, align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Ret, align 8, !tbaa [[TBAA2:![0-9]+]] // CHECK-NEXT: store i128 [[TMP0]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] // CHECK-NEXT: ret void // @@ -66,12 +63,9 @@ void f4() { // CHECK-LABEL: @f5( // CHECK-NEXT: entry: // CHECK-NEXT: [[DOTATOMICTMP:%.*]] = alloca i128, align 8 -// CHECK-NEXT: [[ATOMIC_TEMP:%.*]] = alloca i128, align 8 // CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 8, !tbaa [[TBAA2]] // CHECK-NEXT: store i128 [[TMP0]], ptr [[DOTATOMICTMP]], align 8, !tbaa [[TBAA2]] -// CHECK-NEXT: call void @__atomic_exchange(i64 noundef 16, ptr noundef nonnull @Ptr, ptr noundef nonnull [[DOTATOMICTMP]], ptr noundef nonnull [[ATOMIC_TEMP]], i32 noundef signext 5) -// CHECK-NEXT: [[TMP1:%.*]] = load i128, ptr [[ATOMIC_TEMP]], align 8, !tbaa [[TBAA2]] -// CHECK-NEXT: store i128 [[TMP1]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: call void @__atomic_exchange(i64 noundef 16, ptr noundef nonnull @Ptr, ptr noundef nonnull [[DOTATOMICTMP]], ptr noundef nonnull [[AGG_RESULT:%.*]], i32 noundef signext 5) // CHECK-NEXT: ret void // __int128 f5() { @@ -119,7 +113,7 @@ _Bool f8() { // CHECK-NEXT: [[INDIRECT_ARG_TEMP:%.*]] = alloca i128, align 8 // CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 8, !tbaa [[TBAA2]] // CHECK-NEXT: store i128 [[TMP0]], ptr [[INDIRECT_ARG_TEMP]], align 8, !tbaa [[TBAA2]] -// CHECK-NEXT: call void @__atomic_fetch_add_16(ptr nonnull sret(i128) align 8 [[TMP]], ptr noundef nonnull @Ptr, ptr noundef nonnull [[INDIRECT_ARG_TEMP]], i32 noundef signext 5) +// CHECK-NEXT: call void @__atomic_fetch_add_16(ptr dead_on_unwind nonnull writable sret(i128) align 8 [[TMP]], ptr noundef nonnull @Ptr, ptr noundef nonnull [[INDIRECT_ARG_TEMP]], i32 noundef signext 5) // CHECK-NEXT: [[TMP1:%.*]] = load i128, ptr [[TMP]], align 8, !tbaa [[TBAA2]] // CHECK-NEXT: [[TMP2:%.*]] = add i128 [[TMP1]], [[TMP0]] // CHECK-NEXT: store i128 [[TMP2]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] @@ -135,7 +129,7 @@ __int128 f9() { // CHECK-NEXT: [[INDIRECT_ARG_TEMP:%.*]] = alloca i128, align 8 // CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 8, !tbaa [[TBAA2]] // CHECK-NEXT: store i128 [[TMP0]], ptr [[INDIRECT_ARG_TEMP]], align 8, !tbaa [[TBAA2]] -// CHECK-NEXT: call void @__atomic_fetch_sub_16(ptr nonnull sret(i128) align 8 [[TMP]], ptr noundef nonnull @Ptr, ptr noundef nonnull [[INDIRECT_ARG_TEMP]], i32 noundef signext 5) +// CHECK-NEXT: call void @__atomic_fetch_sub_16(ptr dead_on_unwind nonnull writable sret(i128) align 8 [[TMP]], ptr noundef nonnull @Ptr, ptr noundef nonnull [[INDIRECT_ARG_TEMP]], i32 noundef signext 5) // CHECK-NEXT: [[TMP1:%.*]] = load i128, ptr [[TMP]], align 8, !tbaa [[TBAA2]] // CHECK-NEXT: [[TMP2:%.*]] = sub i128 [[TMP1]], [[TMP0]] // CHECK-NEXT: store i128 [[TMP2]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] @@ -151,7 +145,7 @@ __int128 f10() { // CHECK-NEXT: [[INDIRECT_ARG_TEMP:%.*]] = alloca i128, align 8 // CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 8, !tbaa [[TBAA2]] // CHECK-NEXT: store i128 [[TMP0]], ptr [[INDIRECT_ARG_TEMP]], align 8, !tbaa [[TBAA2]] -// CHECK-NEXT: call void @__atomic_fetch_and_16(ptr nonnull sret(i128) align 8 [[TMP]], ptr noundef nonnull @Ptr, ptr noundef nonnull [[INDIRECT_ARG_TEMP]], i32 noundef signext 5) +// CHECK-NEXT: call void @__atomic_fetch_and_16(ptr dead_on_unwind nonnull writable sret(i128) align 8 [[TMP]], ptr noundef nonnull @Ptr, ptr noundef nonnull [[INDIRECT_ARG_TEMP]], i32 noundef signext 5) // CHECK-NEXT: [[TMP1:%.*]] = load i128, ptr [[TMP]], align 8, !tbaa [[TBAA2]] // CHECK-NEXT: [[TMP2:%.*]] = and i128 [[TMP1]], [[TMP0]] // CHECK-NEXT: store i128 [[TMP2]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] @@ -167,7 +161,7 @@ __int128 f11() { // CHECK-NEXT: [[INDIRECT_ARG_TEMP:%.*]] = alloca i128, align 8 // CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 8, !tbaa [[TBAA2]] // CHECK-NEXT: store i128 [[TMP0]], ptr [[INDIRECT_ARG_TEMP]], align 8, !tbaa [[TBAA2]] -// CHECK-NEXT: call void @__atomic_fetch_xor_16(ptr nonnull sret(i128) align 8 [[TMP]], ptr noundef nonnull @Ptr, ptr noundef nonnull [[INDIRECT_ARG_TEMP]], i32 noundef signext 5) +// CHECK-NEXT: call void @__atomic_fetch_xor_16(ptr dead_on_unwind nonnull writable sret(i128) align 8 [[TMP]], ptr noundef nonnull @Ptr, ptr noundef nonnull [[INDIRECT_ARG_TEMP]], i32 noundef signext 5) // CHECK-NEXT: [[TMP1:%.*]] = load i128, ptr [[TMP]], align 8, !tbaa [[TBAA2]] // CHECK-NEXT: [[TMP2:%.*]] = xor i128 [[TMP1]], [[TMP0]] // CHECK-NEXT: store i128 [[TMP2]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] @@ -183,7 +177,7 @@ __int128 f12() { // CHECK-NEXT: [[INDIRECT_ARG_TEMP:%.*]] = alloca i128, align 8 // CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 8, !tbaa [[TBAA2]] // CHECK-NEXT: store i128 [[TMP0]], ptr [[INDIRECT_ARG_TEMP]], align 8, !tbaa [[TBAA2]] -// CHECK-NEXT: call void @__atomic_fetch_or_16(ptr nonnull sret(i128) align 8 [[TMP]], ptr noundef nonnull @Ptr, ptr noundef nonnull [[INDIRECT_ARG_TEMP]], i32 noundef signext 5) +// CHECK-NEXT: call void @__atomic_fetch_or_16(ptr dead_on_unwind nonnull writable sret(i128) align 8 [[TMP]], ptr noundef nonnull @Ptr, ptr noundef nonnull [[INDIRECT_ARG_TEMP]], i32 noundef signext 5) // CHECK-NEXT: [[TMP1:%.*]] = load i128, ptr [[TMP]], align 8, !tbaa [[TBAA2]] // CHECK-NEXT: [[TMP2:%.*]] = or i128 [[TMP1]], [[TMP0]] // CHECK-NEXT: store i128 [[TMP2]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] @@ -199,7 +193,7 @@ __int128 f13() { // CHECK-NEXT: [[INDIRECT_ARG_TEMP:%.*]] = alloca i128, align 8 // CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 8, !tbaa [[TBAA2]] // CHECK-NEXT: store i128 [[TMP0]], ptr [[INDIRECT_ARG_TEMP]], align 8, !tbaa [[TBAA2]] -// CHECK-NEXT: call void @__atomic_fetch_nand_16(ptr nonnull sret(i128) align 8 [[TMP]], ptr noundef nonnull @Ptr, ptr noundef nonnull [[INDIRECT_ARG_TEMP]], i32 noundef signext 5) +// CHECK-NEXT: call void @__atomic_fetch_nand_16(ptr dead_on_unwind nonnull writable sret(i128) align 8 [[TMP]], ptr noundef nonnull @Ptr, ptr noundef nonnull [[INDIRECT_ARG_TEMP]], i32 noundef signext 5) // CHECK-NEXT: [[TMP1:%.*]] = load i128, ptr [[TMP]], align 8, !tbaa [[TBAA2]] // CHECK-NEXT: [[TMP2:%.*]] = and i128 [[TMP1]], [[TMP0]] // CHECK-NEXT: [[TMP3:%.*]] = xor i128 [[TMP2]], -1 @@ -212,13 +206,10 @@ __int128 f14() { // CHECK-LABEL: @f15( // CHECK-NEXT: entry: -// CHECK-NEXT: [[TMP:%.*]] = alloca i128, align 8 // CHECK-NEXT: [[INDIRECT_ARG_TEMP:%.*]] = alloca i128, align 8 // CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 8, !tbaa [[TBAA2]] // CHECK-NEXT: store i128 [[TMP0]], ptr [[INDIRECT_ARG_TEMP]], align 8, !tbaa [[TBAA2]] -// CHECK-NEXT: call void @__atomic_fetch_add_16(ptr nonnull sret(i128) align 8 [[TMP]], ptr noundef nonnull @Ptr, ptr noundef nonnull [[INDIRECT_ARG_TEMP]], i32 noundef signext 5) -// CHECK-NEXT: [[TMP1:%.*]] = load i128, ptr [[TMP]], align 8, !tbaa [[TBAA2]] -// CHECK-NEXT: store i128 [[TMP1]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: call void @__atomic_fetch_add_16(ptr dead_on_unwind nonnull writable sret(i128) align 8 [[AGG_RESULT:%.*]], ptr noundef nonnull @Ptr, ptr noundef nonnull [[INDIRECT_ARG_TEMP]], i32 noundef signext 5) // CHECK-NEXT: ret void // __int128 f15() { @@ -227,13 +218,10 @@ __int128 f15() { // CHECK-LABEL: @f16( // CHECK-NEXT: entry: -// CHECK-NEXT: [[TMP:%.*]] = alloca i128, align 8 // CHECK-NEXT: [[INDIRECT_ARG_TEMP:%.*]] = alloca i128, align 8 // CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 8, !tbaa [[TBAA2]] // CHECK-NEXT: store i128 [[TMP0]], ptr [[INDIRECT_ARG_TEMP]], align 8, !tbaa [[TBAA2]] -// CHECK-NEXT: call void @__atomic_fetch_sub_16(ptr nonnull sret(i128) align 8 [[TMP]], ptr noundef nonnull @Ptr, ptr noundef nonnull [[INDIRECT_ARG_TEMP]], i32 noundef signext 5) -// CHECK-NEXT: [[TMP1:%.*]] = load i128, ptr [[TMP]], align 8, !tbaa [[TBAA2]] -// CHECK-NEXT: store i128 [[TMP1]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: call void @__atomic_fetch_sub_16(ptr dead_on_unwind nonnull writable sret(i128) align 8 [[AGG_RESULT:%.*]], ptr noundef nonnull @Ptr, ptr noundef nonnull [[INDIRECT_ARG_TEMP]], i32 noundef signext 5) // CHECK-NEXT: ret void // __int128 f16() { @@ -242,13 +230,10 @@ __int128 f16() { // CHECK-LABEL: @f17( // CHECK-NEXT: entry: -// CHECK-NEXT: [[TMP:%.*]] = alloca i128, align 8 // CHECK-NEXT: [[INDIRECT_ARG_TEMP:%.*]] = alloca i128, align 8 // CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 8, !tbaa [[TBAA2]] // CHECK-NEXT: store i128 [[TMP0]], ptr [[INDIRECT_ARG_TEMP]], align 8, !tbaa [[TBAA2]] -// CHECK-NEXT: call void @__atomic_fetch_and_16(ptr nonnull sret(i128) align 8 [[TMP]], ptr noundef nonnull @Ptr, ptr noundef nonnull [[INDIRECT_ARG_TEMP]], i32 noundef signext 5) -// CHECK-NEXT: [[TMP1:%.*]] = load i128, ptr [[TMP]], align 8, !tbaa [[TBAA2]] -// CHECK-NEXT: store i128 [[TMP1]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: call void @__atomic_fetch_and_16(ptr dead_on_unwind nonnull writable sret(i128) align 8 [[AGG_RESULT:%.*]], ptr noundef nonnull @Ptr, ptr noundef nonnull [[INDIRECT_ARG_TEMP]], i32 noundef signext 5) // CHECK-NEXT: ret void // __int128 f17() { @@ -257,13 +242,10 @@ __int128 f17() { // CHECK-LABEL: @f18( // CHECK-NEXT: entry: -// CHECK-NEXT: [[TMP:%.*]] = alloca i128, align 8 // CHECK-NEXT: [[INDIRECT_ARG_TEMP:%.*]] = alloca i128, align 8 // CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 8, !tbaa [[TBAA2]] // CHECK-NEXT: store i128 [[TMP0]], ptr [[INDIRECT_ARG_TEMP]], align 8, !tbaa [[TBAA2]] -// CHECK-NEXT: call void @__atomic_fetch_xor_16(ptr nonnull sret(i128) align 8 [[TMP]], ptr noundef nonnull @Ptr, ptr noundef nonnull [[INDIRECT_ARG_TEMP]], i32 noundef signext 5) -// CHECK-NEXT: [[TMP1:%.*]] = load i128, ptr [[TMP]], align 8, !tbaa [[TBAA2]] -// CHECK-NEXT: store i128 [[TMP1]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: call void @__atomic_fetch_xor_16(ptr dead_on_unwind nonnull writable sret(i128) align 8 [[AGG_RESULT:%.*]], ptr noundef nonnull @Ptr, ptr noundef nonnull [[INDIRECT_ARG_TEMP]], i32 noundef signext 5) // CHECK-NEXT: ret void // __int128 f18() { @@ -272,13 +254,10 @@ __int128 f18() { // CHECK-LABEL: @f19( // CHECK-NEXT: entry: -// CHECK-NEXT: [[TMP:%.*]] = alloca i128, align 8 // CHECK-NEXT: [[INDIRECT_ARG_TEMP:%.*]] = alloca i128, align 8 // CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 8, !tbaa [[TBAA2]] // CHECK-NEXT: store i128 [[TMP0]], ptr [[INDIRECT_ARG_TEMP]], align 8, !tbaa [[TBAA2]] -// CHECK-NEXT: call void @__atomic_fetch_or_16(ptr nonnull sret(i128) align 8 [[TMP]], ptr noundef nonnull @Ptr, ptr noundef nonnull [[INDIRECT_ARG_TEMP]], i32 noundef signext 5) -// CHECK-NEXT: [[TMP1:%.*]] = load i128, ptr [[TMP]], align 8, !tbaa [[TBAA2]] -// CHECK-NEXT: store i128 [[TMP1]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: call void @__atomic_fetch_or_16(ptr dead_on_unwind nonnull writable sret(i128) align 8 [[AGG_RESULT:%.*]], ptr noundef nonnull @Ptr, ptr noundef nonnull [[INDIRECT_ARG_TEMP]], i32 noundef signext 5) // CHECK-NEXT: ret void // __int128 f19() { @@ -287,13 +266,10 @@ __int128 f19() { // CHECK-LABEL: @f20( // CHECK-NEXT: entry: -// CHECK-NEXT: [[TMP:%.*]] = alloca i128, align 8 // CHECK-NEXT: [[INDIRECT_ARG_TEMP:%.*]] = alloca i128, align 8 // CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 8, !tbaa [[TBAA2]] // CHECK-NEXT: store i128 [[TMP0]], ptr [[INDIRECT_ARG_TEMP]], align 8, !tbaa [[TBAA2]] -// CHECK-NEXT: call void @__atomic_fetch_nand_16(ptr nonnull sret(i128) align 8 [[TMP]], ptr noundef nonnull @Ptr, ptr noundef nonnull [[INDIRECT_ARG_TEMP]], i32 noundef signext 5) -// CHECK-NEXT: [[TMP1:%.*]] = load i128, ptr [[TMP]], align 8, !tbaa [[TBAA2]] -// CHECK-NEXT: store i128 [[TMP1]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] +// CHECK-NEXT: call void @__atomic_fetch_nand_16(ptr dead_on_unwind nonnull writable sret(i128) align 8 [[AGG_RESULT:%.*]], ptr noundef nonnull @Ptr, ptr noundef nonnull [[INDIRECT_ARG_TEMP]], i32 noundef signext 5) // CHECK-NEXT: ret void // __int128 f20() { diff --git a/clang/test/CodeGen/SystemZ/systemz-abi-vector.c b/clang/test/CodeGen/SystemZ/systemz-abi-vector.c index f7606641a3747e54296511c06766d9d16e0e00a6..6a06d15f22aa35c07474396b62aff158c28a5088 100644 --- a/clang/test/CodeGen/SystemZ/systemz-abi-vector.c +++ b/clang/test/CodeGen/SystemZ/systemz-abi-vector.c @@ -54,91 +54,91 @@ unsigned int align = __alignof__ (v16i8); // CHECK-VECTOR: @align ={{.*}} global i32 8 v1i8 pass_v1i8(v1i8 arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_v1i8(ptr noalias sret(<1 x i8>) align 1 %{{.*}}, ptr %0) +// CHECK-LABEL: define{{.*}} void @pass_v1i8(ptr dead_on_unwind noalias writable sret(<1 x i8>) align 1 %{{.*}}, ptr %0) // CHECK-VECTOR-LABEL: define{{.*}} <1 x i8> @pass_v1i8(<1 x i8> %{{.*}}) v2i8 pass_v2i8(v2i8 arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_v2i8(ptr noalias sret(<2 x i8>) align 2 %{{.*}}, ptr %0) +// CHECK-LABEL: define{{.*}} void @pass_v2i8(ptr dead_on_unwind noalias writable sret(<2 x i8>) align 2 %{{.*}}, ptr %0) // CHECK-VECTOR-LABEL: define{{.*}} <2 x i8> @pass_v2i8(<2 x i8> %{{.*}}) v4i8 pass_v4i8(v4i8 arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_v4i8(ptr noalias sret(<4 x i8>) align 4 %{{.*}}, ptr %0) +// CHECK-LABEL: define{{.*}} void @pass_v4i8(ptr dead_on_unwind noalias writable sret(<4 x i8>) align 4 %{{.*}}, ptr %0) // CHECK-VECTOR-LABEL: define{{.*}} <4 x i8> @pass_v4i8(<4 x i8> %{{.*}}) v8i8 pass_v8i8(v8i8 arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_v8i8(ptr noalias sret(<8 x i8>) align 8 %{{.*}}, ptr %0) +// CHECK-LABEL: define{{.*}} void @pass_v8i8(ptr dead_on_unwind noalias writable sret(<8 x i8>) align 8 %{{.*}}, ptr %0) // CHECK-VECTOR-LABEL: define{{.*}} <8 x i8> @pass_v8i8(<8 x i8> %{{.*}}) v16i8 pass_v16i8(v16i8 arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_v16i8(ptr noalias sret(<16 x i8>) align 16 %{{.*}}, ptr %0) +// CHECK-LABEL: define{{.*}} void @pass_v16i8(ptr dead_on_unwind noalias writable sret(<16 x i8>) align 16 %{{.*}}, ptr %0) // CHECK-VECTOR-LABEL: define{{.*}} <16 x i8> @pass_v16i8(<16 x i8> %{{.*}}) v32i8 pass_v32i8(v32i8 arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_v32i8(ptr noalias sret(<32 x i8>) align 32 %{{.*}}, ptr %0) -// CHECK-VECTOR-LABEL: define{{.*}} void @pass_v32i8(ptr noalias sret(<32 x i8>) align 8 %{{.*}}, ptr %0) +// CHECK-LABEL: define{{.*}} void @pass_v32i8(ptr dead_on_unwind noalias writable sret(<32 x i8>) align 32 %{{.*}}, ptr %0) +// CHECK-VECTOR-LABEL: define{{.*}} void @pass_v32i8(ptr dead_on_unwind noalias writable sret(<32 x i8>) align 8 %{{.*}}, ptr %0) v1i16 pass_v1i16(v1i16 arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_v1i16(ptr noalias sret(<1 x i16>) align 2 %{{.*}}, ptr %0) +// CHECK-LABEL: define{{.*}} void @pass_v1i16(ptr dead_on_unwind noalias writable sret(<1 x i16>) align 2 %{{.*}}, ptr %0) // CHECK-VECTOR-LABEL: define{{.*}} <1 x i16> @pass_v1i16(<1 x i16> %{{.*}}) v2i16 pass_v2i16(v2i16 arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_v2i16(ptr noalias sret(<2 x i16>) align 4 %{{.*}}, ptr %0) +// CHECK-LABEL: define{{.*}} void @pass_v2i16(ptr dead_on_unwind noalias writable sret(<2 x i16>) align 4 %{{.*}}, ptr %0) // CHECK-VECTOR-LABEL: define{{.*}} <2 x i16> @pass_v2i16(<2 x i16> %{{.*}}) v4i16 pass_v4i16(v4i16 arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_v4i16(ptr noalias sret(<4 x i16>) align 8 %{{.*}}, ptr %0) +// CHECK-LABEL: define{{.*}} void @pass_v4i16(ptr dead_on_unwind noalias writable sret(<4 x i16>) align 8 %{{.*}}, ptr %0) // CHECK-VECTOR-LABEL: define{{.*}} <4 x i16> @pass_v4i16(<4 x i16> %{{.*}}) v8i16 pass_v8i16(v8i16 arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_v8i16(ptr noalias sret(<8 x i16>) align 16 %{{.*}}, ptr %0) +// CHECK-LABEL: define{{.*}} void @pass_v8i16(ptr dead_on_unwind noalias writable sret(<8 x i16>) align 16 %{{.*}}, ptr %0) // CHECK-VECTOR-LABEL: define{{.*}} <8 x i16> @pass_v8i16(<8 x i16> %{{.*}}) v1i32 pass_v1i32(v1i32 arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_v1i32(ptr noalias sret(<1 x i32>) align 4 %{{.*}}, ptr %0) +// CHECK-LABEL: define{{.*}} void @pass_v1i32(ptr dead_on_unwind noalias writable sret(<1 x i32>) align 4 %{{.*}}, ptr %0) // CHECK-VECTOR-LABEL: define{{.*}} <1 x i32> @pass_v1i32(<1 x i32> %{{.*}}) v2i32 pass_v2i32(v2i32 arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_v2i32(ptr noalias sret(<2 x i32>) align 8 %{{.*}}, ptr %0) +// CHECK-LABEL: define{{.*}} void @pass_v2i32(ptr dead_on_unwind noalias writable sret(<2 x i32>) align 8 %{{.*}}, ptr %0) // CHECK-VECTOR-LABEL: define{{.*}} <2 x i32> @pass_v2i32(<2 x i32> %{{.*}}) v4i32 pass_v4i32(v4i32 arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_v4i32(ptr noalias sret(<4 x i32>) align 16 %{{.*}}, ptr %0) +// CHECK-LABEL: define{{.*}} void @pass_v4i32(ptr dead_on_unwind noalias writable sret(<4 x i32>) align 16 %{{.*}}, ptr %0) // CHECK-VECTOR-LABEL: define{{.*}} <4 x i32> @pass_v4i32(<4 x i32> %{{.*}}) v1i64 pass_v1i64(v1i64 arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_v1i64(ptr noalias sret(<1 x i64>) align 8 %{{.*}}, ptr %0) +// CHECK-LABEL: define{{.*}} void @pass_v1i64(ptr dead_on_unwind noalias writable sret(<1 x i64>) align 8 %{{.*}}, ptr %0) // CHECK-VECTOR-LABEL: define{{.*}} <1 x i64> @pass_v1i64(<1 x i64> %{{.*}}) v2i64 pass_v2i64(v2i64 arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_v2i64(ptr noalias sret(<2 x i64>) align 16 %{{.*}}, ptr %0) +// CHECK-LABEL: define{{.*}} void @pass_v2i64(ptr dead_on_unwind noalias writable sret(<2 x i64>) align 16 %{{.*}}, ptr %0) // CHECK-VECTOR-LABEL: define{{.*}} <2 x i64> @pass_v2i64(<2 x i64> %{{.*}}) v1i128 pass_v1i128(v1i128 arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_v1i128(ptr noalias sret(<1 x i128>) align 16 %{{.*}}, ptr %0) +// CHECK-LABEL: define{{.*}} void @pass_v1i128(ptr dead_on_unwind noalias writable sret(<1 x i128>) align 16 %{{.*}}, ptr %0) // CHECK-VECTOR-LABEL: define{{.*}} <1 x i128> @pass_v1i128(<1 x i128> %{{.*}}) v1f32 pass_v1f32(v1f32 arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_v1f32(ptr noalias sret(<1 x float>) align 4 %{{.*}}, ptr %0) +// CHECK-LABEL: define{{.*}} void @pass_v1f32(ptr dead_on_unwind noalias writable sret(<1 x float>) align 4 %{{.*}}, ptr %0) // CHECK-VECTOR-LABEL: define{{.*}} <1 x float> @pass_v1f32(<1 x float> %{{.*}}) v2f32 pass_v2f32(v2f32 arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_v2f32(ptr noalias sret(<2 x float>) align 8 %{{.*}}, ptr %0) +// CHECK-LABEL: define{{.*}} void @pass_v2f32(ptr dead_on_unwind noalias writable sret(<2 x float>) align 8 %{{.*}}, ptr %0) // CHECK-VECTOR-LABEL: define{{.*}} <2 x float> @pass_v2f32(<2 x float> %{{.*}}) v4f32 pass_v4f32(v4f32 arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_v4f32(ptr noalias sret(<4 x float>) align 16 %{{.*}}, ptr %0) +// CHECK-LABEL: define{{.*}} void @pass_v4f32(ptr dead_on_unwind noalias writable sret(<4 x float>) align 16 %{{.*}}, ptr %0) // CHECK-VECTOR-LABEL: define{{.*}} <4 x float> @pass_v4f32(<4 x float> %{{.*}}) v1f64 pass_v1f64(v1f64 arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_v1f64(ptr noalias sret(<1 x double>) align 8 %{{.*}}, ptr %0) +// CHECK-LABEL: define{{.*}} void @pass_v1f64(ptr dead_on_unwind noalias writable sret(<1 x double>) align 8 %{{.*}}, ptr %0) // CHECK-VECTOR-LABEL: define{{.*}} <1 x double> @pass_v1f64(<1 x double> %{{.*}}) v2f64 pass_v2f64(v2f64 arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_v2f64(ptr noalias sret(<2 x double>) align 16 %{{.*}}, ptr %0) +// CHECK-LABEL: define{{.*}} void @pass_v2f64(ptr dead_on_unwind noalias writable sret(<2 x double>) align 16 %{{.*}}, ptr %0) // CHECK-VECTOR-LABEL: define{{.*}} <2 x double> @pass_v2f64(<2 x double> %{{.*}}) v1f128 pass_v1f128(v1f128 arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_v1f128(ptr noalias sret(<1 x fp128>) align 16 %{{.*}}, ptr %0) +// CHECK-LABEL: define{{.*}} void @pass_v1f128(ptr dead_on_unwind noalias writable sret(<1 x fp128>) align 16 %{{.*}}, ptr %0) // CHECK-VECTOR-LABEL: define{{.*}} <1 x fp128> @pass_v1f128(<1 x fp128> %{{.*}}) @@ -146,62 +146,62 @@ v1f128 pass_v1f128(v1f128 arg) { return arg; } struct agg_v1i8 { v1i8 a; }; struct agg_v1i8 pass_agg_v1i8(struct agg_v1i8 arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_agg_v1i8(ptr noalias sret(%struct.agg_v1i8) align 1 %{{.*}}, i8 %{{.*}}) -// CHECK-VECTOR-LABEL: define{{.*}} void @pass_agg_v1i8(ptr noalias sret(%struct.agg_v1i8) align 1 %{{.*}}, <1 x i8> %{{.*}}) +// CHECK-LABEL: define{{.*}} void @pass_agg_v1i8(ptr dead_on_unwind noalias writable sret(%struct.agg_v1i8) align 1 %{{.*}}, i8 %{{.*}}) +// CHECK-VECTOR-LABEL: define{{.*}} void @pass_agg_v1i8(ptr dead_on_unwind noalias writable sret(%struct.agg_v1i8) align 1 %{{.*}}, <1 x i8> %{{.*}}) struct agg_v2i8 { v2i8 a; }; struct agg_v2i8 pass_agg_v2i8(struct agg_v2i8 arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_agg_v2i8(ptr noalias sret(%struct.agg_v2i8) align 2 %{{.*}}, i16 %{{.*}}) -// CHECK-VECTOR-LABEL: define{{.*}} void @pass_agg_v2i8(ptr noalias sret(%struct.agg_v2i8) align 2 %{{.*}}, <2 x i8> %{{.*}}) +// CHECK-LABEL: define{{.*}} void @pass_agg_v2i8(ptr dead_on_unwind noalias writable sret(%struct.agg_v2i8) align 2 %{{.*}}, i16 %{{.*}}) +// CHECK-VECTOR-LABEL: define{{.*}} void @pass_agg_v2i8(ptr dead_on_unwind noalias writable sret(%struct.agg_v2i8) align 2 %{{.*}}, <2 x i8> %{{.*}}) struct agg_v4i8 { v4i8 a; }; struct agg_v4i8 pass_agg_v4i8(struct agg_v4i8 arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_agg_v4i8(ptr noalias sret(%struct.agg_v4i8) align 4 %{{.*}}, i32 %{{.*}}) -// CHECK-VECTOR-LABEL: define{{.*}} void @pass_agg_v4i8(ptr noalias sret(%struct.agg_v4i8) align 4 %{{.*}}, <4 x i8> %{{.*}}) +// CHECK-LABEL: define{{.*}} void @pass_agg_v4i8(ptr dead_on_unwind noalias writable sret(%struct.agg_v4i8) align 4 %{{.*}}, i32 %{{.*}}) +// CHECK-VECTOR-LABEL: define{{.*}} void @pass_agg_v4i8(ptr dead_on_unwind noalias writable sret(%struct.agg_v4i8) align 4 %{{.*}}, <4 x i8> %{{.*}}) struct agg_v8i8 { v8i8 a; }; struct agg_v8i8 pass_agg_v8i8(struct agg_v8i8 arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_agg_v8i8(ptr noalias sret(%struct.agg_v8i8) align 8 %{{.*}}, i64 %{{.*}}) -// CHECK-VECTOR-LABEL: define{{.*}} void @pass_agg_v8i8(ptr noalias sret(%struct.agg_v8i8) align 8 %{{.*}}, <8 x i8> %{{.*}}) +// CHECK-LABEL: define{{.*}} void @pass_agg_v8i8(ptr dead_on_unwind noalias writable sret(%struct.agg_v8i8) align 8 %{{.*}}, i64 %{{.*}}) +// CHECK-VECTOR-LABEL: define{{.*}} void @pass_agg_v8i8(ptr dead_on_unwind noalias writable sret(%struct.agg_v8i8) align 8 %{{.*}}, <8 x i8> %{{.*}}) struct agg_v16i8 { v16i8 a; }; struct agg_v16i8 pass_agg_v16i8(struct agg_v16i8 arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_agg_v16i8(ptr noalias sret(%struct.agg_v16i8) align 16 %{{.*}}, ptr %{{.*}}) -// CHECK-VECTOR-LABEL: define{{.*}} void @pass_agg_v16i8(ptr noalias sret(%struct.agg_v16i8) align 8 %{{.*}}, <16 x i8> %{{.*}}) +// CHECK-LABEL: define{{.*}} void @pass_agg_v16i8(ptr dead_on_unwind noalias writable sret(%struct.agg_v16i8) align 16 %{{.*}}, ptr %{{.*}}) +// CHECK-VECTOR-LABEL: define{{.*}} void @pass_agg_v16i8(ptr dead_on_unwind noalias writable sret(%struct.agg_v16i8) align 8 %{{.*}}, <16 x i8> %{{.*}}) struct agg_v32i8 { v32i8 a; }; struct agg_v32i8 pass_agg_v32i8(struct agg_v32i8 arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_agg_v32i8(ptr noalias sret(%struct.agg_v32i8) align 32 %{{.*}}, ptr %{{.*}}) -// CHECK-VECTOR-LABEL: define{{.*}} void @pass_agg_v32i8(ptr noalias sret(%struct.agg_v32i8) align 8 %{{.*}}, ptr %{{.*}}) +// CHECK-LABEL: define{{.*}} void @pass_agg_v32i8(ptr dead_on_unwind noalias writable sret(%struct.agg_v32i8) align 32 %{{.*}}, ptr %{{.*}}) +// CHECK-VECTOR-LABEL: define{{.*}} void @pass_agg_v32i8(ptr dead_on_unwind noalias writable sret(%struct.agg_v32i8) align 8 %{{.*}}, ptr %{{.*}}) // Verify that the following are *not* vector-like aggregate types struct agg_novector1 { v4i8 a; v4i8 b; }; struct agg_novector1 pass_agg_novector1(struct agg_novector1 arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_agg_novector1(ptr noalias sret(%struct.agg_novector1) align 4 %{{.*}}, i64 %{{.*}}) -// CHECK-VECTOR-LABEL: define{{.*}} void @pass_agg_novector1(ptr noalias sret(%struct.agg_novector1) align 4 %{{.*}}, i64 %{{.*}}) +// CHECK-LABEL: define{{.*}} void @pass_agg_novector1(ptr dead_on_unwind noalias writable sret(%struct.agg_novector1) align 4 %{{.*}}, i64 %{{.*}}) +// CHECK-VECTOR-LABEL: define{{.*}} void @pass_agg_novector1(ptr dead_on_unwind noalias writable sret(%struct.agg_novector1) align 4 %{{.*}}, i64 %{{.*}}) struct agg_novector2 { v4i8 a; float b; }; struct agg_novector2 pass_agg_novector2(struct agg_novector2 arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_agg_novector2(ptr noalias sret(%struct.agg_novector2) align 4 %{{.*}}, i64 %{{.*}}) -// CHECK-VECTOR-LABEL: define{{.*}} void @pass_agg_novector2(ptr noalias sret(%struct.agg_novector2) align 4 %{{.*}}, i64 %{{.*}}) +// CHECK-LABEL: define{{.*}} void @pass_agg_novector2(ptr dead_on_unwind noalias writable sret(%struct.agg_novector2) align 4 %{{.*}}, i64 %{{.*}}) +// CHECK-VECTOR-LABEL: define{{.*}} void @pass_agg_novector2(ptr dead_on_unwind noalias writable sret(%struct.agg_novector2) align 4 %{{.*}}, i64 %{{.*}}) struct agg_novector3 { v4i8 a; int : 0; }; struct agg_novector3 pass_agg_novector3(struct agg_novector3 arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_agg_novector3(ptr noalias sret(%struct.agg_novector3) align 4 %{{.*}}, i32 %{{.*}}) -// CHECK-VECTOR-LABEL: define{{.*}} void @pass_agg_novector3(ptr noalias sret(%struct.agg_novector3) align 4 %{{.*}}, i32 %{{.*}}) +// CHECK-LABEL: define{{.*}} void @pass_agg_novector3(ptr dead_on_unwind noalias writable sret(%struct.agg_novector3) align 4 %{{.*}}, i32 %{{.*}}) +// CHECK-VECTOR-LABEL: define{{.*}} void @pass_agg_novector3(ptr dead_on_unwind noalias writable sret(%struct.agg_novector3) align 4 %{{.*}}, i32 %{{.*}}) struct agg_novector4 { v4i8 a __attribute__((aligned (8))); }; struct agg_novector4 pass_agg_novector4(struct agg_novector4 arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_agg_novector4(ptr noalias sret(%struct.agg_novector4) align 8 %{{.*}}, i64 %{{.*}}) -// CHECK-VECTOR-LABEL: define{{.*}} void @pass_agg_novector4(ptr noalias sret(%struct.agg_novector4) align 8 %{{.*}}, i64 %{{.*}}) +// CHECK-LABEL: define{{.*}} void @pass_agg_novector4(ptr dead_on_unwind noalias writable sret(%struct.agg_novector4) align 8 %{{.*}}, i64 %{{.*}}) +// CHECK-VECTOR-LABEL: define{{.*}} void @pass_agg_novector4(ptr dead_on_unwind noalias writable sret(%struct.agg_novector4) align 8 %{{.*}}, i64 %{{.*}}) // Accessing variable argument lists v1i8 va_v1i8(__builtin_va_list l) { return __builtin_va_arg(l, v1i8); } -// CHECK-LABEL: define{{.*}} void @va_v1i8(ptr noalias sret(<1 x i8>) align 1 %{{.*}}, ptr %{{.*}}) +// CHECK-LABEL: define{{.*}} void @va_v1i8(ptr dead_on_unwind noalias writable sret(<1 x i8>) align 1 %{{.*}}, ptr %{{.*}}) // CHECK: [[REG_COUNT_PTR:%[^ ]+]] = getelementptr inbounds %struct.__va_list_tag, ptr %{{.*}}, i32 0, i32 0 // CHECK: [[REG_COUNT:%[^ ]+]] = load i64, ptr [[REG_COUNT_PTR]] // CHECK: [[FITS_IN_REGS:%[^ ]+]] = icmp ult i64 [[REG_COUNT]], 5 @@ -230,7 +230,7 @@ v1i8 va_v1i8(__builtin_va_list l) { return __builtin_va_arg(l, v1i8); } // CHECK-VECTOR: ret <1 x i8> [[RET]] v2i8 va_v2i8(__builtin_va_list l) { return __builtin_va_arg(l, v2i8); } -// CHECK-LABEL: define{{.*}} void @va_v2i8(ptr noalias sret(<2 x i8>) align 2 %{{.*}}, ptr %{{.*}}) +// CHECK-LABEL: define{{.*}} void @va_v2i8(ptr dead_on_unwind noalias writable sret(<2 x i8>) align 2 %{{.*}}, ptr %{{.*}}) // CHECK: [[REG_COUNT_PTR:%[^ ]+]] = getelementptr inbounds %struct.__va_list_tag, ptr %{{.*}}, i32 0, i32 0 // CHECK: [[REG_COUNT:%[^ ]+]] = load i64, ptr [[REG_COUNT_PTR]] // CHECK: [[FITS_IN_REGS:%[^ ]+]] = icmp ult i64 [[REG_COUNT]], 5 @@ -259,7 +259,7 @@ v2i8 va_v2i8(__builtin_va_list l) { return __builtin_va_arg(l, v2i8); } // CHECK-VECTOR: ret <2 x i8> [[RET]] v4i8 va_v4i8(__builtin_va_list l) { return __builtin_va_arg(l, v4i8); } -// CHECK-LABEL: define{{.*}} void @va_v4i8(ptr noalias sret(<4 x i8>) align 4 %{{.*}}, ptr %{{.*}}) +// CHECK-LABEL: define{{.*}} void @va_v4i8(ptr dead_on_unwind noalias writable sret(<4 x i8>) align 4 %{{.*}}, ptr %{{.*}}) // CHECK: [[REG_COUNT_PTR:%[^ ]+]] = getelementptr inbounds %struct.__va_list_tag, ptr %{{.*}}, i32 0, i32 0 // CHECK: [[REG_COUNT:%[^ ]+]] = load i64, ptr [[REG_COUNT_PTR]] // CHECK: [[FITS_IN_REGS:%[^ ]+]] = icmp ult i64 [[REG_COUNT]], 5 @@ -288,7 +288,7 @@ v4i8 va_v4i8(__builtin_va_list l) { return __builtin_va_arg(l, v4i8); } // CHECK-VECTOR: ret <4 x i8> [[RET]] v8i8 va_v8i8(__builtin_va_list l) { return __builtin_va_arg(l, v8i8); } -// CHECK-LABEL: define{{.*}} void @va_v8i8(ptr noalias sret(<8 x i8>) align 8 %{{.*}}, ptr %{{.*}}) +// CHECK-LABEL: define{{.*}} void @va_v8i8(ptr dead_on_unwind noalias writable sret(<8 x i8>) align 8 %{{.*}}, ptr %{{.*}}) // CHECK: [[REG_COUNT_PTR:%[^ ]+]] = getelementptr inbounds %struct.__va_list_tag, ptr %{{.*}}, i32 0, i32 0 // CHECK: [[REG_COUNT:%[^ ]+]] = load i64, ptr [[REG_COUNT_PTR]] // CHECK: [[FITS_IN_REGS:%[^ ]+]] = icmp ult i64 [[REG_COUNT]], 5 @@ -317,7 +317,7 @@ v8i8 va_v8i8(__builtin_va_list l) { return __builtin_va_arg(l, v8i8); } // CHECK-VECTOR: ret <8 x i8> [[RET]] v16i8 va_v16i8(__builtin_va_list l) { return __builtin_va_arg(l, v16i8); } -// CHECK-LABEL: define{{.*}} void @va_v16i8(ptr noalias sret(<16 x i8>) align 16 %{{.*}}, ptr %{{.*}}) +// CHECK-LABEL: define{{.*}} void @va_v16i8(ptr dead_on_unwind noalias writable sret(<16 x i8>) align 16 %{{.*}}, ptr %{{.*}}) // CHECK: [[REG_COUNT_PTR:%[^ ]+]] = getelementptr inbounds %struct.__va_list_tag, ptr %{{.*}}, i32 0, i32 0 // CHECK: [[REG_COUNT:%[^ ]+]] = load i64, ptr [[REG_COUNT_PTR]] // CHECK: [[FITS_IN_REGS:%[^ ]+]] = icmp ult i64 [[REG_COUNT]], 5 @@ -346,7 +346,7 @@ v16i8 va_v16i8(__builtin_va_list l) { return __builtin_va_arg(l, v16i8); } // CHECK-VECTOR: ret <16 x i8> [[RET]] v32i8 va_v32i8(__builtin_va_list l) { return __builtin_va_arg(l, v32i8); } -// CHECK-LABEL: define{{.*}} void @va_v32i8(ptr noalias sret(<32 x i8>) align 32 %{{.*}}, ptr %{{.*}}) +// CHECK-LABEL: define{{.*}} void @va_v32i8(ptr dead_on_unwind noalias writable sret(<32 x i8>) align 32 %{{.*}}, ptr %{{.*}}) // CHECK: [[REG_COUNT_PTR:%[^ ]+]] = getelementptr inbounds %struct.__va_list_tag, ptr %{{.*}}, i32 0, i32 0 // CHECK: [[REG_COUNT:%[^ ]+]] = load i64, ptr [[REG_COUNT_PTR]] // CHECK: [[FITS_IN_REGS:%[^ ]+]] = icmp ult i64 [[REG_COUNT]], 5 @@ -366,7 +366,7 @@ v32i8 va_v32i8(__builtin_va_list l) { return __builtin_va_arg(l, v32i8); } // CHECK: [[VA_ARG_ADDR:%[^ ]+]] = phi ptr [ [[RAW_REG_ADDR]], %{{.*}} ], [ [[RAW_MEM_ADDR]], %{{.*}} ] // CHECK: [[INDIRECT_ARG:%[^ ]+]] = load ptr, ptr [[VA_ARG_ADDR]] // CHECK: ret void -// CHECK-VECTOR-LABEL: define{{.*}} void @va_v32i8(ptr noalias sret(<32 x i8>) align 8 %{{.*}}, ptr %{{.*}}) +// CHECK-VECTOR-LABEL: define{{.*}} void @va_v32i8(ptr dead_on_unwind noalias writable sret(<32 x i8>) align 8 %{{.*}}, ptr %{{.*}}) // CHECK-VECTOR: [[REG_COUNT_PTR:%[^ ]+]] = getelementptr inbounds %struct.__va_list_tag, ptr %{{.*}}, i32 0, i32 0 // CHECK-VECTOR: [[REG_COUNT:%[^ ]+]] = load i64, ptr [[REG_COUNT_PTR]] // CHECK-VECTOR: [[FITS_IN_REGS:%[^ ]+]] = icmp ult i64 [[REG_COUNT]], 5 @@ -388,7 +388,7 @@ v32i8 va_v32i8(__builtin_va_list l) { return __builtin_va_arg(l, v32i8); } // CHECK-VECTOR: ret void struct agg_v1i8 va_agg_v1i8(__builtin_va_list l) { return __builtin_va_arg(l, struct agg_v1i8); } -// CHECK-LABEL: define{{.*}} void @va_agg_v1i8(ptr noalias sret(%struct.agg_v1i8) align 1 %{{.*}}, ptr %{{.*}}) +// CHECK-LABEL: define{{.*}} void @va_agg_v1i8(ptr dead_on_unwind noalias writable sret(%struct.agg_v1i8) align 1 %{{.*}}, ptr %{{.*}}) // CHECK: [[REG_COUNT_PTR:%[^ ]+]] = getelementptr inbounds %struct.__va_list_tag, ptr %{{.*}}, i32 0, i32 0 // CHECK: [[REG_COUNT:%[^ ]+]] = load i64, ptr [[REG_COUNT_PTR]] // CHECK: [[FITS_IN_REGS:%[^ ]+]] = icmp ult i64 [[REG_COUNT]], 5 @@ -407,7 +407,7 @@ struct agg_v1i8 va_agg_v1i8(__builtin_va_list l) { return __builtin_va_arg(l, st // CHECK: store ptr [[OVERFLOW_ARG_AREA2]], ptr [[OVERFLOW_ARG_AREA_PTR]] // CHECK: [[VA_ARG_ADDR:%[^ ]+]] = phi ptr [ [[RAW_REG_ADDR]], %{{.*}} ], [ [[RAW_MEM_ADDR]], %{{.*}} ] // CHECK: ret void -// CHECK-VECTOR-LABEL: define{{.*}} void @va_agg_v1i8(ptr noalias sret(%struct.agg_v1i8) align 1 %{{.*}}, ptr %{{.*}}) +// CHECK-VECTOR-LABEL: define{{.*}} void @va_agg_v1i8(ptr dead_on_unwind noalias writable sret(%struct.agg_v1i8) align 1 %{{.*}}, ptr %{{.*}}) // CHECK-VECTOR: [[OVERFLOW_ARG_AREA_PTR:%[^ ]+]] = getelementptr inbounds %struct.__va_list_tag, ptr %{{.*}}, i32 0, i32 2 // CHECK-VECTOR: [[OVERFLOW_ARG_AREA:%[^ ]+]] = load ptr, ptr [[OVERFLOW_ARG_AREA_PTR]] // CHECK-VECTOR: [[OVERFLOW_ARG_AREA1:%[^ ]+]] = getelementptr i8, ptr [[OVERFLOW_ARG_AREA]], i64 8 @@ -415,7 +415,7 @@ struct agg_v1i8 va_agg_v1i8(__builtin_va_list l) { return __builtin_va_arg(l, st // CHECK-VECTOR: ret void struct agg_v2i8 va_agg_v2i8(__builtin_va_list l) { return __builtin_va_arg(l, struct agg_v2i8); } -// CHECK-LABEL: define{{.*}} void @va_agg_v2i8(ptr noalias sret(%struct.agg_v2i8) align 2 %{{.*}}, ptr %{{.*}}) +// CHECK-LABEL: define{{.*}} void @va_agg_v2i8(ptr dead_on_unwind noalias writable sret(%struct.agg_v2i8) align 2 %{{.*}}, ptr %{{.*}}) // CHECK: [[REG_COUNT_PTR:%[^ ]+]] = getelementptr inbounds %struct.__va_list_tag, ptr %{{.*}}, i32 0, i32 0 // CHECK: [[REG_COUNT:%[^ ]+]] = load i64, ptr [[REG_COUNT_PTR]] // CHECK: [[FITS_IN_REGS:%[^ ]+]] = icmp ult i64 [[REG_COUNT]], 5 @@ -434,7 +434,7 @@ struct agg_v2i8 va_agg_v2i8(__builtin_va_list l) { return __builtin_va_arg(l, st // CHECK: store ptr [[OVERFLOW_ARG_AREA2]], ptr [[OVERFLOW_ARG_AREA_PTR]] // CHECK: [[VA_ARG_ADDR:%[^ ]+]] = phi ptr [ [[RAW_REG_ADDR]], %{{.*}} ], [ [[RAW_MEM_ADDR]], %{{.*}} ] // CHECK: ret void -// CHECK-VECTOR-LABEL: define{{.*}} void @va_agg_v2i8(ptr noalias sret(%struct.agg_v2i8) align 2 %{{.*}}, ptr %{{.*}}) +// CHECK-VECTOR-LABEL: define{{.*}} void @va_agg_v2i8(ptr dead_on_unwind noalias writable sret(%struct.agg_v2i8) align 2 %{{.*}}, ptr %{{.*}}) // CHECK-VECTOR: [[OVERFLOW_ARG_AREA_PTR:%[^ ]+]] = getelementptr inbounds %struct.__va_list_tag, ptr %{{.*}}, i32 0, i32 2 // CHECK-VECTOR: [[OVERFLOW_ARG_AREA:%[^ ]+]] = load ptr, ptr [[OVERFLOW_ARG_AREA_PTR]] // CHECK-VECTOR: [[OVERFLOW_ARG_AREA1:%[^ ]+]] = getelementptr i8, ptr [[OVERFLOW_ARG_AREA]], i64 8 @@ -442,7 +442,7 @@ struct agg_v2i8 va_agg_v2i8(__builtin_va_list l) { return __builtin_va_arg(l, st // CHECK-VECTOR: ret void struct agg_v4i8 va_agg_v4i8(__builtin_va_list l) { return __builtin_va_arg(l, struct agg_v4i8); } -// CHECK-LABEL: define{{.*}} void @va_agg_v4i8(ptr noalias sret(%struct.agg_v4i8) align 4 %{{.*}}, ptr %{{.*}}) +// CHECK-LABEL: define{{.*}} void @va_agg_v4i8(ptr dead_on_unwind noalias writable sret(%struct.agg_v4i8) align 4 %{{.*}}, ptr %{{.*}}) // CHECK: [[REG_COUNT_PTR:%[^ ]+]] = getelementptr inbounds %struct.__va_list_tag, ptr %{{.*}}, i32 0, i32 0 // CHECK: [[REG_COUNT:%[^ ]+]] = load i64, ptr [[REG_COUNT_PTR]] // CHECK: [[FITS_IN_REGS:%[^ ]+]] = icmp ult i64 [[REG_COUNT]], 5 @@ -461,7 +461,7 @@ struct agg_v4i8 va_agg_v4i8(__builtin_va_list l) { return __builtin_va_arg(l, st // CHECK: store ptr [[OVERFLOW_ARG_AREA2]], ptr [[OVERFLOW_ARG_AREA_PTR]] // CHECK: [[VA_ARG_ADDR:%[^ ]+]] = phi ptr [ [[RAW_REG_ADDR]], %{{.*}} ], [ [[RAW_MEM_ADDR]], %{{.*}} ] // CHECK: ret void -// CHECK-VECTOR-LABEL: define{{.*}} void @va_agg_v4i8(ptr noalias sret(%struct.agg_v4i8) align 4 %{{.*}}, ptr %{{.*}}) +// CHECK-VECTOR-LABEL: define{{.*}} void @va_agg_v4i8(ptr dead_on_unwind noalias writable sret(%struct.agg_v4i8) align 4 %{{.*}}, ptr %{{.*}}) // CHECK-VECTOR: [[OVERFLOW_ARG_AREA_PTR:%[^ ]+]] = getelementptr inbounds %struct.__va_list_tag, ptr %{{.*}}, i32 0, i32 2 // CHECK-VECTOR: [[OVERFLOW_ARG_AREA:%[^ ]+]] = load ptr, ptr [[OVERFLOW_ARG_AREA_PTR]] // CHECK-VECTOR: [[OVERFLOW_ARG_AREA1:%[^ ]+]] = getelementptr i8, ptr [[OVERFLOW_ARG_AREA]], i64 8 @@ -469,7 +469,7 @@ struct agg_v4i8 va_agg_v4i8(__builtin_va_list l) { return __builtin_va_arg(l, st // CHECK-VECTOR: ret void struct agg_v8i8 va_agg_v8i8(__builtin_va_list l) { return __builtin_va_arg(l, struct agg_v8i8); } -// CHECK-LABEL: define{{.*}} void @va_agg_v8i8(ptr noalias sret(%struct.agg_v8i8) align 8 %{{.*}}, ptr %{{.*}}) +// CHECK-LABEL: define{{.*}} void @va_agg_v8i8(ptr dead_on_unwind noalias writable sret(%struct.agg_v8i8) align 8 %{{.*}}, ptr %{{.*}}) // CHECK: [[REG_COUNT_PTR:%[^ ]+]] = getelementptr inbounds %struct.__va_list_tag, ptr %{{.*}}, i32 0, i32 0 // CHECK: [[REG_COUNT:%[^ ]+]] = load i64, ptr [[REG_COUNT_PTR]] // CHECK: [[FITS_IN_REGS:%[^ ]+]] = icmp ult i64 [[REG_COUNT]], 5 @@ -488,7 +488,7 @@ struct agg_v8i8 va_agg_v8i8(__builtin_va_list l) { return __builtin_va_arg(l, st // CHECK: store ptr [[OVERFLOW_ARG_AREA2]], ptr [[OVERFLOW_ARG_AREA_PTR]] // CHECK: [[VA_ARG_ADDR:%[^ ]+]] = phi ptr [ [[RAW_REG_ADDR]], %{{.*}} ], [ [[RAW_MEM_ADDR]], %{{.*}} ] // CHECK: ret void -// CHECK-VECTOR-LABEL: define{{.*}} void @va_agg_v8i8(ptr noalias sret(%struct.agg_v8i8) align 8 %{{.*}}, ptr %{{.*}}) +// CHECK-VECTOR-LABEL: define{{.*}} void @va_agg_v8i8(ptr dead_on_unwind noalias writable sret(%struct.agg_v8i8) align 8 %{{.*}}, ptr %{{.*}}) // CHECK-VECTOR: [[OVERFLOW_ARG_AREA_PTR:%[^ ]+]] = getelementptr inbounds %struct.__va_list_tag, ptr %{{.*}}, i32 0, i32 2 // CHECK-VECTOR: [[OVERFLOW_ARG_AREA:%[^ ]+]] = load ptr, ptr [[OVERFLOW_ARG_AREA_PTR]] // CHECK-VECTOR: [[OVERFLOW_ARG_AREA1:%[^ ]+]] = getelementptr i8, ptr [[OVERFLOW_ARG_AREA]], i64 8 @@ -496,7 +496,7 @@ struct agg_v8i8 va_agg_v8i8(__builtin_va_list l) { return __builtin_va_arg(l, st // CHECK-VECTOR: ret void struct agg_v16i8 va_agg_v16i8(__builtin_va_list l) { return __builtin_va_arg(l, struct agg_v16i8); } -// CHECK-LABEL: define{{.*}} void @va_agg_v16i8(ptr noalias sret(%struct.agg_v16i8) align 16 %{{.*}}, ptr %{{.*}}) +// CHECK-LABEL: define{{.*}} void @va_agg_v16i8(ptr dead_on_unwind noalias writable sret(%struct.agg_v16i8) align 16 %{{.*}}, ptr %{{.*}}) // CHECK: [[REG_COUNT_PTR:%[^ ]+]] = getelementptr inbounds %struct.__va_list_tag, ptr %{{.*}}, i32 0, i32 0 // CHECK: [[REG_COUNT:%[^ ]+]] = load i64, ptr [[REG_COUNT_PTR]] // CHECK: [[FITS_IN_REGS:%[^ ]+]] = icmp ult i64 [[REG_COUNT]], 5 @@ -516,7 +516,7 @@ struct agg_v16i8 va_agg_v16i8(__builtin_va_list l) { return __builtin_va_arg(l, // CHECK: [[VA_ARG_ADDR:%[^ ]+]] = phi ptr [ [[RAW_REG_ADDR]], %{{.*}} ], [ [[RAW_MEM_ADDR]], %{{.*}} ] // CHECK: [[INDIRECT_ARG:%[^ ]+]] = load ptr, ptr [[VA_ARG_ADDR]] // CHECK: ret void -// CHECK-VECTOR-LABEL: define{{.*}} void @va_agg_v16i8(ptr noalias sret(%struct.agg_v16i8) align 8 %{{.*}}, ptr %{{.*}}) +// CHECK-VECTOR-LABEL: define{{.*}} void @va_agg_v16i8(ptr dead_on_unwind noalias writable sret(%struct.agg_v16i8) align 8 %{{.*}}, ptr %{{.*}}) // CHECK-VECTOR: [[OVERFLOW_ARG_AREA_PTR:%[^ ]+]] = getelementptr inbounds %struct.__va_list_tag, ptr %{{.*}}, i32 0, i32 2 // CHECK-VECTOR: [[OVERFLOW_ARG_AREA:%[^ ]+]] = load ptr, ptr [[OVERFLOW_ARG_AREA_PTR]] // CHECK-VECTOR: [[OVERFLOW_ARG_AREA1:%[^ ]+]] = getelementptr i8, ptr [[OVERFLOW_ARG_AREA]], i64 16 @@ -524,7 +524,7 @@ struct agg_v16i8 va_agg_v16i8(__builtin_va_list l) { return __builtin_va_arg(l, // CHECK-VECTOR: ret void struct agg_v32i8 va_agg_v32i8(__builtin_va_list l) { return __builtin_va_arg(l, struct agg_v32i8); } -// CHECK-LABEL: define{{.*}} void @va_agg_v32i8(ptr noalias sret(%struct.agg_v32i8) align 32 %{{.*}}, ptr %{{.*}}) +// CHECK-LABEL: define{{.*}} void @va_agg_v32i8(ptr dead_on_unwind noalias writable sret(%struct.agg_v32i8) align 32 %{{.*}}, ptr %{{.*}}) // CHECK: [[REG_COUNT_PTR:%[^ ]+]] = getelementptr inbounds %struct.__va_list_tag, ptr %{{.*}}, i32 0, i32 0 // CHECK: [[REG_COUNT:%[^ ]+]] = load i64, ptr [[REG_COUNT_PTR]] // CHECK: [[FITS_IN_REGS:%[^ ]+]] = icmp ult i64 [[REG_COUNT]], 5 @@ -544,7 +544,7 @@ struct agg_v32i8 va_agg_v32i8(__builtin_va_list l) { return __builtin_va_arg(l, // CHECK: [[VA_ARG_ADDR:%[^ ]+]] = phi ptr [ [[RAW_REG_ADDR]], %{{.*}} ], [ [[RAW_MEM_ADDR]], %{{.*}} ] // CHECK: [[INDIRECT_ARG:%[^ ]+]] = load ptr, ptr [[VA_ARG_ADDR]] // CHECK: ret void -// CHECK-VECTOR-LABEL: define{{.*}} void @va_agg_v32i8(ptr noalias sret(%struct.agg_v32i8) align 8 %{{.*}}, ptr %{{.*}}) +// CHECK-VECTOR-LABEL: define{{.*}} void @va_agg_v32i8(ptr dead_on_unwind noalias writable sret(%struct.agg_v32i8) align 8 %{{.*}}, ptr %{{.*}}) // CHECK-VECTOR: [[REG_COUNT_PTR:%[^ ]+]] = getelementptr inbounds %struct.__va_list_tag, ptr %{{.*}}, i32 0, i32 0 // CHECK-VECTOR: [[REG_COUNT:%[^ ]+]] = load i64, ptr [[REG_COUNT_PTR]] // CHECK-VECTOR: [[FITS_IN_REGS:%[^ ]+]] = icmp ult i64 [[REG_COUNT]], 5 diff --git a/clang/test/CodeGen/SystemZ/systemz-abi.c b/clang/test/CodeGen/SystemZ/systemz-abi.c index 7b2c04ece185ff39401f49e06a6b73d8dcdd7115..65a2bc9bbb680e82386ff0dc7cccc196cab79368 100644 --- a/clang/test/CodeGen/SystemZ/systemz-abi.c +++ b/clang/test/CodeGen/SystemZ/systemz-abi.c @@ -43,7 +43,7 @@ long long pass_longlong(long long arg) { return arg; } // CHECK-LABEL: define{{.*}} i64 @pass_longlong(i64 %{{.*}}) __int128 pass_int128(__int128 arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_int128(ptr noalias sret(i128) align 8 %{{.*}}, ptr %0) +// CHECK-LABEL: define{{.*}} void @pass_int128(ptr dead_on_unwind noalias writable sret(i128) align 8 %{{.*}}, ptr %0) float pass_float(float arg) { return arg; } // CHECK-LABEL: define{{.*}} float @pass_float(float %{{.*}}) @@ -52,125 +52,125 @@ double pass_double(double arg) { return arg; } // CHECK-LABEL: define{{.*}} double @pass_double(double %{{.*}}) long double pass_longdouble(long double arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_longdouble(ptr noalias sret(fp128) align 8 %{{.*}}, ptr %0) +// CHECK-LABEL: define{{.*}} void @pass_longdouble(ptr dead_on_unwind noalias writable sret(fp128) align 8 %{{.*}}, ptr %0) // Complex types _Complex char pass_complex_char(_Complex char arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_complex_char(ptr noalias sret({ i8, i8 }) align 1 %{{.*}}, ptr %{{.*}}arg) +// CHECK-LABEL: define{{.*}} void @pass_complex_char(ptr dead_on_unwind noalias writable sret({ i8, i8 }) align 1 %{{.*}}, ptr %{{.*}}arg) _Complex short pass_complex_short(_Complex short arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_complex_short(ptr noalias sret({ i16, i16 }) align 2 %{{.*}}, ptr %{{.*}}arg) +// CHECK-LABEL: define{{.*}} void @pass_complex_short(ptr dead_on_unwind noalias writable sret({ i16, i16 }) align 2 %{{.*}}, ptr %{{.*}}arg) _Complex int pass_complex_int(_Complex int arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_complex_int(ptr noalias sret({ i32, i32 }) align 4 %{{.*}}, ptr %{{.*}}arg) +// CHECK-LABEL: define{{.*}} void @pass_complex_int(ptr dead_on_unwind noalias writable sret({ i32, i32 }) align 4 %{{.*}}, ptr %{{.*}}arg) _Complex long pass_complex_long(_Complex long arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_complex_long(ptr noalias sret({ i64, i64 }) align 8 %{{.*}}, ptr %{{.*}}arg) +// CHECK-LABEL: define{{.*}} void @pass_complex_long(ptr dead_on_unwind noalias writable sret({ i64, i64 }) align 8 %{{.*}}, ptr %{{.*}}arg) _Complex long long pass_complex_longlong(_Complex long long arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_complex_longlong(ptr noalias sret({ i64, i64 }) align 8 %{{.*}}, ptr %{{.*}}arg) +// CHECK-LABEL: define{{.*}} void @pass_complex_longlong(ptr dead_on_unwind noalias writable sret({ i64, i64 }) align 8 %{{.*}}, ptr %{{.*}}arg) _Complex float pass_complex_float(_Complex float arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_complex_float(ptr noalias sret({ float, float }) align 4 %{{.*}}, ptr %{{.*}}arg) +// CHECK-LABEL: define{{.*}} void @pass_complex_float(ptr dead_on_unwind noalias writable sret({ float, float }) align 4 %{{.*}}, ptr %{{.*}}arg) _Complex double pass_complex_double(_Complex double arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_complex_double(ptr noalias sret({ double, double }) align 8 %{{.*}}, ptr %{{.*}}arg) +// CHECK-LABEL: define{{.*}} void @pass_complex_double(ptr dead_on_unwind noalias writable sret({ double, double }) align 8 %{{.*}}, ptr %{{.*}}arg) _Complex long double pass_complex_longdouble(_Complex long double arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_complex_longdouble(ptr noalias sret({ fp128, fp128 }) align 8 %{{.*}}, ptr %{{.*}}arg) +// CHECK-LABEL: define{{.*}} void @pass_complex_longdouble(ptr dead_on_unwind noalias writable sret({ fp128, fp128 }) align 8 %{{.*}}, ptr %{{.*}}arg) // Aggregate types struct agg_1byte { char a[1]; }; struct agg_1byte pass_agg_1byte(struct agg_1byte arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_agg_1byte(ptr noalias sret(%struct.agg_1byte) align 1 %{{.*}}, i8 %{{.*}}) +// CHECK-LABEL: define{{.*}} void @pass_agg_1byte(ptr dead_on_unwind noalias writable sret(%struct.agg_1byte) align 1 %{{.*}}, i8 %{{.*}}) struct agg_2byte { char a[2]; }; struct agg_2byte pass_agg_2byte(struct agg_2byte arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_agg_2byte(ptr noalias sret(%struct.agg_2byte) align 1 %{{.*}}, i16 %{{.*}}) +// CHECK-LABEL: define{{.*}} void @pass_agg_2byte(ptr dead_on_unwind noalias writable sret(%struct.agg_2byte) align 1 %{{.*}}, i16 %{{.*}}) struct agg_3byte { char a[3]; }; struct agg_3byte pass_agg_3byte(struct agg_3byte arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_agg_3byte(ptr noalias sret(%struct.agg_3byte) align 1 %{{.*}}, ptr %{{.*}}) +// CHECK-LABEL: define{{.*}} void @pass_agg_3byte(ptr dead_on_unwind noalias writable sret(%struct.agg_3byte) align 1 %{{.*}}, ptr %{{.*}}) struct agg_4byte { char a[4]; }; struct agg_4byte pass_agg_4byte(struct agg_4byte arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_agg_4byte(ptr noalias sret(%struct.agg_4byte) align 1 %{{.*}}, i32 %{{.*}}) +// CHECK-LABEL: define{{.*}} void @pass_agg_4byte(ptr dead_on_unwind noalias writable sret(%struct.agg_4byte) align 1 %{{.*}}, i32 %{{.*}}) struct agg_5byte { char a[5]; }; struct agg_5byte pass_agg_5byte(struct agg_5byte arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_agg_5byte(ptr noalias sret(%struct.agg_5byte) align 1 %{{.*}}, ptr %{{.*}}) +// CHECK-LABEL: define{{.*}} void @pass_agg_5byte(ptr dead_on_unwind noalias writable sret(%struct.agg_5byte) align 1 %{{.*}}, ptr %{{.*}}) struct agg_6byte { char a[6]; }; struct agg_6byte pass_agg_6byte(struct agg_6byte arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_agg_6byte(ptr noalias sret(%struct.agg_6byte) align 1 %{{.*}}, ptr %{{.*}}) +// CHECK-LABEL: define{{.*}} void @pass_agg_6byte(ptr dead_on_unwind noalias writable sret(%struct.agg_6byte) align 1 %{{.*}}, ptr %{{.*}}) struct agg_7byte { char a[7]; }; struct agg_7byte pass_agg_7byte(struct agg_7byte arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_agg_7byte(ptr noalias sret(%struct.agg_7byte) align 1 %{{.*}}, ptr %{{.*}}) +// CHECK-LABEL: define{{.*}} void @pass_agg_7byte(ptr dead_on_unwind noalias writable sret(%struct.agg_7byte) align 1 %{{.*}}, ptr %{{.*}}) struct agg_8byte { char a[8]; }; struct agg_8byte pass_agg_8byte(struct agg_8byte arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_agg_8byte(ptr noalias sret(%struct.agg_8byte) align 1 %{{.*}}, i64 %{{.*}}) +// CHECK-LABEL: define{{.*}} void @pass_agg_8byte(ptr dead_on_unwind noalias writable sret(%struct.agg_8byte) align 1 %{{.*}}, i64 %{{.*}}) struct agg_16byte { char a[16]; }; struct agg_16byte pass_agg_16byte(struct agg_16byte arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_agg_16byte(ptr noalias sret(%struct.agg_16byte) align 1 %{{.*}}, ptr %{{.*}}) +// CHECK-LABEL: define{{.*}} void @pass_agg_16byte(ptr dead_on_unwind noalias writable sret(%struct.agg_16byte) align 1 %{{.*}}, ptr %{{.*}}) // Float-like aggregate types struct agg_float { float a; }; struct agg_float pass_agg_float(struct agg_float arg) { return arg; } -// HARD-FLOAT-LABEL: define{{.*}} void @pass_agg_float(ptr noalias sret(%struct.agg_float) align 4 %{{.*}}, float %{{.*}}) -// SOFT-FLOAT-LABEL: define{{.*}} void @pass_agg_float(ptr noalias sret(%struct.agg_float) align 4 %{{.*}}, i32 %{{.*}}) +// HARD-FLOAT-LABEL: define{{.*}} void @pass_agg_float(ptr dead_on_unwind noalias writable sret(%struct.agg_float) align 4 %{{.*}}, float %{{.*}}) +// SOFT-FLOAT-LABEL: define{{.*}} void @pass_agg_float(ptr dead_on_unwind noalias writable sret(%struct.agg_float) align 4 %{{.*}}, i32 %{{.*}}) struct agg_double { double a; }; struct agg_double pass_agg_double(struct agg_double arg) { return arg; } -// HARD-FLOAT-LABEL: define{{.*}} void @pass_agg_double(ptr noalias sret(%struct.agg_double) align 8 %{{.*}}, double %{{.*}}) -// SOFT-FLOAT-LABEL: define{{.*}} void @pass_agg_double(ptr noalias sret(%struct.agg_double) align 8 %{{.*}}, i64 %{{.*}}) +// HARD-FLOAT-LABEL: define{{.*}} void @pass_agg_double(ptr dead_on_unwind noalias writable sret(%struct.agg_double) align 8 %{{.*}}, double %{{.*}}) +// SOFT-FLOAT-LABEL: define{{.*}} void @pass_agg_double(ptr dead_on_unwind noalias writable sret(%struct.agg_double) align 8 %{{.*}}, i64 %{{.*}}) struct agg_longdouble { long double a; }; struct agg_longdouble pass_agg_longdouble(struct agg_longdouble arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_agg_longdouble(ptr noalias sret(%struct.agg_longdouble) align 8 %{{.*}}, ptr %{{.*}}) +// CHECK-LABEL: define{{.*}} void @pass_agg_longdouble(ptr dead_on_unwind noalias writable sret(%struct.agg_longdouble) align 8 %{{.*}}, ptr %{{.*}}) struct agg_float_a8 { float a __attribute__((aligned (8))); }; struct agg_float_a8 pass_agg_float_a8(struct agg_float_a8 arg) { return arg; } -// HARD-FLOAT-LABEL: define{{.*}} void @pass_agg_float_a8(ptr noalias sret(%struct.agg_float_a8) align 8 %{{.*}}, double %{{.*}}) -// SOFT-FLOAT-LABEL: define{{.*}} void @pass_agg_float_a8(ptr noalias sret(%struct.agg_float_a8) align 8 %{{.*}}, i64 %{{.*}}) +// HARD-FLOAT-LABEL: define{{.*}} void @pass_agg_float_a8(ptr dead_on_unwind noalias writable sret(%struct.agg_float_a8) align 8 %{{.*}}, double %{{.*}}) +// SOFT-FLOAT-LABEL: define{{.*}} void @pass_agg_float_a8(ptr dead_on_unwind noalias writable sret(%struct.agg_float_a8) align 8 %{{.*}}, i64 %{{.*}}) struct agg_float_a16 { float a __attribute__((aligned (16))); }; struct agg_float_a16 pass_agg_float_a16(struct agg_float_a16 arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_agg_float_a16(ptr noalias sret(%struct.agg_float_a16) align 16 %{{.*}}, ptr %{{.*}}) +// CHECK-LABEL: define{{.*}} void @pass_agg_float_a16(ptr dead_on_unwind noalias writable sret(%struct.agg_float_a16) align 16 %{{.*}}, ptr %{{.*}}) // Verify that the following are *not* float-like aggregate types struct agg_nofloat1 { float a; float b; }; struct agg_nofloat1 pass_agg_nofloat1(struct agg_nofloat1 arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_agg_nofloat1(ptr noalias sret(%struct.agg_nofloat1) align 4 %{{.*}}, i64 %{{.*}}) +// CHECK-LABEL: define{{.*}} void @pass_agg_nofloat1(ptr dead_on_unwind noalias writable sret(%struct.agg_nofloat1) align 4 %{{.*}}, i64 %{{.*}}) struct agg_nofloat2 { float a; int b; }; struct agg_nofloat2 pass_agg_nofloat2(struct agg_nofloat2 arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_agg_nofloat2(ptr noalias sret(%struct.agg_nofloat2) align 4 %{{.*}}, i64 %{{.*}}) +// CHECK-LABEL: define{{.*}} void @pass_agg_nofloat2(ptr dead_on_unwind noalias writable sret(%struct.agg_nofloat2) align 4 %{{.*}}, i64 %{{.*}}) struct agg_nofloat3 { float a; int : 0; }; struct agg_nofloat3 pass_agg_nofloat3(struct agg_nofloat3 arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_agg_nofloat3(ptr noalias sret(%struct.agg_nofloat3) align 4 %{{.*}}, i32 %{{.*}}) +// CHECK-LABEL: define{{.*}} void @pass_agg_nofloat3(ptr dead_on_unwind noalias writable sret(%struct.agg_nofloat3) align 4 %{{.*}}, i32 %{{.*}}) // Union types likewise are *not* float-like aggregate types union union_float { float a; }; union union_float pass_union_float(union union_float arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_union_float(ptr noalias sret(%union.union_float) align 4 %{{.*}}, i32 %{{.*}}) +// CHECK-LABEL: define{{.*}} void @pass_union_float(ptr dead_on_unwind noalias writable sret(%union.union_float) align 4 %{{.*}}, i32 %{{.*}}) union union_double { double a; }; union union_double pass_union_double(union union_double arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_union_double(ptr noalias sret(%union.union_double) align 8 %{{.*}}, i64 %{{.*}}) +// CHECK-LABEL: define{{.*}} void @pass_union_double(ptr dead_on_unwind noalias writable sret(%union.union_double) align 8 %{{.*}}, i64 %{{.*}}) // Accessing variable argument lists @@ -267,7 +267,7 @@ double va_double(__builtin_va_list l) { return __builtin_va_arg(l, double); } // CHECK: ret double [[RET]] long double va_longdouble(__builtin_va_list l) { return __builtin_va_arg(l, long double); } -// CHECK-LABEL: define{{.*}} void @va_longdouble(ptr noalias sret(fp128) align 8 %{{.*}}, ptr %{{.*}}) +// CHECK-LABEL: define{{.*}} void @va_longdouble(ptr dead_on_unwind noalias writable sret(fp128) align 8 %{{.*}}, ptr %{{.*}}) // CHECK: [[REG_COUNT_PTR:%[^ ]+]] = getelementptr inbounds %struct.__va_list_tag, ptr %{{.*}}, i32 0, i32 0 // CHECK: [[REG_COUNT:%[^ ]+]] = load i64, ptr [[REG_COUNT_PTR]] // CHECK: [[FITS_IN_REGS:%[^ ]+]] = icmp ult i64 [[REG_COUNT]], 5 @@ -291,7 +291,7 @@ long double va_longdouble(__builtin_va_list l) { return __builtin_va_arg(l, long // CHECK: ret void _Complex char va_complex_char(__builtin_va_list l) { return __builtin_va_arg(l, _Complex char); } -// CHECK-LABEL: define{{.*}} void @va_complex_char(ptr noalias sret({ i8, i8 }) align 1 %{{.*}}, ptr %{{.*}} +// CHECK-LABEL: define{{.*}} void @va_complex_char(ptr dead_on_unwind noalias writable sret({ i8, i8 }) align 1 %{{.*}}, ptr %{{.*}} // CHECK: [[REG_COUNT_PTR:%[^ ]+]] = getelementptr inbounds %struct.__va_list_tag, ptr %{{.*}}, i32 0, i32 0 // CHECK: [[REG_COUNT:%[^ ]+]] = load i64, ptr [[REG_COUNT_PTR]] // CHECK: [[FITS_IN_REGS:%[^ ]+]] = icmp ult i64 [[REG_COUNT]], 5 @@ -313,7 +313,7 @@ _Complex char va_complex_char(__builtin_va_list l) { return __builtin_va_arg(l, // CHECK: ret void struct agg_1byte va_agg_1byte(__builtin_va_list l) { return __builtin_va_arg(l, struct agg_1byte); } -// CHECK-LABEL: define{{.*}} void @va_agg_1byte(ptr noalias sret(%struct.agg_1byte) align 1 %{{.*}}, ptr %{{.*}} +// CHECK-LABEL: define{{.*}} void @va_agg_1byte(ptr dead_on_unwind noalias writable sret(%struct.agg_1byte) align 1 %{{.*}}, ptr %{{.*}} // CHECK: [[REG_COUNT_PTR:%[^ ]+]] = getelementptr inbounds %struct.__va_list_tag, ptr %{{.*}}, i32 0, i32 0 // CHECK: [[REG_COUNT:%[^ ]+]] = load i64, ptr [[REG_COUNT_PTR]] // CHECK: [[FITS_IN_REGS:%[^ ]+]] = icmp ult i64 [[REG_COUNT]], 5 @@ -334,7 +334,7 @@ struct agg_1byte va_agg_1byte(__builtin_va_list l) { return __builtin_va_arg(l, // CHECK: ret void struct agg_2byte va_agg_2byte(__builtin_va_list l) { return __builtin_va_arg(l, struct agg_2byte); } -// CHECK-LABEL: define{{.*}} void @va_agg_2byte(ptr noalias sret(%struct.agg_2byte) align 1 %{{.*}}, ptr %{{.*}} +// CHECK-LABEL: define{{.*}} void @va_agg_2byte(ptr dead_on_unwind noalias writable sret(%struct.agg_2byte) align 1 %{{.*}}, ptr %{{.*}} // CHECK: [[REG_COUNT_PTR:%[^ ]+]] = getelementptr inbounds %struct.__va_list_tag, ptr %{{.*}}, i32 0, i32 0 // CHECK: [[REG_COUNT:%[^ ]+]] = load i64, ptr [[REG_COUNT_PTR]] // CHECK: [[FITS_IN_REGS:%[^ ]+]] = icmp ult i64 [[REG_COUNT]], 5 @@ -355,7 +355,7 @@ struct agg_2byte va_agg_2byte(__builtin_va_list l) { return __builtin_va_arg(l, // CHECK: ret void struct agg_3byte va_agg_3byte(__builtin_va_list l) { return __builtin_va_arg(l, struct agg_3byte); } -// CHECK-LABEL: define{{.*}} void @va_agg_3byte(ptr noalias sret(%struct.agg_3byte) align 1 %{{.*}}, ptr %{{.*}} +// CHECK-LABEL: define{{.*}} void @va_agg_3byte(ptr dead_on_unwind noalias writable sret(%struct.agg_3byte) align 1 %{{.*}}, ptr %{{.*}} // CHECK: [[REG_COUNT_PTR:%[^ ]+]] = getelementptr inbounds %struct.__va_list_tag, ptr %{{.*}}, i32 0, i32 0 // CHECK: [[REG_COUNT:%[^ ]+]] = load i64, ptr [[REG_COUNT_PTR]] // CHECK: [[FITS_IN_REGS:%[^ ]+]] = icmp ult i64 [[REG_COUNT]], 5 @@ -377,7 +377,7 @@ struct agg_3byte va_agg_3byte(__builtin_va_list l) { return __builtin_va_arg(l, // CHECK: ret void struct agg_4byte va_agg_4byte(__builtin_va_list l) { return __builtin_va_arg(l, struct agg_4byte); } -// CHECK-LABEL: define{{.*}} void @va_agg_4byte(ptr noalias sret(%struct.agg_4byte) align 1 %{{.*}}, ptr %{{.*}} +// CHECK-LABEL: define{{.*}} void @va_agg_4byte(ptr dead_on_unwind noalias writable sret(%struct.agg_4byte) align 1 %{{.*}}, ptr %{{.*}} // CHECK: [[REG_COUNT_PTR:%[^ ]+]] = getelementptr inbounds %struct.__va_list_tag, ptr %{{.*}}, i32 0, i32 0 // CHECK: [[REG_COUNT:%[^ ]+]] = load i64, ptr [[REG_COUNT_PTR]] // CHECK: [[FITS_IN_REGS:%[^ ]+]] = icmp ult i64 [[REG_COUNT]], 5 @@ -398,7 +398,7 @@ struct agg_4byte va_agg_4byte(__builtin_va_list l) { return __builtin_va_arg(l, // CHECK: ret void struct agg_8byte va_agg_8byte(__builtin_va_list l) { return __builtin_va_arg(l, struct agg_8byte); } -// CHECK-LABEL: define{{.*}} void @va_agg_8byte(ptr noalias sret(%struct.agg_8byte) align 1 %{{.*}}, ptr %{{.*}} +// CHECK-LABEL: define{{.*}} void @va_agg_8byte(ptr dead_on_unwind noalias writable sret(%struct.agg_8byte) align 1 %{{.*}}, ptr %{{.*}} // CHECK: [[REG_COUNT_PTR:%[^ ]+]] = getelementptr inbounds %struct.__va_list_tag, ptr %{{.*}}, i32 0, i32 0 // CHECK: [[REG_COUNT:%[^ ]+]] = load i64, ptr [[REG_COUNT_PTR]] // CHECK: [[FITS_IN_REGS:%[^ ]+]] = icmp ult i64 [[REG_COUNT]], 5 @@ -419,7 +419,7 @@ struct agg_8byte va_agg_8byte(__builtin_va_list l) { return __builtin_va_arg(l, // CHECK: ret void struct agg_float va_agg_float(__builtin_va_list l) { return __builtin_va_arg(l, struct agg_float); } -// CHECK-LABEL: define{{.*}} void @va_agg_float(ptr noalias sret(%struct.agg_float) align 4 %{{.*}}, ptr %{{.*}} +// CHECK-LABEL: define{{.*}} void @va_agg_float(ptr dead_on_unwind noalias writable sret(%struct.agg_float) align 4 %{{.*}}, ptr %{{.*}} // HARD-FLOAT: [[REG_COUNT_PTR:%[^ ]+]] = getelementptr inbounds %struct.__va_list_tag, ptr %{{.*}}, i32 0, i32 1 // SOFT-FLOAT: [[REG_COUNT_PTR:%[^ ]+]] = getelementptr inbounds %struct.__va_list_tag, ptr %{{.*}}, i32 0, i32 0 // CHECK: [[REG_COUNT:%[^ ]+]] = load i64, ptr [[REG_COUNT_PTR]] @@ -443,7 +443,7 @@ struct agg_float va_agg_float(__builtin_va_list l) { return __builtin_va_arg(l, // CHECK: ret void struct agg_double va_agg_double(__builtin_va_list l) { return __builtin_va_arg(l, struct agg_double); } -// CHECK-LABEL: define{{.*}} void @va_agg_double(ptr noalias sret(%struct.agg_double) align 8 %{{.*}}, ptr %{{.*}} +// CHECK-LABEL: define{{.*}} void @va_agg_double(ptr dead_on_unwind noalias writable sret(%struct.agg_double) align 8 %{{.*}}, ptr %{{.*}} // HARD-FLOAT: [[REG_COUNT_PTR:%[^ ]+]] = getelementptr inbounds %struct.__va_list_tag, ptr %{{.*}}, i32 0, i32 1 // SOFT-FLOAT: [[REG_COUNT_PTR:%[^ ]+]] = getelementptr inbounds %struct.__va_list_tag, ptr %{{.*}}, i32 0, i32 0 // CHECK: [[REG_COUNT:%[^ ]+]] = load i64, ptr [[REG_COUNT_PTR]] @@ -467,7 +467,7 @@ struct agg_double va_agg_double(__builtin_va_list l) { return __builtin_va_arg(l // CHECK: ret void struct agg_longdouble va_agg_longdouble(__builtin_va_list l) { return __builtin_va_arg(l, struct agg_longdouble); } -// CHECK-LABEL: define{{.*}} void @va_agg_longdouble(ptr noalias sret(%struct.agg_longdouble) align 8 %{{.*}}, ptr %{{.*}} +// CHECK-LABEL: define{{.*}} void @va_agg_longdouble(ptr dead_on_unwind noalias writable sret(%struct.agg_longdouble) align 8 %{{.*}}, ptr %{{.*}} // CHECK: [[REG_COUNT_PTR:%[^ ]+]] = getelementptr inbounds %struct.__va_list_tag, ptr %{{.*}}, i32 0, i32 0 // CHECK: [[REG_COUNT:%[^ ]+]] = load i64, ptr [[REG_COUNT_PTR]] // CHECK: [[FITS_IN_REGS:%[^ ]+]] = icmp ult i64 [[REG_COUNT]], 5 @@ -489,7 +489,7 @@ struct agg_longdouble va_agg_longdouble(__builtin_va_list l) { return __builtin_ // CHECK: ret void struct agg_float_a8 va_agg_float_a8(__builtin_va_list l) { return __builtin_va_arg(l, struct agg_float_a8); } -// CHECK-LABEL: define{{.*}} void @va_agg_float_a8(ptr noalias sret(%struct.agg_float_a8) align 8 %{{.*}}, ptr %{{.*}} +// CHECK-LABEL: define{{.*}} void @va_agg_float_a8(ptr dead_on_unwind noalias writable sret(%struct.agg_float_a8) align 8 %{{.*}}, ptr %{{.*}} // HARD-FLOAT: [[REG_COUNT_PTR:%[^ ]+]] = getelementptr inbounds %struct.__va_list_tag, ptr %{{.*}}, i32 0, i32 1 // SOFT-FLOAT: [[REG_COUNT_PTR:%[^ ]+]] = getelementptr inbounds %struct.__va_list_tag, ptr %{{.*}}, i32 0, i32 0 // CHECK: [[REG_COUNT:%[^ ]+]] = load i64, ptr [[REG_COUNT_PTR]] @@ -513,7 +513,7 @@ struct agg_float_a8 va_agg_float_a8(__builtin_va_list l) { return __builtin_va_a // CHECK: ret void struct agg_float_a16 va_agg_float_a16(__builtin_va_list l) { return __builtin_va_arg(l, struct agg_float_a16); } -// CHECK-LABEL: define{{.*}} void @va_agg_float_a16(ptr noalias sret(%struct.agg_float_a16) align 16 %{{.*}}, ptr %{{.*}} +// CHECK-LABEL: define{{.*}} void @va_agg_float_a16(ptr dead_on_unwind noalias writable sret(%struct.agg_float_a16) align 16 %{{.*}}, ptr %{{.*}} // CHECK: [[REG_COUNT_PTR:%[^ ]+]] = getelementptr inbounds %struct.__va_list_tag, ptr %{{.*}}, i32 0, i32 0 // CHECK: [[REG_COUNT:%[^ ]+]] = load i64, ptr [[REG_COUNT_PTR]] // CHECK: [[FITS_IN_REGS:%[^ ]+]] = icmp ult i64 [[REG_COUNT]], 5 @@ -535,7 +535,7 @@ struct agg_float_a16 va_agg_float_a16(__builtin_va_list l) { return __builtin_va // CHECK: ret void struct agg_nofloat1 va_agg_nofloat1(__builtin_va_list l) { return __builtin_va_arg(l, struct agg_nofloat1); } -// CHECK-LABEL: define{{.*}} void @va_agg_nofloat1(ptr noalias sret(%struct.agg_nofloat1) align 4 %{{.*}}, ptr %{{.*}} +// CHECK-LABEL: define{{.*}} void @va_agg_nofloat1(ptr dead_on_unwind noalias writable sret(%struct.agg_nofloat1) align 4 %{{.*}}, ptr %{{.*}} // CHECK: [[REG_COUNT_PTR:%[^ ]+]] = getelementptr inbounds %struct.__va_list_tag, ptr %{{.*}}, i32 0, i32 0 // CHECK: [[REG_COUNT:%[^ ]+]] = load i64, ptr [[REG_COUNT_PTR]] // CHECK: [[FITS_IN_REGS:%[^ ]+]] = icmp ult i64 [[REG_COUNT]], 5 @@ -556,7 +556,7 @@ struct agg_nofloat1 va_agg_nofloat1(__builtin_va_list l) { return __builtin_va_a // CHECK: ret void struct agg_nofloat2 va_agg_nofloat2(__builtin_va_list l) { return __builtin_va_arg(l, struct agg_nofloat2); } -// CHECK-LABEL: define{{.*}} void @va_agg_nofloat2(ptr noalias sret(%struct.agg_nofloat2) align 4 %{{.*}}, ptr %{{.*}} +// CHECK-LABEL: define{{.*}} void @va_agg_nofloat2(ptr dead_on_unwind noalias writable sret(%struct.agg_nofloat2) align 4 %{{.*}}, ptr %{{.*}} // CHECK: [[REG_COUNT_PTR:%[^ ]+]] = getelementptr inbounds %struct.__va_list_tag, ptr %{{.*}}, i32 0, i32 0 // CHECK: [[REG_COUNT:%[^ ]+]] = load i64, ptr [[REG_COUNT_PTR]] // CHECK: [[FITS_IN_REGS:%[^ ]+]] = icmp ult i64 [[REG_COUNT]], 5 @@ -577,7 +577,7 @@ struct agg_nofloat2 va_agg_nofloat2(__builtin_va_list l) { return __builtin_va_a // CHECK: ret void struct agg_nofloat3 va_agg_nofloat3(__builtin_va_list l) { return __builtin_va_arg(l, struct agg_nofloat3); } -// CHECK-LABEL: define{{.*}} void @va_agg_nofloat3(ptr noalias sret(%struct.agg_nofloat3) align 4 %{{.*}}, ptr %{{.*}} +// CHECK-LABEL: define{{.*}} void @va_agg_nofloat3(ptr dead_on_unwind noalias writable sret(%struct.agg_nofloat3) align 4 %{{.*}}, ptr %{{.*}} // CHECK: [[REG_COUNT_PTR:%[^ ]+]] = getelementptr inbounds %struct.__va_list_tag, ptr %{{.*}}, i32 0, i32 0 // CHECK: [[REG_COUNT:%[^ ]+]] = load i64, ptr [[REG_COUNT_PTR]] // CHECK: [[FITS_IN_REGS:%[^ ]+]] = icmp ult i64 [[REG_COUNT]], 5 diff --git a/clang/test/CodeGen/SystemZ/systemz-abi.cpp b/clang/test/CodeGen/SystemZ/systemz-abi.cpp index 08bf08c3803f49ed6fdcf2d16435d871b352d22d..06be85421ba17a76c7927e8d5f605034708251a7 100644 --- a/clang/test/CodeGen/SystemZ/systemz-abi.cpp +++ b/clang/test/CodeGen/SystemZ/systemz-abi.cpp @@ -6,20 +6,20 @@ class agg_float_class { float a; }; class agg_float_class pass_agg_float_class(class agg_float_class arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @_Z20pass_agg_float_class15agg_float_class(ptr noalias sret(%class.agg_float_class) align 4 %{{.*}}, float %{{.*}}) -// SOFT-FLOAT-LABEL: define{{.*}} void @_Z20pass_agg_float_class15agg_float_class(ptr noalias sret(%class.agg_float_class) align 4 %{{.*}}, i32 %{{.*}}) +// CHECK-LABEL: define{{.*}} void @_Z20pass_agg_float_class15agg_float_class(ptr dead_on_unwind noalias writable sret(%class.agg_float_class) align 4 %{{.*}}, float %{{.*}}) +// SOFT-FLOAT-LABEL: define{{.*}} void @_Z20pass_agg_float_class15agg_float_class(ptr dead_on_unwind noalias writable sret(%class.agg_float_class) align 4 %{{.*}}, i32 %{{.*}}) class agg_double_class { double a; }; class agg_double_class pass_agg_double_class(class agg_double_class arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @_Z21pass_agg_double_class16agg_double_class(ptr noalias sret(%class.agg_double_class) align 8 %{{.*}}, double %{{.*}}) -// SOFT-FLOAT-LABEL: define{{.*}} void @_Z21pass_agg_double_class16agg_double_class(ptr noalias sret(%class.agg_double_class) align 8 %{{.*}}, i64 %{{.*}}) +// CHECK-LABEL: define{{.*}} void @_Z21pass_agg_double_class16agg_double_class(ptr dead_on_unwind noalias writable sret(%class.agg_double_class) align 8 %{{.*}}, double %{{.*}}) +// SOFT-FLOAT-LABEL: define{{.*}} void @_Z21pass_agg_double_class16agg_double_class(ptr dead_on_unwind noalias writable sret(%class.agg_double_class) align 8 %{{.*}}, i64 %{{.*}}) // This structure is passed in a GPR in C++ (and C, checked in systemz-abi.c). struct agg_float_cpp { float a; int : 0; }; struct agg_float_cpp pass_agg_float_cpp(struct agg_float_cpp arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @_Z18pass_agg_float_cpp13agg_float_cpp(ptr noalias sret(%struct.agg_float_cpp) align 4 %{{.*}}, i32 %{{.*}}) -// SOFT-FLOAT-LABEL: define{{.*}} void @_Z18pass_agg_float_cpp13agg_float_cpp(ptr noalias sret(%struct.agg_float_cpp) align 4 %{{.*}}, i32 %{{.*}}) +// CHECK-LABEL: define{{.*}} void @_Z18pass_agg_float_cpp13agg_float_cpp(ptr dead_on_unwind noalias writable sret(%struct.agg_float_cpp) align 4 %{{.*}}, i32 %{{.*}}) +// SOFT-FLOAT-LABEL: define{{.*}} void @_Z18pass_agg_float_cpp13agg_float_cpp(ptr dead_on_unwind noalias writable sret(%struct.agg_float_cpp) align 4 %{{.*}}, i32 %{{.*}}) // A field member of empty class type in C++ makes the record nonhomogeneous, @@ -27,31 +27,31 @@ struct agg_float_cpp pass_agg_float_cpp(struct agg_float_cpp arg) { return arg; struct empty { }; struct agg_nofloat_empty { float a; empty dummy; }; struct agg_nofloat_empty pass_agg_nofloat_empty(struct agg_nofloat_empty arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @_Z22pass_agg_nofloat_empty17agg_nofloat_empty(ptr noalias sret(%struct.agg_nofloat_empty) align 4 %{{.*}}, i64 %{{.*}}) -// SOFT-FLOAT-LABEL: define{{.*}} void @_Z22pass_agg_nofloat_empty17agg_nofloat_empty(ptr noalias sret(%struct.agg_nofloat_empty) align 4 %{{.*}}, i64 %{{.*}}) +// CHECK-LABEL: define{{.*}} void @_Z22pass_agg_nofloat_empty17agg_nofloat_empty(ptr dead_on_unwind noalias writable sret(%struct.agg_nofloat_empty) align 4 %{{.*}}, i64 %{{.*}}) +// SOFT-FLOAT-LABEL: define{{.*}} void @_Z22pass_agg_nofloat_empty17agg_nofloat_empty(ptr dead_on_unwind noalias writable sret(%struct.agg_nofloat_empty) align 4 %{{.*}}, i64 %{{.*}}) struct agg_float_empty { float a; [[no_unique_address]] empty dummy; }; struct agg_float_empty pass_agg_float_empty(struct agg_float_empty arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @_Z20pass_agg_float_empty15agg_float_empty(ptr noalias sret(%struct.agg_float_empty) align 4 %{{.*}}, float %{{.*}}) -// SOFT-FLOAT-LABEL: define{{.*}} void @_Z20pass_agg_float_empty15agg_float_empty(ptr noalias sret(%struct.agg_float_empty) align 4 %{{.*}}, i32 %{{.*}}) +// CHECK-LABEL: define{{.*}} void @_Z20pass_agg_float_empty15agg_float_empty(ptr dead_on_unwind noalias writable sret(%struct.agg_float_empty) align 4 %{{.*}}, float %{{.*}}) +// SOFT-FLOAT-LABEL: define{{.*}} void @_Z20pass_agg_float_empty15agg_float_empty(ptr dead_on_unwind noalias writable sret(%struct.agg_float_empty) align 4 %{{.*}}, i32 %{{.*}}) struct agg_nofloat_emptyarray { float a; [[no_unique_address]] empty dummy[3]; }; struct agg_nofloat_emptyarray pass_agg_nofloat_emptyarray(struct agg_nofloat_emptyarray arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @_Z27pass_agg_nofloat_emptyarray22agg_nofloat_emptyarray(ptr noalias sret(%struct.agg_nofloat_emptyarray) align 4 %{{.*}}, i64 %{{.*}}) -// SOFT-FLOAT-LABEL: define{{.*}} void @_Z27pass_agg_nofloat_emptyarray22agg_nofloat_emptyarray(ptr noalias sret(%struct.agg_nofloat_emptyarray) align 4 %{{.*}}, i64 %{{.*}}) +// CHECK-LABEL: define{{.*}} void @_Z27pass_agg_nofloat_emptyarray22agg_nofloat_emptyarray(ptr dead_on_unwind noalias writable sret(%struct.agg_nofloat_emptyarray) align 4 %{{.*}}, i64 %{{.*}}) +// SOFT-FLOAT-LABEL: define{{.*}} void @_Z27pass_agg_nofloat_emptyarray22agg_nofloat_emptyarray(ptr dead_on_unwind noalias writable sret(%struct.agg_nofloat_emptyarray) align 4 %{{.*}}, i64 %{{.*}}) // And likewise for members of base classes. struct noemptybase { empty dummy; }; struct agg_nofloat_emptybase : noemptybase { float a; }; struct agg_nofloat_emptybase pass_agg_nofloat_emptybase(struct agg_nofloat_emptybase arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @_Z26pass_agg_nofloat_emptybase21agg_nofloat_emptybase(ptr noalias sret(%struct.agg_nofloat_emptybase) align 4 %{{.*}}, i64 %{{.*}}) -// SOFT-FLOAT-LABEL: define{{.*}} void @_Z26pass_agg_nofloat_emptybase21agg_nofloat_emptybase(ptr noalias sret(%struct.agg_nofloat_emptybase) align 4 %{{.*}}, i64 %{{.*}}) +// CHECK-LABEL: define{{.*}} void @_Z26pass_agg_nofloat_emptybase21agg_nofloat_emptybase(ptr dead_on_unwind noalias writable sret(%struct.agg_nofloat_emptybase) align 4 %{{.*}}, i64 %{{.*}}) +// SOFT-FLOAT-LABEL: define{{.*}} void @_Z26pass_agg_nofloat_emptybase21agg_nofloat_emptybase(ptr dead_on_unwind noalias writable sret(%struct.agg_nofloat_emptybase) align 4 %{{.*}}, i64 %{{.*}}) struct emptybase { [[no_unique_address]] empty dummy; }; struct agg_float_emptybase : emptybase { float a; }; struct agg_float_emptybase pass_agg_float_emptybase(struct agg_float_emptybase arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @_Z24pass_agg_float_emptybase19agg_float_emptybase(ptr noalias sret(%struct.agg_float_emptybase) align 4 %{{.*}}, float %{{.*}}) -// SOFT-FLOAT-LABEL: define{{.*}} void @_Z24pass_agg_float_emptybase19agg_float_emptybase(ptr noalias sret(%struct.agg_float_emptybase) align 4 %{{.*}}, i32 %{{.*}}) +// CHECK-LABEL: define{{.*}} void @_Z24pass_agg_float_emptybase19agg_float_emptybase(ptr dead_on_unwind noalias writable sret(%struct.agg_float_emptybase) align 4 %{{.*}}, float %{{.*}}) +// SOFT-FLOAT-LABEL: define{{.*}} void @_Z24pass_agg_float_emptybase19agg_float_emptybase(ptr dead_on_unwind noalias writable sret(%struct.agg_float_emptybase) align 4 %{{.*}}, i32 %{{.*}}) struct noemptybasearray { [[no_unique_address]] empty dummy[3]; }; struct agg_nofloat_emptybasearray : noemptybasearray { float a; }; struct agg_nofloat_emptybasearray pass_agg_nofloat_emptybasearray(struct agg_nofloat_emptybasearray arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @_Z31pass_agg_nofloat_emptybasearray26agg_nofloat_emptybasearray(ptr noalias sret(%struct.agg_nofloat_emptybasearray) align 4 %{{.*}}, i64 %{{.*}}) -// SOFT-FLOAT-LABEL: define{{.*}} void @_Z31pass_agg_nofloat_emptybasearray26agg_nofloat_emptybasearray(ptr noalias sret(%struct.agg_nofloat_emptybasearray) align 4 %{{.*}}, i64 %{{.*}}) +// CHECK-LABEL: define{{.*}} void @_Z31pass_agg_nofloat_emptybasearray26agg_nofloat_emptybasearray(ptr dead_on_unwind noalias writable sret(%struct.agg_nofloat_emptybasearray) align 4 %{{.*}}, i64 %{{.*}}) +// SOFT-FLOAT-LABEL: define{{.*}} void @_Z31pass_agg_nofloat_emptybasearray26agg_nofloat_emptybasearray(ptr dead_on_unwind noalias writable sret(%struct.agg_nofloat_emptybasearray) align 4 %{{.*}}, i64 %{{.*}}) diff --git a/clang/test/CodeGen/SystemZ/systemz-inline-asm.c b/clang/test/CodeGen/SystemZ/systemz-inline-asm.c index 0d614f8cbb905e451933c3bf72f1140747af914f..e38d37cd345e2613785dda6b2572826d69f52a39 100644 --- a/clang/test/CodeGen/SystemZ/systemz-inline-asm.c +++ b/clang/test/CodeGen/SystemZ/systemz-inline-asm.c @@ -123,7 +123,7 @@ double test_f64(double f, double g) { long double test_f128(long double f, long double g) { asm("axbr %0, %2" : "=f" (f) : "0" (f), "f" (g)); return f; -// CHECK: define{{.*}} void @test_f128(ptr noalias nocapture writeonly sret(fp128) align 8 [[DEST:%.*]], ptr nocapture noundef readonly %0, ptr nocapture noundef readonly %1) +// CHECK: define{{.*}} void @test_f128(ptr dead_on_unwind noalias nocapture writable writeonly sret(fp128) align 8 [[DEST:%.*]], ptr nocapture noundef readonly %0, ptr nocapture noundef readonly %1) // CHECK: %f = load fp128, ptr %0 // CHECK: %g = load fp128, ptr %1 // CHECK: [[RESULT:%.*]] = tail call fp128 asm "axbr $0, $2", "=f,0,f"(fp128 %f, fp128 %g) diff --git a/clang/test/CodeGen/WebAssembly/wasm-arguments.c b/clang/test/CodeGen/WebAssembly/wasm-arguments.c index 1b54b6401db0e95fa10222cf80feaf75b95bab53..a0914fc7688090872d68571e708eb22c7aea402a 100644 --- a/clang/test/CodeGen/WebAssembly/wasm-arguments.c +++ b/clang/test/CodeGen/WebAssembly/wasm-arguments.c @@ -25,9 +25,9 @@ typedef struct { void struct_arg(s1 i) {} // Structs should be returned sret and not simplified by the frontend. -// WEBASSEMBLY32: define void @struct_ret(ptr noalias sret(%struct.s1) align 4 %agg.result) +// WEBASSEMBLY32: define void @struct_ret(ptr dead_on_unwind noalias writable sret(%struct.s1) align 4 %agg.result) // WEBASSEMBLY32: ret void -// WEBASSEMBLY64: define void @struct_ret(ptr noalias sret(%struct.s1) align 4 %agg.result) +// WEBASSEMBLY64: define void @struct_ret(ptr dead_on_unwind noalias writable sret(%struct.s1) align 4 %agg.result) // WEBASSEMBLY64: ret void // Except with the experimental multivalue ABI, which returns structs by value @@ -103,9 +103,9 @@ union simple_union { void union_arg(union simple_union s) {} // Unions should be returned sret and not simplified by the frontend. -// WEBASSEMBLY32: define void @union_ret(ptr noalias sret(%union.simple_union) align 4 %agg.result) +// WEBASSEMBLY32: define void @union_ret(ptr dead_on_unwind noalias writable sret(%union.simple_union) align 4 %agg.result) // WEBASSEMBLY32: ret void -// WEBASSEMBLY64: define void @union_ret(ptr noalias sret(%union.simple_union) align 4 %agg.result) +// WEBASSEMBLY64: define void @union_ret(ptr dead_on_unwind noalias writable sret(%union.simple_union) align 4 %agg.result) // WEBASSEMBLY64: ret void // The experimental multivalue ABI returns them by value, though. @@ -129,8 +129,8 @@ typedef struct { void bitfield_arg(bitfield1 bf1) {} // And returned via sret pointers. -// WEBASSEMBLY32: define void @bitfield_ret(ptr noalias sret(%struct.bitfield1) align 4 %agg.result) -// WEBASSEMBLY64: define void @bitfield_ret(ptr noalias sret(%struct.bitfield1) align 4 %agg.result) +// WEBASSEMBLY32: define void @bitfield_ret(ptr dead_on_unwind noalias writable sret(%struct.bitfield1) align 4 %agg.result) +// WEBASSEMBLY64: define void @bitfield_ret(ptr dead_on_unwind noalias writable sret(%struct.bitfield1) align 4 %agg.result) // Except, of course, in the experimental multivalue ABI // EXPERIMENTAL-MV: define %struct.bitfield1 @bitfield_ret() diff --git a/clang/test/CodeGen/WebAssembly/wasm-varargs.c b/clang/test/CodeGen/WebAssembly/wasm-varargs.c index da22ad6a1b2e9b4d7f4babe4e8df74d7526ac8a4..c475de19ae4487830f9f8f76d2cea5906819fd35 100644 --- a/clang/test/CodeGen/WebAssembly/wasm-varargs.c +++ b/clang/test/CodeGen/WebAssembly/wasm-varargs.c @@ -68,7 +68,7 @@ struct S { }; // CHECK-LABEL: define {{[^@]+}}@test_struct -// CHECK-SAME: (ptr noalias sret([[STRUCT_S:%.*]]) align 4 [[AGG_RESULT:%.*]], ptr noundef [[FMT:%.*]], ...) #[[ATTR0]] { +// CHECK-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_S:%.*]]) align 4 [[AGG_RESULT:%.*]], ptr noundef [[FMT:%.*]], ...) #[[ATTR0]] { // CHECK-NEXT: entry: // CHECK-NEXT: [[FMT_ADDR:%.*]] = alloca ptr, align 4 // CHECK-NEXT: [[VA:%.*]] = alloca ptr, align 4 @@ -96,7 +96,7 @@ struct S test_struct(char *fmt, ...) { struct Z {}; // CHECK-LABEL: define {{[^@]+}}@test_empty_struct -// CHECK-SAME: (ptr noalias sret([[STRUCT_S:%.*]]) align 4 [[AGG_RESULT:%.*]], ptr noundef [[FMT:%.*]], ...) #[[ATTR0]] { +// CHECK-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_S:%.*]]) align 4 [[AGG_RESULT:%.*]], ptr noundef [[FMT:%.*]], ...) #[[ATTR0]] { // CHECK-NEXT: entry: // CHECK-NEXT: [[FMT_ADDR:%.*]] = alloca ptr, align 4 // CHECK-NEXT: [[VA:%.*]] = alloca ptr, align 4 diff --git a/clang/test/CodeGen/X86/avx512er-builtins.c b/clang/test/CodeGen/X86/avx512er-builtins.c index ee31236a3c01aa885458c8c5602fd6fe03f03389..11ec6aabec1e3f20eed06c2962adee8ec3f98393 100644 --- a/clang/test/CodeGen/X86/avx512er-builtins.c +++ b/clang/test/CodeGen/X86/avx512er-builtins.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +avx512f -target-feature +avx512er -emit-llvm -o - -Wall -Werror | FileCheck %s +// RUN: %clang_cc1 -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +avx512f -target-feature +avx512er -emit-llvm -o - -Wall | FileCheck %s #include diff --git a/clang/test/CodeGen/X86/avx512pf-builtins.c b/clang/test/CodeGen/X86/avx512pf-builtins.c index 4ca70f5787968b93b04567b36afa6a03bdfaa988..3a117ed6a9460e952305a82fb002af44f9b0a687 100644 --- a/clang/test/CodeGen/X86/avx512pf-builtins.c +++ b/clang/test/CodeGen/X86/avx512pf-builtins.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +avx512pf -emit-llvm -o - -Wall -Werror | FileCheck %s +// RUN: %clang_cc1 -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +avx512pf -emit-llvm -o - -Wall | FileCheck %s #include diff --git a/clang/test/CodeGen/X86/x86-inline-asm-v-constraint.c b/clang/test/CodeGen/X86/inline-asm-constraints.c similarity index 100% rename from clang/test/CodeGen/X86/x86-inline-asm-v-constraint.c rename to clang/test/CodeGen/X86/inline-asm-constraints.c diff --git a/clang/test/CodeGen/X86/x86_32-arguments-darwin.c b/clang/test/CodeGen/X86/x86_32-arguments-darwin.c index 69d1156acf7eb24ce668a15583f0c298ba5ee934..8eeba631157d07526f4a4afed8da4f3549abc5c2 100644 --- a/clang/test/CodeGen/X86/x86_32-arguments-darwin.c +++ b/clang/test/CodeGen/X86/x86_32-arguments-darwin.c @@ -71,7 +71,7 @@ struct s10 { // Small vectors and 1 x {i64,double} are returned in registers // CHECK: i32 @f11() -// CHECK: void @f12(ptr noalias sret(<2 x i32>) align 8 %agg.result) +// CHECK: void @f12(ptr dead_on_unwind noalias writable sret(<2 x i32>) align 8 %agg.result) // CHECK: i64 @f13() // CHECK: i64 @f14() // CHECK: <2 x i64> @f15() @@ -93,11 +93,11 @@ T16 f16(void) { while (1) {} } // 128-bits). // CHECK: i32 @f17() -// CHECK: void @f18(ptr noalias sret(%struct.anon.{{[0-9]+}}) align 8 %agg.result) -// CHECK: void @f19(ptr noalias sret(%struct.anon.{{[0-9]+}}) align 8 %agg.result) -// CHECK: void @f20(ptr noalias sret(%struct.anon.{{[0-9]+}}) align 8 %agg.result) -// CHECK: void @f21(ptr noalias sret(%struct.anon.{{[0-9]+}}) align 16 %agg.result) -// CHECK: void @f22(ptr noalias sret(%struct.anon.{{[0-9]+}}) align 16 %agg.result) +// CHECK: void @f18(ptr dead_on_unwind noalias writable sret(%struct.anon.{{[0-9]+}}) align 8 %agg.result) +// CHECK: void @f19(ptr dead_on_unwind noalias writable sret(%struct.anon.{{[0-9]+}}) align 8 %agg.result) +// CHECK: void @f20(ptr dead_on_unwind noalias writable sret(%struct.anon.{{[0-9]+}}) align 8 %agg.result) +// CHECK: void @f21(ptr dead_on_unwind noalias writable sret(%struct.anon.{{[0-9]+}}) align 16 %agg.result) +// CHECK: void @f22(ptr dead_on_unwind noalias writable sret(%struct.anon.{{[0-9]+}}) align 16 %agg.result) struct { T11 a; } f17(void) { while (1) {} } struct { T12 a; } f18(void) { while (1) {} } struct { T13 a; } f19(void) { while (1) {} } @@ -116,11 +116,11 @@ struct { struct {} a; struct { float a[1]; } b; } f25(void) { while (1) {} } // Small structures are handled recursively // CHECK: i32 @f26() -// CHECK: void @f27(ptr noalias sret(%struct.s27) align 1 %agg.result) +// CHECK: void @f27(ptr dead_on_unwind noalias writable sret(%struct.s27) align 1 %agg.result) struct s26 { struct { char a, b; } a; struct { char a, b; } b; } f26(void) { while (1) {} } struct s27 { struct { char a, b, c; } a; struct { char a; } b; } f27(void) { while (1) {} } -// CHECK: void @f28(ptr noalias sret(%struct.s28) align 4 %agg.result) +// CHECK: void @f28(ptr dead_on_unwind noalias writable sret(%struct.s28) align 4 %agg.result) struct s28 { int a; int b[]; } f28(void) { while (1) {} } // CHECK-LABEL: define{{.*}} i16 @f29() @@ -150,7 +150,7 @@ struct s36 { struct { int : 0; } a[2][10]; char b; char c; } f36(void) { while ( // CHECK-LABEL: define{{.*}} float @f37() struct s37 { float c[1][1]; } f37(void) { while (1) {} } -// CHECK-LABEL: define{{.*}} void @f38(ptr noalias sret(%struct.s38) align 2 %agg.result) +// CHECK-LABEL: define{{.*}} void @f38(ptr dead_on_unwind noalias writable sret(%struct.s38) align 2 %agg.result) struct s38 { char a[3]; short b; } f38(void) { while (1) {} } // CHECK-LABEL: define{{.*}} void @f39(ptr noundef byval(%struct.s39) align 16 %x) diff --git a/clang/test/CodeGen/X86/x86_32-arguments-iamcu.c b/clang/test/CodeGen/X86/x86_32-arguments-iamcu.c index c2b8f23ba5f33614b09507c09217fe382940ef66..2700bda1e7edf6c2645aa8c39710fd9beffcd4a0 100644 --- a/clang/test/CodeGen/X86/x86_32-arguments-iamcu.c +++ b/clang/test/CodeGen/X86/x86_32-arguments-iamcu.c @@ -58,7 +58,7 @@ st4_t retSmallStruct(st4_t r) { return r; } // CHECK-LABEL: define{{.*}} i64 @retPaddedStruct(i32 %r.coerce0, i32 %r.coerce1) st5_t retPaddedStruct(st5_t r) { return r; } -// CHECK-LABEL: define{{.*}} void @retLargeStruct(ptr noalias sret(%struct.st12_t) align 4 %agg.result, i32 noundef %i1, ptr noundef byval(%struct.st12_t) align 4 %r) +// CHECK-LABEL: define{{.*}} void @retLargeStruct(ptr dead_on_unwind noalias writable sret(%struct.st12_t) align 4 %agg.result, i32 noundef %i1, ptr noundef byval(%struct.st12_t) align 4 %r) st12_t retLargeStruct(int i1, st12_t r) { return r; } // CHECK-LABEL: define{{.*}} i32 @varArgs(i32 noundef %i1, ...) diff --git a/clang/test/CodeGen/X86/x86_64-arguments-nacl.c b/clang/test/CodeGen/X86/x86_64-arguments-nacl.c index 3f91ed1b1c461d34db0f9d734e0a3ca8516cc8bd..4d820aef8fd2df924afa05ac302afc971ace5393 100644 --- a/clang/test/CodeGen/X86/x86_64-arguments-nacl.c +++ b/clang/test/CodeGen/X86/x86_64-arguments-nacl.c @@ -61,7 +61,7 @@ void f12_1(struct s12 a0) {} // Check that sret parameter is accounted for when checking available integer // registers. -// CHECK: define{{.*}} void @f13(ptr noalias sret(%struct.s13_0) align 8 %agg.result, i32 noundef %a, i32 noundef %b, i32 noundef %c, i32 noundef %d, ptr noundef byval({{.*}}) align 8 %e, i32 noundef %f) +// CHECK: define{{.*}} void @f13(ptr dead_on_unwind noalias writable sret(%struct.s13_0) align 8 %agg.result, i32 noundef %a, i32 noundef %b, i32 noundef %c, i32 noundef %d, ptr noundef byval({{.*}}) align 8 %e, i32 noundef %f) struct s13_0 { long long f0[3]; }; struct s13_1 { long long f0[2]; }; diff --git a/clang/test/CodeGen/X86/x86_64-arguments-win32.c b/clang/test/CodeGen/X86/x86_64-arguments-win32.c index 31aa0546a3c864eaafa04023de8813cc191c8304..8768e73a854aa3858beb149c15cedbef808a9fb0 100644 --- a/clang/test/CodeGen/X86/x86_64-arguments-win32.c +++ b/clang/test/CodeGen/X86/x86_64-arguments-win32.c @@ -27,5 +27,5 @@ void f6(_Complex double a) {} // CHECK-LABEL: define dso_local i64 @f7() _Complex float f7(void) { return 1.0; } -// CHECK-LABEL: define dso_local void @f8(ptr noalias sret({ double, double }) align 8 %agg.result) +// CHECK-LABEL: define dso_local void @f8(ptr dead_on_unwind noalias writable sret({ double, double }) align 8 %agg.result) _Complex double f8(void) { return 1.0; } diff --git a/clang/test/CodeGen/X86/x86_64-arguments.c b/clang/test/CodeGen/X86/x86_64-arguments.c index b2c4283b5e6feb152c818cfc5e07eec2fae0f088..cf5636cfd518b64d095493aacfb694ed7e760a4c 100644 --- a/clang/test/CodeGen/X86/x86_64-arguments.c +++ b/clang/test/CodeGen/X86/x86_64-arguments.c @@ -47,7 +47,7 @@ void f7(e7 a0) { // Test merging/passing of upper eightbyte with X87 class. // -// CHECK-LABEL: define{{.*}} void @f8_1(ptr noalias sret(%union.u8) align 16 %agg.result) +// CHECK-LABEL: define{{.*}} void @f8_1(ptr dead_on_unwind noalias writable sret(%union.u8) align 16 %agg.result) // CHECK-LABEL: define{{.*}} void @f8_2(ptr noundef byval(%union.u8) align 16 %a0) union u8 { long double a; @@ -63,7 +63,7 @@ struct s9 { int a; int b; int : 0; } f9(void) { while (1) {} } struct s10 { int a; int b; int : 0; }; void f10(struct s10 a0) {} -// CHECK-LABEL: define{{.*}} void @f11(ptr noalias sret(%union.anon) align 16 %agg.result) +// CHECK-LABEL: define{{.*}} void @f11(ptr dead_on_unwind noalias writable sret(%union.anon) align 16 %agg.result) union { long double a; float b; } f11(void) { while (1) {} } // CHECK-LABEL: define{{.*}} i32 @f12_0() @@ -74,7 +74,7 @@ void f12_1(struct s12 a0) {} // Check that sret parameter is accounted for when checking available integer // registers. -// CHECK: define{{.*}} void @f13(ptr noalias sret(%struct.s13_0) align 8 %agg.result, i32 noundef %a, i32 noundef %b, i32 noundef %c, i32 noundef %d, ptr noundef byval({{.*}}) align 8 %e, i32 noundef %f) +// CHECK: define{{.*}} void @f13(ptr dead_on_unwind noalias writable sret(%struct.s13_0) align 8 %agg.result, i32 noundef %a, i32 noundef %b, i32 noundef %c, i32 noundef %d, ptr noundef byval({{.*}}) align 8 %e, i32 noundef %f) struct s13_0 { long long f0[3]; }; struct s13_1 { long long f0[2]; }; diff --git a/clang/test/CodeGen/aarch64-branch-protection-attr.c b/clang/test/CodeGen/aarch64-branch-protection-attr.c index 8ab3e17ade426466dbac8d6e8cfca4ca226a8dd1..f0e1dcccd1e8277f9ceb5bdb6cc4efc0e0658f7b 100644 --- a/clang/test/CodeGen/aarch64-branch-protection-attr.c +++ b/clang/test/CodeGen/aarch64-branch-protection-attr.c @@ -63,29 +63,33 @@ __attribute__ ((target("branch-protection=pac-ret+pc+bti"))) void pauthlr_bti() {} // CHECK: define{{.*}} void @pauthlr_bti() #[[#PAUTHLR_BTI:]] +__attribute__ ((target("branch-protection=gcs"))) +void gcs() {} +// CHECK: define{{.*}} void @gcs() #[[#GCS:]] -// CHECK-DAG: attributes #[[#NONE]] = { {{.*}} "branch-target-enforcement"="false" {{.*}} "sign-return-address"="none" +// CHECK-DAG: attributes #[[#NONE]] = { {{.*}} "branch-target-enforcement"="false" "guarded-control-stack"="false" {{.*}} "sign-return-address"="none" -// CHECK-DAG: attributes #[[#STD]] = { {{.*}} "branch-target-enforcement"="true" {{.*}} "sign-return-address"="non-leaf" "sign-return-address-key"="a_key" +// CHECK-DAG: attributes #[[#STD]] = { {{.*}} "branch-target-enforcement"="true" "guarded-control-stack"="true" {{.*}} "sign-return-address"="non-leaf" "sign-return-address-key"="a_key" -// CHECK-DAG: attributes #[[#BTI]] = { {{.*}} "branch-target-enforcement"="true" {{.*}} "sign-return-address"="none" +// CHECK-DAG: attributes #[[#BTI]] = { {{.*}} "branch-target-enforcement"="true" "guarded-control-stack"="false" {{.*}} "sign-return-address"="none" -// CHECK-DAG: attributes #[[#PAC]] = { {{.*}} "branch-target-enforcement"="false" {{.*}} "sign-return-address"="non-leaf" "sign-return-address-key"="a_key" +// CHECK-DAG: attributes #[[#PAC]] = { {{.*}} "branch-target-enforcement"="false" "guarded-control-stack"="false" {{.*}} "sign-return-address"="non-leaf" "sign-return-address-key"="a_key" -// CHECK-DAG: attributes #[[#PACLEAF]] = { {{.*}} "branch-target-enforcement"="false" {{.*}}"sign-return-address"="all" "sign-return-address-key"="a_key" +// CHECK-DAG: attributes #[[#PACLEAF]] = { {{.*}} "branch-target-enforcement"="false" "guarded-control-stack"="false" {{.*}}"sign-return-address"="all" "sign-return-address-key"="a_key" -// CHECK-DAG: attributes #[[#PACBKEY]] = { {{.*}}"branch-target-enforcement"="false" {{.*}} "sign-return-address"="non-leaf" "sign-return-address-key"="b_key" +// CHECK-DAG: attributes #[[#PACBKEY]] = { {{.*}}"branch-target-enforcement"="false" "guarded-control-stack"="false" {{.*}} "sign-return-address"="non-leaf" "sign-return-address-key"="b_key" -// CHECK-DAG: attributes #[[#PACBKEYLEAF]] = { {{.*}} "branch-target-enforcement"="false" {{.*}}"sign-return-address"="all" "sign-return-address-key"="b_key" +// CHECK-DAG: attributes #[[#PACBKEYLEAF]] = { {{.*}} "branch-target-enforcement"="false" "guarded-control-stack"="false" {{.*}}"sign-return-address"="all" "sign-return-address-key"="b_key" -// CHECK-DAG: attributes #[[#BTIPACLEAF]] = { {{.*}}"branch-target-enforcement"="true" {{.*}} "sign-return-address"="all" "sign-return-address-key"="a_key" +// CHECK-DAG: attributes #[[#BTIPACLEAF]] = { {{.*}}"branch-target-enforcement"="true" "guarded-control-stack"="false" {{.*}} "sign-return-address"="all" "sign-return-address-key"="a_key" -// CHECK-DAG: attributes #[[#PAUTHLR]] = { {{.*}}"branch-protection-pauth-lr"="true" {{.*}}"branch-target-enforcement"="false" {{.*}}"sign-return-address"="non-leaf" "sign-return-address-key"="a_key" +// CHECK-DAG: attributes #[[#PAUTHLR]] = { {{.*}}"branch-protection-pauth-lr"="true" {{.*}}"branch-target-enforcement"="false" "guarded-control-stack"="false" {{.*}}"sign-return-address"="non-leaf" "sign-return-address-key"="a_key" -// CHECK-DAG: attributes #[[#PAUTHLR_BKEY]] = { {{.*}}"branch-protection-pauth-lr"="true" {{.*}}"branch-target-enforcement"="false" {{.*}}"sign-return-address"="non-leaf" "sign-return-address-key"="b_key" +// CHECK-DAG: attributes #[[#PAUTHLR_BKEY]] = { {{.*}}"branch-protection-pauth-lr"="true" {{.*}}"branch-target-enforcement"="false" "guarded-control-stack"="false" {{.*}}"sign-return-address"="non-leaf" "sign-return-address-key"="b_key" -// CHECK-DAG: attributes #[[#PAUTHLR_LEAF]] = { {{.*}}"branch-protection-pauth-lr"="true" {{.*}}"branch-target-enforcement"="false" {{.*}}"sign-return-address"="all" "sign-return-address-key"="a_key" +// CHECK-DAG: attributes #[[#PAUTHLR_LEAF]] = { {{.*}}"branch-protection-pauth-lr"="true" {{.*}}"branch-target-enforcement"="false" "guarded-control-stack"="false" {{.*}}"sign-return-address"="all" "sign-return-address-key"="a_key" -// CHECK-DAG: attributes #[[#PAUTHLR_BTI]] = { {{.*}}"branch-protection-pauth-lr"="true" {{.*}}"branch-target-enforcement"="true" {{.*}}"sign-return-address"="non-leaf" "sign-return-address-key"="a_key" +// CHECK-DAG: attributes #[[#PAUTHLR_BTI]] = { {{.*}}"branch-protection-pauth-lr"="true" {{.*}}"branch-target-enforcement"="true" "guarded-control-stack"="false" {{.*}}"sign-return-address"="non-leaf" "sign-return-address-key"="a_key" +// CHECK-DAG: attributes #[[#GCS]] = { {{.*}}"branch-target-enforcement"="false" "guarded-control-stack"="true" {{.*}} "sign-return-address"="none" diff --git a/clang/test/CodeGen/aarch64-fix-cortex-a53-835769.c b/clang/test/CodeGen/aarch64-fix-cortex-a53-835769.c index 3d1a2c7aceb1f1ab633d3f59c9dd201565a0089b..e5d70564d57b304bb6d16a08d6c30cfff4deb9eb 100644 --- a/clang/test/CodeGen/aarch64-fix-cortex-a53-835769.c +++ b/clang/test/CodeGen/aarch64-fix-cortex-a53-835769.c @@ -5,13 +5,13 @@ // RUN: %clang -O3 -target aarch64-linux-eabi -mno-fix-cortex-a53-835769 %s -S -o- 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-NO --check-prefix=CHECK %s -// RUN: %clang -O3 -target aarch64-android-eabi %s -S -o- \ +// RUN: %clang -O3 --target=aarch64-linux-androideabi %s -S -o- \ // RUN: | FileCheck --check-prefix=CHECK-YES --check-prefix=CHECK %s // RUN: %clang -O3 -target aarch64-linux-ohos %s -S -o- \ // RUN: | FileCheck --check-prefix=CHECK-YES --check-prefix=CHECK %s -// RUN: %clang -O3 -target aarch64-android-eabi -mfix-cortex-a53-835769 %s -S -o- \ +// RUN: %clang -O3 --target=aarch64-linux-androideabi -mfix-cortex-a53-835769 %s -S -o- \ // RUN: | FileCheck --check-prefix=CHECK-YES --check-prefix=CHECK %s -// RUN: %clang -O3 -target aarch64-android-eabi -mno-fix-cortex-a53-835769 %s -S -o- \ +// RUN: %clang -O3 --target=aarch64-linux-androideabi -mno-fix-cortex-a53-835769 %s -S -o- \ // RUN: | FileCheck --check-prefix=CHECK-NO --check-prefix=CHECK %s // REQUIRES: aarch64-registered-target diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_cvt.c b/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_cvt.c index a3ee7d2092f79f4aa27d00e311456bc214b9a37e..f596b3167f2b82eed8e133dc4a3914c84e3ddc45 100644 --- a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_cvt.c +++ b/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_cvt.c @@ -59,7 +59,7 @@ svbfloat16_t test_cvt_bf16_x2(svfloat32x2_t zn) __arm_streaming { // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv8i32( [[ZN:%.*]], i64 0) // CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv8i32( [[ZN]], i64 4) -// CHECK-NEXT: [[TMP2:%.*]] = tail call { , } @llvm.aarch64.sve.fcvtu.x2.nxv4f32( [[TMP0]], [[TMP1]]) +// CHECK-NEXT: [[TMP2:%.*]] = tail call { , } @llvm.aarch64.sve.ucvtf.x2.nxv4f32( [[TMP0]], [[TMP1]]) // CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP2]], 0 // CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv8f32.nxv4f32( poison, [[TMP3]], i64 0) // CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , } [[TMP2]], 1 @@ -70,7 +70,7 @@ svbfloat16_t test_cvt_bf16_x2(svfloat32x2_t zn) __arm_streaming { // CPP-CHECK-NEXT: entry: // CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv8i32( [[ZN:%.*]], i64 0) // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv8i32( [[ZN]], i64 4) -// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call { , } @llvm.aarch64.sve.fcvtu.x2.nxv4f32( [[TMP0]], [[TMP1]]) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call { , } @llvm.aarch64.sve.ucvtf.x2.nxv4f32( [[TMP0]], [[TMP1]]) // CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP2]], 0 // CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv8f32.nxv4f32( poison, [[TMP3]], i64 0) // CPP-CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , } [[TMP2]], 1 @@ -85,7 +85,7 @@ svfloat32x2_t test_svcvt_f32_u32_x2(svuint32x2_t zn) __arm_streaming { // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv8i32( [[ZN:%.*]], i64 0) // CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv8i32( [[ZN]], i64 4) -// CHECK-NEXT: [[TMP2:%.*]] = tail call { , } @llvm.aarch64.sve.fcvts.x2.nxv4f32( [[TMP0]], [[TMP1]]) +// CHECK-NEXT: [[TMP2:%.*]] = tail call { , } @llvm.aarch64.sve.scvtf.x2.nxv4f32( [[TMP0]], [[TMP1]]) // CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP2]], 0 // CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv8f32.nxv4f32( poison, [[TMP3]], i64 0) // CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , } [[TMP2]], 1 @@ -96,7 +96,7 @@ svfloat32x2_t test_svcvt_f32_u32_x2(svuint32x2_t zn) __arm_streaming { // CPP-CHECK-NEXT: entry: // CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv8i32( [[ZN:%.*]], i64 0) // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv8i32( [[ZN]], i64 4) -// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call { , } @llvm.aarch64.sve.fcvts.x2.nxv4f32( [[TMP0]], [[TMP1]]) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call { , } @llvm.aarch64.sve.scvtf.x2.nxv4f32( [[TMP0]], [[TMP1]]) // CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP2]], 0 // CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv8f32.nxv4f32( poison, [[TMP3]], i64 0) // CPP-CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , } [[TMP2]], 1 @@ -111,7 +111,7 @@ svfloat32x2_t test_svcvt_f32_s32_x2(svint32x2_t zn) __arm_streaming { // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4f32.nxv8f32( [[ZN:%.*]], i64 0) // CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4f32.nxv8f32( [[ZN]], i64 4) -// CHECK-NEXT: [[TMP2:%.*]] = tail call { , } @llvm.aarch64.sve.ucvtf.x2.nxv4f32( [[TMP0]], [[TMP1]]) +// CHECK-NEXT: [[TMP2:%.*]] = tail call { , } @llvm.aarch64.sve.fcvtu.x2.nxv4f32( [[TMP0]], [[TMP1]]) // CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP2]], 0 // CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv8i32.nxv4i32( poison, [[TMP3]], i64 0) // CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , } [[TMP2]], 1 @@ -122,7 +122,7 @@ svfloat32x2_t test_svcvt_f32_s32_x2(svint32x2_t zn) __arm_streaming { // CPP-CHECK-NEXT: entry: // CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4f32.nxv8f32( [[ZN:%.*]], i64 0) // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4f32.nxv8f32( [[ZN]], i64 4) -// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call { , } @llvm.aarch64.sve.ucvtf.x2.nxv4f32( [[TMP0]], [[TMP1]]) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call { , } @llvm.aarch64.sve.fcvtu.x2.nxv4f32( [[TMP0]], [[TMP1]]) // CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP2]], 0 // CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv8i32.nxv4i32( poison, [[TMP3]], i64 0) // CPP-CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , } [[TMP2]], 1 @@ -137,7 +137,7 @@ svuint32x2_t test_svcvt_u32_f32_x2(svfloat32x2_t zn) __arm_streaming { // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4f32.nxv8f32( [[ZN:%.*]], i64 0) // CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4f32.nxv8f32( [[ZN]], i64 4) -// CHECK-NEXT: [[TMP2:%.*]] = tail call { , } @llvm.aarch64.sve.scvtf.x2.nxv4f32( [[TMP0]], [[TMP1]]) +// CHECK-NEXT: [[TMP2:%.*]] = tail call { , } @llvm.aarch64.sve.fcvts.x2.nxv4f32( [[TMP0]], [[TMP1]]) // CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP2]], 0 // CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv8i32.nxv4i32( poison, [[TMP3]], i64 0) // CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , } [[TMP2]], 1 @@ -148,7 +148,7 @@ svuint32x2_t test_svcvt_u32_f32_x2(svfloat32x2_t zn) __arm_streaming { // CPP-CHECK-NEXT: entry: // CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.vector.extract.nxv4f32.nxv8f32( [[ZN:%.*]], i64 0) // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4f32.nxv8f32( [[ZN]], i64 4) -// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call { , } @llvm.aarch64.sve.scvtf.x2.nxv4f32( [[TMP0]], [[TMP1]]) +// CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call { , } @llvm.aarch64.sve.fcvts.x2.nxv4f32( [[TMP0]], [[TMP1]]) // CPP-CHECK-NEXT: [[TMP3:%.*]] = extractvalue { , } [[TMP2]], 0 // CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call @llvm.vector.insert.nxv8i32.nxv4i32( poison, [[TMP3]], i64 0) // CPP-CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , } [[TMP2]], 1 @@ -166,7 +166,7 @@ svint32x2_t test_svcvt_s32_f32_x2(svfloat32x2_t zn) __arm_streaming { // CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 4) // CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 8) // CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 12) -// CHECK-NEXT: [[TMP4:%.*]] = tail call { , , , } @llvm.aarch64.sve.fcvtu.x4.nxv4f32( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) +// CHECK-NEXT: [[TMP4:%.*]] = tail call { , , , } @llvm.aarch64.sve.ucvtf.x4.nxv4f32( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) // CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP4]], 0 // CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv16f32.nxv4f32( poison, [[TMP5]], i64 0) // CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP4]], 1 @@ -183,7 +183,7 @@ svint32x2_t test_svcvt_s32_f32_x2(svfloat32x2_t zn) __arm_streaming { // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 4) // CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 8) // CPP-CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 12) -// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call { , , , } @llvm.aarch64.sve.fcvtu.x4.nxv4f32( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call { , , , } @llvm.aarch64.sve.ucvtf.x4.nxv4f32( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) // CPP-CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP4]], 0 // CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv16f32.nxv4f32( poison, [[TMP5]], i64 0) // CPP-CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP4]], 1 @@ -204,7 +204,7 @@ svfloat32x4_t test_svcvt_f32_u32_x4(svuint32x4_t zn) __arm_streaming { // CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 4) // CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 8) // CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 12) -// CHECK-NEXT: [[TMP4:%.*]] = tail call { , , , } @llvm.aarch64.sve.fcvts.x4.nxv4f32( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) +// CHECK-NEXT: [[TMP4:%.*]] = tail call { , , , } @llvm.aarch64.sve.scvtf.x4.nxv4f32( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) // CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP4]], 0 // CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv16f32.nxv4f32( poison, [[TMP5]], i64 0) // CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP4]], 1 @@ -221,7 +221,7 @@ svfloat32x4_t test_svcvt_f32_u32_x4(svuint32x4_t zn) __arm_streaming { // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 4) // CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 8) // CPP-CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv4i32.nxv16i32( [[ZN]], i64 12) -// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call { , , , } @llvm.aarch64.sve.fcvts.x4.nxv4f32( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call { , , , } @llvm.aarch64.sve.scvtf.x4.nxv4f32( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) // CPP-CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP4]], 0 // CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv16f32.nxv4f32( poison, [[TMP5]], i64 0) // CPP-CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP4]], 1 @@ -242,7 +242,7 @@ svfloat32x4_t test_svcvt_f32_s32_x4(svint32x4_t zn) __arm_streaming { // CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4f32.nxv16f32( [[ZN]], i64 4) // CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv4f32.nxv16f32( [[ZN]], i64 8) // CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv4f32.nxv16f32( [[ZN]], i64 12) -// CHECK-NEXT: [[TMP4:%.*]] = tail call { , , , } @llvm.aarch64.sve.ucvtf.x4.nxv4f32( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) +// CHECK-NEXT: [[TMP4:%.*]] = tail call { , , , } @llvm.aarch64.sve.fcvtu.x4.nxv4f32( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) // CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP4]], 0 // CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv16i32.nxv4i32( poison, [[TMP5]], i64 0) // CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP4]], 1 @@ -259,7 +259,7 @@ svfloat32x4_t test_svcvt_f32_s32_x4(svint32x4_t zn) __arm_streaming { // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4f32.nxv16f32( [[ZN]], i64 4) // CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv4f32.nxv16f32( [[ZN]], i64 8) // CPP-CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv4f32.nxv16f32( [[ZN]], i64 12) -// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call { , , , } @llvm.aarch64.sve.ucvtf.x4.nxv4f32( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call { , , , } @llvm.aarch64.sve.fcvtu.x4.nxv4f32( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) // CPP-CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP4]], 0 // CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv16i32.nxv4i32( poison, [[TMP5]], i64 0) // CPP-CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP4]], 1 @@ -280,7 +280,7 @@ svuint32x4_t test_svcvt_u32_f32_x4(svfloat32x4_t zn) __arm_streaming { // CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4f32.nxv16f32( [[ZN]], i64 4) // CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv4f32.nxv16f32( [[ZN]], i64 8) // CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv4f32.nxv16f32( [[ZN]], i64 12) -// CHECK-NEXT: [[TMP4:%.*]] = tail call { , , , } @llvm.aarch64.sve.scvtf.x4.nxv4f32( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) +// CHECK-NEXT: [[TMP4:%.*]] = tail call { , , , } @llvm.aarch64.sve.fcvts.x4.nxv4f32( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) // CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP4]], 0 // CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv16i32.nxv4i32( poison, [[TMP5]], i64 0) // CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP4]], 1 @@ -297,7 +297,7 @@ svuint32x4_t test_svcvt_u32_f32_x4(svfloat32x4_t zn) __arm_streaming { // CPP-CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.vector.extract.nxv4f32.nxv16f32( [[ZN]], i64 4) // CPP-CHECK-NEXT: [[TMP2:%.*]] = tail call @llvm.vector.extract.nxv4f32.nxv16f32( [[ZN]], i64 8) // CPP-CHECK-NEXT: [[TMP3:%.*]] = tail call @llvm.vector.extract.nxv4f32.nxv16f32( [[ZN]], i64 12) -// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call { , , , } @llvm.aarch64.sve.scvtf.x4.nxv4f32( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) +// CPP-CHECK-NEXT: [[TMP4:%.*]] = tail call { , , , } @llvm.aarch64.sve.fcvts.x4.nxv4f32( [[TMP0]], [[TMP1]], [[TMP2]], [[TMP3]]) // CPP-CHECK-NEXT: [[TMP5:%.*]] = extractvalue { , , , } [[TMP4]], 0 // CPP-CHECK-NEXT: [[TMP6:%.*]] = tail call @llvm.vector.insert.nxv16i32.nxv4i32( poison, [[TMP5]], i64 0) // CPP-CHECK-NEXT: [[TMP7:%.*]] = extractvalue { , , , } [[TMP4]], 1 diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_mla.c b/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_mla.c index f52edd9888daa93275f5893dc02f15450cc769bf..2679f9cc8dfd0cd17a09d1dde4da9f1e94a83120 100644 --- a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_mla.c +++ b/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_mla.c @@ -86,7 +86,7 @@ void test_svmla4_f32(uint32_t slice_base, svfloat32x4_t zn, svfloat32x4_t zm) __ // CPP-CHECK-NEXT: ret void // void test_svmla_single2_f32(uint32_t slice_base, svfloat32x2_t zn, svfloat32_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmla_single_za32,,_f32,,_vg1x2)(slice_base, zn, zm); + SVE_ACLE_FUNC(svmla,_single,_za32,_f32,_vg1x2)(slice_base, zn, zm); } // CHECK-LABEL: @test_svmla_single4_f32( @@ -108,7 +108,7 @@ void test_svmla_single2_f32(uint32_t slice_base, svfloat32x2_t zn, svfloat32_t z // CPP-CHECK-NEXT: ret void // void test_svmla_single4_f32(uint32_t slice_base, svfloat32x4_t zn, svfloat32_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmla_single_za32,,_f32,,_vg1x4)(slice_base, zn, zm); + SVE_ACLE_FUNC(svmla,_single,_za32,_f32,_vg1x4)(slice_base, zn, zm); } // @@ -224,7 +224,7 @@ void test_svmla4_f64(uint32_t slice_base, svfloat64x4_t zn, svfloat64x4_t zm) __ // CPP-CHECK-NEXT: ret void // void test_svmla_single2_f64(uint32_t slice_base, svfloat64x2_t zn, svfloat64_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmla_single_za64,,_f64,,_vg1x2)(slice_base, zn, zm); + SVE_ACLE_FUNC(svmla,_single,_za64,_f64,_vg1x2)(slice_base, zn, zm); } // CHECK-LABEL: @test_svmla_single4_f64( @@ -246,7 +246,7 @@ void test_svmla_single2_f64(uint32_t slice_base, svfloat64x2_t zn, svfloat64_t z // CPP-CHECK-NEXT: ret void // void test_svmla_single4_f64(uint32_t slice_base, svfloat64x4_t zn, svfloat64_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmla_single_za64,,_f64,,_vg1x4)(slice_base, zn, zm); + SVE_ACLE_FUNC(svmla,_single,_za64,_f64,_vg1x4)(slice_base, zn, zm); } // diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_mlal.c b/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_mlal.c index 834ade753507675b0ad28dd5cff0befe6614e4a2..032830512987af4dc8a5784cabc9e51519401401 100644 --- a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_mlal.c +++ b/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_mlal.c @@ -311,7 +311,7 @@ void test_svmla_single1_s16(uint32_t slice_base, svint16_t zn, svint16_t zm) __a // void test_svmla_single2_f16(uint32_t slice_base, svfloat16x2_t zn, svfloat16_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmla_single_za32,,_f16,,_vg2x2)(slice_base, zn, zm); + SVE_ACLE_FUNC(svmla,_single,_za32,_f16,_vg2x2)(slice_base, zn, zm); } // CHECK-LABEL: @test_svmla_single2_bf16( @@ -330,7 +330,7 @@ void test_svmla_single2_f16(uint32_t slice_base, svfloat16x2_t zn, svfloat16_t z // void test_svmla_single2_bf16(uint32_t slice_base, svbfloat16x2_t zn, svbfloat16_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmla_single_za32,,_bf16,,_vg2x2)(slice_base, zn, zm); + SVE_ACLE_FUNC(svmla,_single,_za32,_bf16,_vg2x2)(slice_base, zn, zm); } // CHECK-LABEL: @test_svmla_single2_u16( @@ -349,7 +349,7 @@ void test_svmla_single2_bf16(uint32_t slice_base, svbfloat16x2_t zn, svbfloat16_ // void test_svmla_single2_u16(uint32_t slice_base, svuint16x2_t zn, svuint16_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmla_single_za32,,_u16,,_vg2x2)(slice_base, zn, zm); + SVE_ACLE_FUNC(svmla,_single,_za32,_u16,_vg2x2)(slice_base, zn, zm); } // CHECK-LABEL: @test_svmla_single2_s16( @@ -368,7 +368,7 @@ void test_svmla_single2_u16(uint32_t slice_base, svuint16x2_t zn, svuint16_t zm) // void test_svmla_single2_s16(uint32_t slice_base, svint16x2_t zn, svint16_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmla_single_za32,,_s16,,_vg2x2)(slice_base, zn, zm); + SVE_ACLE_FUNC(svmla,_single,_za32,_s16,_vg2x2)(slice_base, zn, zm); } // CHECK-LABEL: @test_svmla_single4_f16( @@ -391,7 +391,7 @@ void test_svmla_single2_s16(uint32_t slice_base, svint16x2_t zn, svint16_t zm) _ // void test_svmla_single4_f16(uint32_t slice_base, svfloat16x4_t zn, svfloat16_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmla_single_za32,,_f16,,_vg2x4)(slice_base, zn, zm); + SVE_ACLE_FUNC(svmla,_single,_za32,_f16,_vg2x4)(slice_base, zn, zm); } // CHECK-LABEL: @test_svmla_single4_bf16( @@ -414,7 +414,7 @@ void test_svmla_single4_f16(uint32_t slice_base, svfloat16x4_t zn, svfloat16_t z // void test_svmla_single4_bf16(uint32_t slice_base, svbfloat16x4_t zn, svbfloat16_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmla_single_za32,,_bf16,,_vg2x4)(slice_base, zn, zm); + SVE_ACLE_FUNC(svmla,_single,_za32,_bf16,_vg2x4)(slice_base, zn, zm); } // CHECK-LABEL: @test_svmla_single4_u16( @@ -437,7 +437,7 @@ void test_svmla_single4_bf16(uint32_t slice_base, svbfloat16x4_t zn, svbfloat16_ // void test_svmla_single4_u16(uint32_t slice_base, svuint16x4_t zn, svuint16_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmla_single_za32,,_u16,,_vg2x4)(slice_base, zn, zm); + SVE_ACLE_FUNC(svmla,_single,_za32,_u16,_vg2x4)(slice_base, zn, zm); } // CHECK-LABEL: @test_svmla_single4_s16( @@ -460,7 +460,7 @@ void test_svmla_single4_u16(uint32_t slice_base, svuint16x4_t zn, svuint16_t zm) // void test_svmla_single4_s16(uint32_t slice_base, svint16x4_t zn, svint16_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmla_single_za32,,_s16,,_vg2x4)(slice_base, zn, zm); + SVE_ACLE_FUNC(svmla,_single,_za32,_s16,_vg2x4)(slice_base, zn, zm); } // @@ -479,7 +479,7 @@ void test_svmla_single4_s16(uint32_t slice_base, svint16x4_t zn, svint16_t zm) _ // void test_svmla_lane1_f16(uint32_t slice_base, svfloat16_t zn, svfloat16_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmla_lane_za32,,,_f16,_vg2x1)(slice_base, zn, zm, 7); + SVE_ACLE_FUNC(svmla_lane_za32,_f16,_vg2x1,,)(slice_base, zn, zm, 7); } // CHECK-LABEL: @test_svmla_lane1_bf16( @@ -494,7 +494,7 @@ void test_svmla_lane1_f16(uint32_t slice_base, svfloat16_t zn, svfloat16_t zm) _ // void test_svmla_lane1_bf16(uint32_t slice_base, svbfloat16_t zn, svbfloat16_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmla_lane_za32,,,_bf16,_vg2x1)(slice_base, zn, zm, 7); + SVE_ACLE_FUNC(svmla_lane_za32,_bf16,_vg2x1,,)(slice_base, zn, zm, 7); } // CHECK-LABEL: @test_svmla_lane1_u16( @@ -509,7 +509,7 @@ void test_svmla_lane1_bf16(uint32_t slice_base, svbfloat16_t zn, svbfloat16_t zm // void test_svmla_lane1_u16(uint32_t slice_base, svuint16_t zn, svuint16_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmla_lane_za32,,,_u16,_vg2x1)(slice_base, zn, zm, 7); + SVE_ACLE_FUNC(svmla_lane_za32,_u16,_vg2x1,,)(slice_base, zn, zm, 7); } // CHECK-LABEL: @test_svmla_lane1_s16( @@ -524,7 +524,7 @@ void test_svmla_lane1_u16(uint32_t slice_base, svuint16_t zn, svuint16_t zm) __a // void test_svmla_lane1_s16(uint32_t slice_base, svint16_t zn, svint16_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmla_lane_za32,,,_s16,_vg2x1)(slice_base, zn, zm, 7); + SVE_ACLE_FUNC(svmla_lane_za32,_s16,_vg2x1,,)(slice_base, zn, zm, 7); } // CHECK-LABEL: @test_svmla_lane2_f16( @@ -543,7 +543,7 @@ void test_svmla_lane1_s16(uint32_t slice_base, svint16_t zn, svint16_t zm) __arm // void test_svmla_lane2_f16(uint32_t slice_base, svfloat16x2_t zn, svfloat16_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmla_lane_za32,,,_f16,_vg2x2)(slice_base, zn, zm, 7); + SVE_ACLE_FUNC(svmla_lane_za32,_f16,_vg2x2,,)(slice_base, zn, zm, 7); } // CHECK-LABEL: @test_svmla_lane2_bf16( @@ -562,7 +562,7 @@ void test_svmla_lane2_f16(uint32_t slice_base, svfloat16x2_t zn, svfloat16_t zm) // void test_svmla_lane2_bf16(uint32_t slice_base, svbfloat16x2_t zn, svbfloat16_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmla_lane_za32,,,_bf16,_vg2x2)(slice_base, zn, zm, 7); + SVE_ACLE_FUNC(svmla_lane_za32,_bf16,_vg2x2,,)(slice_base, zn, zm, 7); } // CHECK-LABEL: @test_svmla_lane2_u16( @@ -581,7 +581,7 @@ void test_svmla_lane2_bf16(uint32_t slice_base, svbfloat16x2_t zn, svbfloat16_t // void test_svmla_lane2_u16(uint32_t slice_base, svuint16x2_t zn, svuint16_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmla_lane_za32,,,_u16,_vg2x2)(slice_base, zn, zm, 7); + SVE_ACLE_FUNC(svmla_lane_za32,_u16,_vg2x2,,)(slice_base, zn, zm, 7); } // CHECK-LABEL: @test_svmla_lane2_s16( @@ -600,7 +600,7 @@ void test_svmla_lane2_u16(uint32_t slice_base, svuint16x2_t zn, svuint16_t zm) _ // void test_svmla_lane2_s16(uint32_t slice_base, svint16x2_t zn, svint16_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmla_lane_za32,,,_s16,_vg2x2)(slice_base, zn, zm, 7); + SVE_ACLE_FUNC(svmla_lane_za32,_s16,_vg2x2,,)(slice_base, zn, zm, 7); } // CHECK-LABEL: @test_svmla_lane4_f16( @@ -623,7 +623,7 @@ void test_svmla_lane2_s16(uint32_t slice_base, svint16x2_t zn, svint16_t zm) __a // void test_svmla_lane4_f16(uint32_t slice_base, svfloat16x4_t zn, svfloat16_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmla_lane_za32,,,_f16,_vg2x4)(slice_base, zn, zm, 7); + SVE_ACLE_FUNC(svmla_lane_za32,_f16,_vg2x4,,)(slice_base, zn, zm, 7); } // CHECK-LABEL: @test_svmla_lane4_bf16( @@ -646,7 +646,7 @@ void test_svmla_lane4_f16(uint32_t slice_base, svfloat16x4_t zn, svfloat16_t zm) // void test_svmla_lane4_bf16(uint32_t slice_base, svbfloat16x4_t zn, svbfloat16_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmla_lane_za32,,,_bf16,_vg2x4)(slice_base, zn, zm, 7); + SVE_ACLE_FUNC(svmla_lane_za32,_bf16,_vg2x4,,)(slice_base, zn, zm, 7); } // CHECK-LABEL: @test_svmla_lane4_u16( @@ -669,7 +669,7 @@ void test_svmla_lane4_bf16(uint32_t slice_base, svbfloat16x4_t zn, svbfloat16_t // void test_svmla_lane4_u16(uint32_t slice_base, svuint16x4_t zn, svuint16_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmla_lane_za32,,,_u16,_vg2x4)(slice_base, zn, zm, 7); + SVE_ACLE_FUNC(svmla_lane_za32,_u16,_vg2x4,,)(slice_base, zn, zm, 7); } // CHECK-LABEL: @test_svmla_lane4_s16( @@ -692,5 +692,5 @@ void test_svmla_lane4_u16(uint32_t slice_base, svuint16x4_t zn, svuint16_t zm) _ // void test_svmla_lane4_s16(uint32_t slice_base, svint16x4_t zn, svint16_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmla_lane_za32,,,_s16,_vg2x4)(slice_base, zn, zm, 7); + SVE_ACLE_FUNC(svmla_lane_za32,_s16,_vg2x4,,)(slice_base, zn, zm, 7); } diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_mlall.c b/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_mlall.c index fceb16a482600d1f62a7b9f7fb1ae23b0d4869a8..44e715e9581b7cf7fd6010622bea6093617ce093 100644 --- a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_mlall.c +++ b/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_mlall.c @@ -199,7 +199,7 @@ void test_usmlall_single_x1_u8(uint32_t slice_base, svuint8_t zn, svint8_t zm) _ // void test_svmla_single_x2_s8(uint32_t slice_base, svint8x2_t zn, svint8_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmla_single_za32,,_s8,,_vg4x2)(slice_base, zn, zm); + SVE_ACLE_FUNC(svmla,_single,_za32,_s8,_vg4x2)(slice_base, zn, zm); } // CHECK-LABEL: @test_svmla_single_x2_s16( @@ -218,7 +218,7 @@ void test_svmla_single_x2_s8(uint32_t slice_base, svint8x2_t zn, svint8_t zm) __ // void test_svmla_single_x2_s16(uint32_t slice_base, svint16x2_t zn, svint16_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmla_single_za64,,_s16,,_vg4x2)(slice_base, zn, zm); + SVE_ACLE_FUNC(svmla,_single,_za64,_s16,_vg4x2)(slice_base, zn, zm); } // CHECK-LABEL: @test_svmla_single_x2_u8( @@ -237,7 +237,7 @@ void test_svmla_single_x2_s16(uint32_t slice_base, svint16x2_t zn, svint16_t zm) // void test_svmla_single_x2_u8(uint32_t slice_base, svuint8x2_t zn, svuint8_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmla_single_za32,,_u8,,_vg4x2)(slice_base, zn, zm); + SVE_ACLE_FUNC(svmla,_single,_za32,_u8,_vg4x2)(slice_base, zn, zm); } // CHECK-LABEL: @test_svmla_single_x2_u16( @@ -256,7 +256,7 @@ void test_svmla_single_x2_u8(uint32_t slice_base, svuint8x2_t zn, svuint8_t zm) // void test_svmla_single_x2_u16(uint32_t slice_base, svuint16x2_t zn, svuint16_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmla_single_za64,,_u16,,_vg4x2)(slice_base, zn, zm); + SVE_ACLE_FUNC(svmla,_single,_za64,_u16,_vg4x2)(slice_base, zn, zm); } // MLSL @@ -277,7 +277,7 @@ void test_svmla_single_x2_u16(uint32_t slice_base, svuint16x2_t zn, svuint16_t z // void test_svmls_single_x2_s8(uint32_t slice_base, svint8x2_t zn, svint8_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmls_single_za32,,_s8,,_vg4x2)(slice_base, zn, zm); + SVE_ACLE_FUNC(svmls,_single,_za32,_s8,_vg4x2)(slice_base, zn, zm); } // CHECK-LABEL: @test_svmls_single_x2_s16( @@ -296,7 +296,7 @@ void test_svmls_single_x2_s8(uint32_t slice_base, svint8x2_t zn, svint8_t zm) __ // void test_svmls_single_x2_s16(uint32_t slice_base, svint16x2_t zn, svint16_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmls_single_za64,,_s16,,_vg4x2)(slice_base, zn, zm); + SVE_ACLE_FUNC(svmls,_single,_za64,_s16,_vg4x2)(slice_base, zn, zm); } // CHECK-LABEL: @test_svmls_single_x2_u8( @@ -315,7 +315,7 @@ void test_svmls_single_x2_s16(uint32_t slice_base, svint16x2_t zn, svint16_t zm) // void test_svmls_single_x2_u8(uint32_t slice_base, svuint8x2_t zn, svuint8_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmls_single_za32,,_u8,,_vg4x2)(slice_base, zn, zm); + SVE_ACLE_FUNC(svmls,_single,_za32,_u8,_vg4x2)(slice_base, zn, zm); } // CHECK-LABEL: @test_svmls_single_x2_u16( @@ -334,7 +334,7 @@ void test_svmls_single_x2_u8(uint32_t slice_base, svuint8x2_t zn, svuint8_t zm) // void test_svmls_single_x2_u16(uint32_t slice_base, svuint16x2_t zn, svuint16_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmls_single_za64,,_u16,,_vg4x2)(slice_base, zn, zm); + SVE_ACLE_FUNC(svmls,_single,_za64,_u16,_vg4x2)(slice_base, zn, zm); } // SUMLALL @@ -355,7 +355,7 @@ void test_svmls_single_x2_u16(uint32_t slice_base, svuint16x2_t zn, svuint16_t z // void test_svsumla_single_x2_s8(uint32_t slice_base, svint8x2_t zn, svuint8_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svsumla_single_za32,,_s8,,_vg4x2)(slice_base, zn, zm); + SVE_ACLE_FUNC(svsumla,_single,_za32,_s8,_vg4x2)(slice_base, zn, zm); } // USMLALL @@ -376,7 +376,7 @@ void test_svsumla_single_x2_s8(uint32_t slice_base, svint8x2_t zn, svuint8_t zm) // void test_usmlall_single_x2_u8(uint32_t slice_base, svuint8x2_t zn, svint8_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svusmla_single_za32,,_u8,,_vg4x2)(slice_base, zn, zm); + SVE_ACLE_FUNC(svusmla,_single,_za32,_u8,_vg4x2)(slice_base, zn, zm); } // @@ -405,7 +405,7 @@ void test_usmlall_single_x2_u8(uint32_t slice_base, svuint8x2_t zn, svint8_t zm) // void test_svmla_single_x4_s8(uint32_t slice_base, svint8x4_t zn, svint8_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmla_single_za32,,_s8,,_vg4x4)(slice_base, zn, zm); + SVE_ACLE_FUNC(svmla,_single,_za32,_s8,_vg4x4)(slice_base, zn, zm); } // CHECK-LABEL: @test_svmla_single_x4_s16( @@ -428,7 +428,7 @@ void test_svmla_single_x4_s8(uint32_t slice_base, svint8x4_t zn, svint8_t zm) __ // void test_svmla_single_x4_s16(uint32_t slice_base, svint16x4_t zn, svint16_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmla_single_za64,,_s16,,_vg4x4)(slice_base, zn, zm); + SVE_ACLE_FUNC(svmla,_single,_za64,_s16,_vg4x4)(slice_base, zn, zm); } // CHECK-LABEL: @test_svmla_single_x4_u8( @@ -451,7 +451,7 @@ void test_svmla_single_x4_s16(uint32_t slice_base, svint16x4_t zn, svint16_t zm) // void test_svmla_single_x4_u8(uint32_t slice_base, svuint8x4_t zn, svuint8_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmla_single_za32,,_u8,,_vg4x4)(slice_base, zn, zm); + SVE_ACLE_FUNC(svmla,_single,_za32,_u8,_vg4x4)(slice_base, zn, zm); } // CHECK-LABEL: @test_svmla_single_x4_u16( @@ -474,7 +474,7 @@ void test_svmla_single_x4_u8(uint32_t slice_base, svuint8x4_t zn, svuint8_t zm) // void test_svmla_single_x4_u16(uint32_t slice_base, svuint16x4_t zn, svuint16_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmla_single_za64,,_u16,,_vg4x4)(slice_base, zn, zm); + SVE_ACLE_FUNC(svmla,_single,_za64,_u16,_vg4x4)(slice_base, zn, zm); } // MLSL @@ -499,7 +499,7 @@ void test_svmla_single_x4_u16(uint32_t slice_base, svuint16x4_t zn, svuint16_t z // void test_svmls_single_x4_s8(uint32_t slice_base, svint8x4_t zn, svint8_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmls_single_za32,,_s8,,_vg4x4)(slice_base, zn, zm); + SVE_ACLE_FUNC(svmls,_single,_za32,_s8,_vg4x4)(slice_base, zn, zm); } // CHECK-LABEL: @test_svmls_single_x4_s16( @@ -522,7 +522,7 @@ void test_svmls_single_x4_s8(uint32_t slice_base, svint8x4_t zn, svint8_t zm) __ // void test_svmls_single_x4_s16(uint32_t slice_base, svint16x4_t zn, svint16_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmls_single_za64,,_s16,,_vg4x4)(slice_base, zn, zm); + SVE_ACLE_FUNC(svmls,_single,_za64,_s16,_vg4x4)(slice_base, zn, zm); } // CHECK-LABEL: @test_svmls_single_x4_u8( @@ -545,7 +545,7 @@ void test_svmls_single_x4_s16(uint32_t slice_base, svint16x4_t zn, svint16_t zm) // void test_svmls_single_x4_u8(uint32_t slice_base, svuint8x4_t zn, svuint8_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmls_single_za32,,_u8,,_vg4x4)(slice_base, zn, zm); + SVE_ACLE_FUNC(svmls,_single,_za32,_u8,_vg4x4)(slice_base, zn, zm); } // CHECK-LABEL: @test_svmls_single_x4_u16( @@ -568,7 +568,7 @@ void test_svmls_single_x4_u8(uint32_t slice_base, svuint8x4_t zn, svuint8_t zm) // void test_svmls_single_x4_u16(uint32_t slice_base, svuint16x4_t zn, svuint16_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmls_single_za64,,_u16,,_vg4x4)(slice_base, zn, zm); + SVE_ACLE_FUNC(svmls,_single,_za64,_u16,_vg4x4)(slice_base, zn, zm); } // SUMLALL @@ -593,7 +593,7 @@ void test_svmls_single_x4_u16(uint32_t slice_base, svuint16x4_t zn, svuint16_t z // void test_svsumla_single_x4_s8(uint32_t slice_base, svint8x4_t zn, svuint8_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svsumla_single_za32,,_s8,,_vg4x4)(slice_base, zn, zm); + SVE_ACLE_FUNC(svsumla,_single,_za32,_s8,_vg4x4)(slice_base, zn, zm); } // USMLALL @@ -618,7 +618,7 @@ void test_svsumla_single_x4_s8(uint32_t slice_base, svint8x4_t zn, svuint8_t zm) // void test_usmlall_single_x4_u8(uint32_t slice_base, svuint8x4_t zn, svint8_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svusmla_single_za32,,_u8,,_vg4x4)(slice_base, zn, zm); + SVE_ACLE_FUNC(svusmla,_single,_za32,_u8,_vg4x4)(slice_base, zn, zm); } // diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_mls.c b/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_mls.c index 6830a399e91d6478b1895a3d9190ff4b9969e315..fd4bf390b8232e878c5f25d77293c19942b747f7 100644 --- a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_mls.c +++ b/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_mls.c @@ -36,7 +36,7 @@ // CPP-CHECK-NEXT: ret void // void test_svmls2_f32(uint32_t slice_base, svfloat32x2_t zn, svfloat32x2_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmls_za32,,_f32,,_vg1x2)(slice_base, zn, zm); + SVE_ACLE_FUNC(svmls_za32,_f32,_vg1x2,,)(slice_base, zn, zm); } // CHECK-LABEL: @test_svmls4_f32( @@ -66,7 +66,7 @@ void test_svmls2_f32(uint32_t slice_base, svfloat32x2_t zn, svfloat32x2_t zm) __ // CPP-CHECK-NEXT: ret void // void test_svmls4_f32(uint32_t slice_base, svfloat32x4_t zn, svfloat32x4_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmls_za32,,_f32,,_vg1x4)(slice_base, zn, zm); + SVE_ACLE_FUNC(svmls_za32,_f32,_vg1x4,,)(slice_base, zn, zm); } // @@ -86,7 +86,7 @@ void test_svmls4_f32(uint32_t slice_base, svfloat32x4_t zn, svfloat32x4_t zm) __ // CPP-CHECK-NEXT: ret void // void test_svmls_single2_f32(uint32_t slice_base, svfloat32x2_t zn, svfloat32_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmls_single_za32,,_f32,,_vg1x2)(slice_base, zn, zm); + SVE_ACLE_FUNC(svmls,_single,_za32,_f32,_vg1x2)(slice_base, zn, zm); } // CHECK-LABEL: @test_svmls_single4_f32( @@ -108,7 +108,7 @@ void test_svmls_single2_f32(uint32_t slice_base, svfloat32x2_t zn, svfloat32_t z // CPP-CHECK-NEXT: ret void // void test_svmls_single4_f32(uint32_t slice_base, svfloat32x4_t zn, svfloat32_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmls_single_za32,,_f32,,_vg1x4)(slice_base, zn, zm); + SVE_ACLE_FUNC(svmls,_single,_za32,_f32,_vg1x4)(slice_base, zn, zm); } // @@ -128,7 +128,7 @@ void test_svmls_single4_f32(uint32_t slice_base, svfloat32x4_t zn, svfloat32_t z // CPP-CHECK-NEXT: ret void // void test_svmls_lane2_f32(uint32_t slice_base, svfloat32x2_t zn, svfloat32_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmls_lane_za32,,_f32,,_vg1x2)(slice_base, zn, zm, 3); + SVE_ACLE_FUNC(svmls_lane_za32,_f32,_vg1x2,,)(slice_base, zn, zm, 3); } // CHECK-LABEL: @test_svmls_lane4_f32( @@ -150,7 +150,7 @@ void test_svmls_lane2_f32(uint32_t slice_base, svfloat32x2_t zn, svfloat32_t zm) // CPP-CHECK-NEXT: ret void // void test_svmls_lane4_f32(uint32_t slice_base, svfloat32x4_t zn, svfloat32_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmls_lane_za32,,_f32,,_vg1x4)(slice_base, zn, zm, 3); + SVE_ACLE_FUNC(svmls_lane_za32,_f32,_vg1x4,,)(slice_base, zn, zm, 3); } // @@ -174,7 +174,7 @@ void test_svmls_lane4_f32(uint32_t slice_base, svfloat32x4_t zn, svfloat32_t zm) // CPP-CHECK-NEXT: ret void // void test_svmls2_f64(uint32_t slice_base, svfloat64x2_t zn, svfloat64x2_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmls_za64,,_f64,,_vg1x2)(slice_base, zn, zm); + SVE_ACLE_FUNC(svmls_za64,_f64,_vg1x2,,)(slice_base, zn, zm); } // CHECK-LABEL: @test_svmls4_f64( @@ -204,7 +204,7 @@ void test_svmls2_f64(uint32_t slice_base, svfloat64x2_t zn, svfloat64x2_t zm) __ // CPP-CHECK-NEXT: ret void // void test_svmls4_f64(uint32_t slice_base, svfloat64x4_t zn, svfloat64x4_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmls_za64,,_f64,,_vg1x4)(slice_base, zn, zm); + SVE_ACLE_FUNC(svmls_za64,_f64,_vg1x4,,)(slice_base, zn, zm); } // @@ -224,7 +224,7 @@ void test_svmls4_f64(uint32_t slice_base, svfloat64x4_t zn, svfloat64x4_t zm) __ // CPP-CHECK-NEXT: ret void // void test_svmls_single2_f64(uint32_t slice_base, svfloat64x2_t zn, svfloat64_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmls_single_za64,,_f64,,_vg1x2)(slice_base, zn, zm); + SVE_ACLE_FUNC(svmls,_single,_za64,_f64,_vg1x2)(slice_base, zn, zm); } // CHECK-LABEL: @test_svmls_single4_f64( @@ -246,7 +246,7 @@ void test_svmls_single2_f64(uint32_t slice_base, svfloat64x2_t zn, svfloat64_t z // CPP-CHECK-NEXT: ret void // void test_svmls_single4_f64(uint32_t slice_base, svfloat64x4_t zn, svfloat64_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmls_single_za64,,_f64,,_vg1x4)(slice_base, zn, zm); + SVE_ACLE_FUNC(svmls,_single,_za64,_f64,_vg1x4)(slice_base, zn, zm); } // @@ -266,7 +266,7 @@ void test_svmls_single4_f64(uint32_t slice_base, svfloat64x4_t zn, svfloat64_t z // CPP-CHECK-NEXT: ret void // void test_svmls_lane2_f64(uint32_t slice_base, svfloat64x2_t zn, svfloat64_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmls_lane_za64,,_f64,,_vg1x2)(slice_base, zn, zm, 1); + SVE_ACLE_FUNC(svmls_lane_za64,_f64,_vg1x2,,)(slice_base, zn, zm, 1); } // CHECK-LABEL: @test_svmls_lane4_f64( @@ -288,5 +288,5 @@ void test_svmls_lane2_f64(uint32_t slice_base, svfloat64x2_t zn, svfloat64_t zm) // CPP-CHECK-NEXT: ret void // void test_svmls_lane4_f64(uint32_t slice_base, svfloat64x4_t zn, svfloat64_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmls_lane_za64,,_f64,,_vg1x4)(slice_base, zn, zm, 1); + SVE_ACLE_FUNC(svmls_lane_za64,_f64,_vg1x4,,)(slice_base, zn, zm, 1); } diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_mlsl.c b/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_mlsl.c index 0a87d97f649c90ea0a74be0197eadadbc8c7b3f0..afc7db797c9dfcee74e053eb23eb4c32ce9a1772 100644 --- a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_mlsl.c +++ b/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_mlsl.c @@ -311,7 +311,7 @@ void test_svmls_single1_s16(uint32_t slice_base, svint16_t zn, svint16_t zm) __a // void test_svmls_single2_f16(uint32_t slice_base, svfloat16x2_t zn, svfloat16_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmls_single_za32,,_f16,,_vg2x2)(slice_base, zn, zm); + SVE_ACLE_FUNC(svmls,_single,_za32,_f16,_vg2x2)(slice_base, zn, zm); } // CHECK-LABEL: @test_svmls_single2_bf16( @@ -330,7 +330,7 @@ void test_svmls_single2_f16(uint32_t slice_base, svfloat16x2_t zn, svfloat16_t z // void test_svmls_single2_bf16(uint32_t slice_base, svbfloat16x2_t zn, svbfloat16_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmls_single_za32,,_bf16,,_vg2x2)(slice_base, zn, zm); + SVE_ACLE_FUNC(svmls,_single,_za32,_bf16,_vg2x2)(slice_base, zn, zm); } // CHECK-LABEL: @test_svmls_single2_u16( @@ -349,7 +349,7 @@ void test_svmls_single2_bf16(uint32_t slice_base, svbfloat16x2_t zn, svbfloat16_ // void test_svmls_single2_u16(uint32_t slice_base, svuint16x2_t zn, svuint16_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmls_single_za32,,_u16,,_vg2x2)(slice_base, zn, zm); + SVE_ACLE_FUNC(svmls,_single,_za32,_u16,_vg2x2)(slice_base, zn, zm); } // CHECK-LABEL: @test_svmls_single2_s16( @@ -368,7 +368,7 @@ void test_svmls_single2_u16(uint32_t slice_base, svuint16x2_t zn, svuint16_t zm) // void test_svmls_single2_s16(uint32_t slice_base, svint16x2_t zn, svint16_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmls_single_za32,,_s16,,_vg2x2)(slice_base, zn, zm); + SVE_ACLE_FUNC(svmls,_single,_za32,_s16,_vg2x2)(slice_base, zn, zm); } // CHECK-LABEL: @test_svmls_single4_f16( @@ -391,7 +391,7 @@ void test_svmls_single2_s16(uint32_t slice_base, svint16x2_t zn, svint16_t zm) _ // void test_svmls_single4_f16(uint32_t slice_base, svfloat16x4_t zn, svfloat16_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmls_single_za32,,_f16,,_vg2x4)(slice_base, zn, zm); + SVE_ACLE_FUNC(svmls,_single,_za32,_f16,_vg2x4)(slice_base, zn, zm); } // CHECK-LABEL: @test_svmls_single4_bf16( @@ -414,7 +414,7 @@ void test_svmls_single4_f16(uint32_t slice_base, svfloat16x4_t zn, svfloat16_t z // void test_svmls_single4_bf16(uint32_t slice_base, svbfloat16x4_t zn, svbfloat16_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmls_single_za32,,_bf16,,_vg2x4)(slice_base, zn, zm); + SVE_ACLE_FUNC(svmls,_single,_za32,_bf16,_vg2x4)(slice_base, zn, zm); } // CHECK-LABEL: @test_svmls_single4_u16( @@ -437,7 +437,7 @@ void test_svmls_single4_bf16(uint32_t slice_base, svbfloat16x4_t zn, svbfloat16_ // void test_svmls_single4_u16(uint32_t slice_base, svuint16x4_t zn, svuint16_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmls_single_za32,,_u16,,_vg2x4)(slice_base, zn, zm); + SVE_ACLE_FUNC(svmls,_single,_za32,_u16,_vg2x4)(slice_base, zn, zm); } // CHECK-LABEL: @test_svmls_single4_s16( @@ -460,7 +460,7 @@ void test_svmls_single4_u16(uint32_t slice_base, svuint16x4_t zn, svuint16_t zm) // void test_svmls_single4_s16(uint32_t slice_base, svint16x4_t zn, svint16_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmls_single_za32,,_s16,,_vg2x4)(slice_base, zn, zm); + SVE_ACLE_FUNC(svmls,_single,_za32,_s16,_vg2x4)(slice_base, zn, zm); } // @@ -479,7 +479,7 @@ void test_svmls_single4_s16(uint32_t slice_base, svint16x4_t zn, svint16_t zm) _ // void test_svmls_lane1_f16(uint32_t slice_base, svfloat16_t zn, svfloat16_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmls_lane_za32,,_f16,,_vg2x1)(slice_base, zn, zm, 7); + SVE_ACLE_FUNC(svmls_lane_za32,_f16,_vg2x1,,)(slice_base, zn, zm, 7); } // CHECK-LABEL: @test_svmls_lane1_bf16( @@ -494,7 +494,7 @@ void test_svmls_lane1_f16(uint32_t slice_base, svfloat16_t zn, svfloat16_t zm) _ // void test_svmls_lane1_bf16(uint32_t slice_base, svbfloat16_t zn, svbfloat16_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmls_lane_za32,,_bf16,,_vg2x1)(slice_base, zn, zm, 7); + SVE_ACLE_FUNC(svmls_lane_za32,_bf16,_vg2x1,,)(slice_base, zn, zm, 7); } // CHECK-LABEL: @test_svmls_lane1_u16( @@ -509,7 +509,7 @@ void test_svmls_lane1_bf16(uint32_t slice_base, svbfloat16_t zn, svbfloat16_t zm // void test_svmls_lane1_u16(uint32_t slice_base, svuint16_t zn, svuint16_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmls_lane_za32,,_u16,,_vg2x1)(slice_base, zn, zm, 7); + SVE_ACLE_FUNC(svmls_lane_za32,_u16,_vg2x1,,)(slice_base, zn, zm, 7); } // CHECK-LABEL: @test_svmls_lane1_s16( @@ -524,7 +524,7 @@ void test_svmls_lane1_u16(uint32_t slice_base, svuint16_t zn, svuint16_t zm) __a // void test_svmls_lane1_s16(uint32_t slice_base, svint16_t zn, svint16_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmls_lane_za32,,_s16,,_vg2x1)(slice_base, zn, zm, 7); + SVE_ACLE_FUNC(svmls_lane_za32,_s16,_vg2x1,,)(slice_base, zn, zm, 7); } // CHECK-LABEL: @test_svmls_lane2_f16( @@ -543,7 +543,7 @@ void test_svmls_lane1_s16(uint32_t slice_base, svint16_t zn, svint16_t zm) __arm // void test_svmls_lane2_f16(uint32_t slice_base, svfloat16x2_t zn, svfloat16_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmls_lane_za32,,_f16,,_vg2x2)(slice_base, zn, zm, 7); + SVE_ACLE_FUNC(svmls_lane_za32,_f16,_vg2x2,,)(slice_base, zn, zm, 7); } // CHECK-LABEL: @test_svmls_lane2_bf16( @@ -562,7 +562,7 @@ void test_svmls_lane2_f16(uint32_t slice_base, svfloat16x2_t zn, svfloat16_t zm) // void test_svmls_lane2_bf16(uint32_t slice_base, svbfloat16x2_t zn, svbfloat16_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmls_lane_za32,,_bf16,,_vg2x2)(slice_base, zn, zm, 7); + SVE_ACLE_FUNC(svmls_lane_za32,_bf16,_vg2x2,,)(slice_base, zn, zm, 7); } // CHECK-LABEL: @test_svmls_lane2_u16( @@ -581,7 +581,7 @@ void test_svmls_lane2_bf16(uint32_t slice_base, svbfloat16x2_t zn, svbfloat16_t // void test_svmls_lane2_u16(uint32_t slice_base, svuint16x2_t zn, svuint16_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmls_lane_za32,,_u16,,_vg2x2)(slice_base, zn, zm, 7); + SVE_ACLE_FUNC(svmls_lane_za32,_u16,_vg2x2,,)(slice_base, zn, zm, 7); } // CHECK-LABEL: @test_svmls_lane2_s16( @@ -600,7 +600,7 @@ void test_svmls_lane2_u16(uint32_t slice_base, svuint16x2_t zn, svuint16_t zm) _ // void test_svmls_lane2_s16(uint32_t slice_base, svint16x2_t zn, svint16_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmls_lane_za32,,_s16,,_vg2x2)(slice_base, zn, zm, 7); + SVE_ACLE_FUNC(svmls_lane_za32,_s16,_vg2x2,,)(slice_base, zn, zm, 7); } // CHECK-LABEL: @test_svmls_lane4_f16( @@ -623,7 +623,7 @@ void test_svmls_lane2_s16(uint32_t slice_base, svint16x2_t zn, svint16_t zm) __a // void test_svmls_lane4_f16(uint32_t slice_base, svfloat16x4_t zn, svfloat16_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmls_lane_za32,,_f16,,_vg2x4)(slice_base, zn, zm, 7); + SVE_ACLE_FUNC(svmls_lane_za32,_f16,_vg2x4,,)(slice_base, zn, zm, 7); } // CHECK-LABEL: @test_svmls_lane4_bf16( @@ -646,7 +646,7 @@ void test_svmls_lane4_f16(uint32_t slice_base, svfloat16x4_t zn, svfloat16_t zm) // void test_svmls_lane4_bf16(uint32_t slice_base, svbfloat16x4_t zn, svbfloat16_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmls_lane_za32,,_bf16,,_vg2x4)(slice_base, zn, zm, 7); + SVE_ACLE_FUNC(svmls_lane_za32,_bf16,_vg2x4,,)(slice_base, zn, zm, 7); } // CHECK-LABEL: @test_svmls_lane4_u16( @@ -669,7 +669,7 @@ void test_svmls_lane4_bf16(uint32_t slice_base, svbfloat16x4_t zn, svbfloat16_t // void test_svmls_lane4_u16(uint32_t slice_base, svuint16x4_t zn, svuint16_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmls_lane_za32,,_u16,,_vg2x4)(slice_base, zn, zm, 7); + SVE_ACLE_FUNC(svmls_lane_za32,_u16,_vg2x4,,)(slice_base, zn, zm, 7); } // CHECK-LABEL: @test_svmls_lane4_s16( @@ -692,5 +692,5 @@ void test_svmls_lane4_u16(uint32_t slice_base, svuint16x4_t zn, svuint16_t zm) _ // void test_svmls_lane4_s16(uint32_t slice_base, svint16x4_t zn, svint16_t zm) __arm_streaming __arm_shared_za { - SVE_ACLE_FUNC(svmls_lane_za32,,_s16,,_vg2x4)(slice_base, zn, zm, 7); + SVE_ACLE_FUNC(svmls_lane_za32,_s16,_vg2x4,,)(slice_base, zn, zm, 7); } diff --git a/clang/test/CodeGen/aarch64-sve-acle-__ARM_FEATURE_SVE_VECTOR_OPERATORS.c b/clang/test/CodeGen/aarch64-sve-acle-__ARM_FEATURE_SVE_VECTOR_OPERATORS.c index 9c96dfb9e33eeba498af3ee128493b528b4663ac..1e6a4500cc886c9010a893bda2f7727c1676e9a1 100644 --- a/clang/test/CodeGen/aarch64-sve-acle-__ARM_FEATURE_SVE_VECTOR_OPERATORS.c +++ b/clang/test/CodeGen/aarch64-sve-acle-__ARM_FEATURE_SVE_VECTOR_OPERATORS.c @@ -59,7 +59,7 @@ typedef int8_t vec_int8 __attribute__((vector_size(N / 8))); // CHECK128-NEXT: ret <16 x i8> [[CASTFIXEDSVE]] // CHECK-LABEL: define{{.*}} void @f2( -// CHECK-SAME: ptr noalias nocapture writeonly sret(<[[#div(VBITS,8)]] x i8>) align 16 %agg.result, ptr nocapture noundef readonly %0) +// CHECK-SAME: ptr dead_on_unwind noalias nocapture writable writeonly sret(<[[#div(VBITS,8)]] x i8>) align 16 %agg.result, ptr nocapture noundef readonly %0) // CHECK-NEXT: entry: // CHECK-NEXT: [[X:%.*]] = load <[[#div(VBITS,8)]] x i8>, ptr [[TMP0:%.*]], align 16, [[TBAA6:!tbaa !.*]] // CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.ptrue.nxv16i1(i32 31) diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_dot.c b/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_dot.c index d01b59114d54299b4d4ce5baa1b430221d3b5753..035ba244f9441e8a963d70615e8a967305e53d11 100644 --- a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_dot.c +++ b/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_dot.c @@ -26,7 +26,7 @@ // svint32_t test_svdot_s32_x2(svint32_t op1, svint16_t op2, svint16_t op3) { - return SVE_ACLE_FUNC(svdot,_s32_s16_s16,)(op1, op2, op3); + return SVE_ACLE_FUNC(svdot,_s32_s16,)(op1, op2, op3); } // CHECK-LABEL: @test_svdot_u32_x2( @@ -41,7 +41,7 @@ svint32_t test_svdot_s32_x2(svint32_t op1, svint16_t op2, svint16_t op3) // svuint32_t test_svdot_u32_x2(svuint32_t op1, svuint16_t op2, svuint16_t op3) { - return SVE_ACLE_FUNC(svdot,_u32_u16_u16,)(op1, op2, op3); + return SVE_ACLE_FUNC(svdot,_u32_u16,)(op1, op2, op3); } // CHECK-LABEL: @test_svdot_f32_x2( @@ -56,7 +56,7 @@ svuint32_t test_svdot_u32_x2(svuint32_t op1, svuint16_t op2, svuint16_t op3) // svfloat32_t test_svdot_f32_x2(svfloat32_t op1, svfloat16_t op2, svfloat16_t op3) { - return SVE_ACLE_FUNC(svdot,_f32_f16_f16,)(op1, op2, op3); + return SVE_ACLE_FUNC(svdot,_f32_f16,)(op1, op2, op3); } @@ -73,7 +73,7 @@ svfloat32_t test_svdot_f32_x2(svfloat32_t op1, svfloat16_t op2, svfloat16_t op3) // svint32_t test_svdot_lane_s32_x2(svint32_t op1, svint16_t op2, svint16_t op3) { - return SVE_ACLE_FUNC(svdot_lane,_s32_s16_s16,)(op1, op2, op3, 3); + return SVE_ACLE_FUNC(svdot_lane,_s32_s16,)(op1, op2, op3, 3); } // CHECK-LABEL: @test_svdot_lane_u32_x2( @@ -88,7 +88,7 @@ svint32_t test_svdot_lane_s32_x2(svint32_t op1, svint16_t op2, svint16_t op3) // svuint32_t test_svdot_lane_u32_x2(svuint32_t op1, svuint16_t op2, svuint16_t op3) { - return SVE_ACLE_FUNC(svdot_lane,_u32_u16_u16,)(op1, op2, op3, 3); + return SVE_ACLE_FUNC(svdot_lane,_u32_u16,)(op1, op2, op3, 3); } // CHECK-LABEL: @test_svdot_lane_f32_x2( @@ -103,5 +103,5 @@ svuint32_t test_svdot_lane_u32_x2(svuint32_t op1, svuint16_t op2, svuint16_t op3 // svfloat32_t test_svdot_lane_f32_x2(svfloat32_t op1, svfloat16_t op2, svfloat16_t op3) { - return SVE_ACLE_FUNC(svdot_lane,_f32_f16_f16,)(op1, op2, op3, 3); + return SVE_ACLE_FUNC(svdot_lane,_f32_f16,)(op1, op2, op3, 3); } diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_extq.c b/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_extq.c index 7704db5667a2a7f667c06804c3346e278746328e..738b290b76cf59a1ca02511876c416ae1bff5946 100644 --- a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_extq.c +++ b/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_extq.c @@ -20,194 +20,194 @@ #define SVE_ACLE_FUNC(A1, A2, A3, A4) A1##A2##A3##A4 #endif -// CHECK-LABEL: define dso_local @test_svextq_lane_u8 +// CHECK-LABEL: define dso_local @test_svextq_u8 // CHECK-SAME: ( [[ZN:%.*]], [[ZM:%.*]]) #[[ATTR0:[0-9]+]] { // CHECK-NEXT: entry: -// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.extq.lane.nxv16i8( [[ZN]], [[ZM]], i32 0) +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.extq.nxv16i8( [[ZN]], [[ZM]], i32 0) // CHECK-NEXT: ret [[TMP0]] // -// CPP-CHECK-LABEL: define dso_local @_Z19test_svextq_lane_u8u11__SVUint8_tS_ +// CPP-CHECK-LABEL: define dso_local @_Z14test_svextq_u8u11__SVUint8_tS_ // CPP-CHECK-SAME: ( [[ZN:%.*]], [[ZM:%.*]]) #[[ATTR0:[0-9]+]] { // CPP-CHECK-NEXT: entry: -// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.extq.lane.nxv16i8( [[ZN]], [[ZM]], i32 0) +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.extq.nxv16i8( [[ZN]], [[ZM]], i32 0) // CPP-CHECK-NEXT: ret [[TMP0]] // -svuint8_t test_svextq_lane_u8(svuint8_t zn, svuint8_t zm) { - return SVE_ACLE_FUNC(svextq_lane, _u8,,)(zn, zm, 0); +svuint8_t test_svextq_u8(svuint8_t zn, svuint8_t zm) { + return SVE_ACLE_FUNC(svextq, _u8,,)(zn, zm, 0); } -// CHECK-LABEL: define dso_local @test_svextq_lane_s8 +// CHECK-LABEL: define dso_local @test_svextq_s8 // CHECK-SAME: ( [[ZN:%.*]], [[ZM:%.*]]) #[[ATTR0]] { // CHECK-NEXT: entry: -// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.extq.lane.nxv16i8( [[ZN]], [[ZM]], i32 4) +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.extq.nxv16i8( [[ZN]], [[ZM]], i32 4) // CHECK-NEXT: ret [[TMP0]] // -// CPP-CHECK-LABEL: define dso_local @_Z19test_svextq_lane_s8u10__SVInt8_tS_ +// CPP-CHECK-LABEL: define dso_local @_Z14test_svextq_s8u10__SVInt8_tS_ // CPP-CHECK-SAME: ( [[ZN:%.*]], [[ZM:%.*]]) #[[ATTR0]] { // CPP-CHECK-NEXT: entry: -// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.extq.lane.nxv16i8( [[ZN]], [[ZM]], i32 4) +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.extq.nxv16i8( [[ZN]], [[ZM]], i32 4) // CPP-CHECK-NEXT: ret [[TMP0]] // -svint8_t test_svextq_lane_s8(svint8_t zn, svint8_t zm) { - return SVE_ACLE_FUNC(svextq_lane, _s8,,)(zn, zm, 4); +svint8_t test_svextq_s8(svint8_t zn, svint8_t zm) { + return SVE_ACLE_FUNC(svextq, _s8,,)(zn, zm, 4); } -// CHECK-LABEL: define dso_local @test_svextq_lane_u16 +// CHECK-LABEL: define dso_local @test_svextq_u16 // CHECK-SAME: ( [[ZN:%.*]], [[ZM:%.*]]) #[[ATTR0]] { // CHECK-NEXT: entry: -// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.extq.lane.nxv8i16( [[ZN]], [[ZM]], i32 1) +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.extq.nxv8i16( [[ZN]], [[ZM]], i32 1) // CHECK-NEXT: ret [[TMP0]] // -// CPP-CHECK-LABEL: define dso_local @_Z20test_svextq_lane_u16u12__SVUint16_tS_ +// CPP-CHECK-LABEL: define dso_local @_Z15test_svextq_u16u12__SVUint16_tS_ // CPP-CHECK-SAME: ( [[ZN:%.*]], [[ZM:%.*]]) #[[ATTR0]] { // CPP-CHECK-NEXT: entry: -// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.extq.lane.nxv8i16( [[ZN]], [[ZM]], i32 1) +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.extq.nxv8i16( [[ZN]], [[ZM]], i32 1) // CPP-CHECK-NEXT: ret [[TMP0]] // -svuint16_t test_svextq_lane_u16(svuint16_t zn, svuint16_t zm) { - return SVE_ACLE_FUNC(svextq_lane, _u16,,)(zn, zm, 1); +svuint16_t test_svextq_u16(svuint16_t zn, svuint16_t zm) { + return SVE_ACLE_FUNC(svextq, _u16,,)(zn, zm, 1); } -// CHECK-LABEL: define dso_local @test_svextq_lane_s16 +// CHECK-LABEL: define dso_local @test_svextq_s16 // CHECK-SAME: ( [[ZN:%.*]], [[ZM:%.*]]) #[[ATTR0]] { // CHECK-NEXT: entry: -// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.extq.lane.nxv8i16( [[ZN]], [[ZM]], i32 5) +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.extq.nxv8i16( [[ZN]], [[ZM]], i32 5) // CHECK-NEXT: ret [[TMP0]] // -// CPP-CHECK-LABEL: define dso_local @_Z20test_svextq_lane_s16u11__SVInt16_tS_ +// CPP-CHECK-LABEL: define dso_local @_Z15test_svextq_s16u11__SVInt16_tS_ // CPP-CHECK-SAME: ( [[ZN:%.*]], [[ZM:%.*]]) #[[ATTR0]] { // CPP-CHECK-NEXT: entry: -// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.extq.lane.nxv8i16( [[ZN]], [[ZM]], i32 5) +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.extq.nxv8i16( [[ZN]], [[ZM]], i32 5) // CPP-CHECK-NEXT: ret [[TMP0]] // -svint16_t test_svextq_lane_s16(svint16_t zn, svint16_t zm) { - return SVE_ACLE_FUNC(svextq_lane, _s16,,)(zn, zm, 5); +svint16_t test_svextq_s16(svint16_t zn, svint16_t zm) { + return SVE_ACLE_FUNC(svextq, _s16,,)(zn, zm, 5); } -// CHECK-LABEL: define dso_local @test_svextq_lane_u32 +// CHECK-LABEL: define dso_local @test_svextq_u32 // CHECK-SAME: ( [[ZN:%.*]], [[ZM:%.*]]) #[[ATTR0]] { // CHECK-NEXT: entry: -// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.extq.lane.nxv4i32( [[ZN]], [[ZM]], i32 2) +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.extq.nxv4i32( [[ZN]], [[ZM]], i32 2) // CHECK-NEXT: ret [[TMP0]] // -// CPP-CHECK-LABEL: define dso_local @_Z20test_svextq_lane_u32u12__SVUint32_tS_ +// CPP-CHECK-LABEL: define dso_local @_Z15test_svextq_u32u12__SVUint32_tS_ // CPP-CHECK-SAME: ( [[ZN:%.*]], [[ZM:%.*]]) #[[ATTR0]] { // CPP-CHECK-NEXT: entry: -// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.extq.lane.nxv4i32( [[ZN]], [[ZM]], i32 2) +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.extq.nxv4i32( [[ZN]], [[ZM]], i32 2) // CPP-CHECK-NEXT: ret [[TMP0]] // -svuint32_t test_svextq_lane_u32(svuint32_t zn, svuint32_t zm) { - return SVE_ACLE_FUNC(svextq_lane, _u32,,)(zn, zm, 2); +svuint32_t test_svextq_u32(svuint32_t zn, svuint32_t zm) { + return SVE_ACLE_FUNC(svextq, _u32,,)(zn, zm, 2); } -// CHECK-LABEL: define dso_local @test_svextq_lane_s32 +// CHECK-LABEL: define dso_local @test_svextq_s32 // CHECK-SAME: ( [[ZN:%.*]], [[ZM:%.*]]) #[[ATTR0]] { // CHECK-NEXT: entry: -// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.extq.lane.nxv4i32( [[ZN]], [[ZM]], i32 6) +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.extq.nxv4i32( [[ZN]], [[ZM]], i32 6) // CHECK-NEXT: ret [[TMP0]] // -// CPP-CHECK-LABEL: define dso_local @_Z20test_svextq_lane_s32u11__SVInt32_tS_ +// CPP-CHECK-LABEL: define dso_local @_Z15test_svextq_s32u11__SVInt32_tS_ // CPP-CHECK-SAME: ( [[ZN:%.*]], [[ZM:%.*]]) #[[ATTR0]] { // CPP-CHECK-NEXT: entry: -// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.extq.lane.nxv4i32( [[ZN]], [[ZM]], i32 6) +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.extq.nxv4i32( [[ZN]], [[ZM]], i32 6) // CPP-CHECK-NEXT: ret [[TMP0]] // -svint32_t test_svextq_lane_s32(svint32_t zn, svint32_t zm) { - return SVE_ACLE_FUNC(svextq_lane, _s32,,)(zn, zm, 6); +svint32_t test_svextq_s32(svint32_t zn, svint32_t zm) { + return SVE_ACLE_FUNC(svextq, _s32,,)(zn, zm, 6); } -// CHECK-LABEL: define dso_local @test_svextq_lane_u64 +// CHECK-LABEL: define dso_local @test_svextq_u64 // CHECK-SAME: ( [[ZN:%.*]], [[ZM:%.*]]) #[[ATTR0]] { // CHECK-NEXT: entry: -// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.extq.lane.nxv2i64( [[ZN]], [[ZM]], i32 3) +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.extq.nxv2i64( [[ZN]], [[ZM]], i32 3) // CHECK-NEXT: ret [[TMP0]] // -// CPP-CHECK-LABEL: define dso_local @_Z20test_svextq_lane_u64u12__SVUint64_tS_ +// CPP-CHECK-LABEL: define dso_local @_Z15test_svextq_u64u12__SVUint64_tS_ // CPP-CHECK-SAME: ( [[ZN:%.*]], [[ZM:%.*]]) #[[ATTR0]] { // CPP-CHECK-NEXT: entry: -// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.extq.lane.nxv2i64( [[ZN]], [[ZM]], i32 3) +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.extq.nxv2i64( [[ZN]], [[ZM]], i32 3) // CPP-CHECK-NEXT: ret [[TMP0]] // -svuint64_t test_svextq_lane_u64(svuint64_t zn, svuint64_t zm) { - return SVE_ACLE_FUNC(svextq_lane, _u64,,)(zn, zm, 3); +svuint64_t test_svextq_u64(svuint64_t zn, svuint64_t zm) { + return SVE_ACLE_FUNC(svextq, _u64,,)(zn, zm, 3); } -// CHECK-LABEL: define dso_local @test_svextq_lane_s64 +// CHECK-LABEL: define dso_local @test_svextq_s64 // CHECK-SAME: ( [[ZN:%.*]], [[ZM:%.*]]) #[[ATTR0]] { // CHECK-NEXT: entry: -// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.extq.lane.nxv2i64( [[ZN]], [[ZM]], i32 7) +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.extq.nxv2i64( [[ZN]], [[ZM]], i32 7) // CHECK-NEXT: ret [[TMP0]] // -// CPP-CHECK-LABEL: define dso_local @_Z20test_svextq_lane_s64u11__SVInt64_tS_ +// CPP-CHECK-LABEL: define dso_local @_Z15test_svextq_s64u11__SVInt64_tS_ // CPP-CHECK-SAME: ( [[ZN:%.*]], [[ZM:%.*]]) #[[ATTR0]] { // CPP-CHECK-NEXT: entry: -// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.extq.lane.nxv2i64( [[ZN]], [[ZM]], i32 7) +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.extq.nxv2i64( [[ZN]], [[ZM]], i32 7) // CPP-CHECK-NEXT: ret [[TMP0]] // -svint64_t test_svextq_lane_s64(svint64_t zn, svint64_t zm) { - return SVE_ACLE_FUNC(svextq_lane, _s64,,)(zn, zm, 7); +svint64_t test_svextq_s64(svint64_t zn, svint64_t zm) { + return SVE_ACLE_FUNC(svextq, _s64,,)(zn, zm, 7); } -// CHECK-LABEL: define dso_local @test_svextq_lane_f16 +// CHECK-LABEL: define dso_local @test_svextq_f16 // CHECK-SAME: ( [[ZN:%.*]], [[ZM:%.*]]) #[[ATTR0]] { // CHECK-NEXT: entry: -// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.extq.lane.nxv8f16( [[ZN]], [[ZM]], i32 8) +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.extq.nxv8f16( [[ZN]], [[ZM]], i32 8) // CHECK-NEXT: ret [[TMP0]] // -// CPP-CHECK-LABEL: define dso_local @_Z20test_svextq_lane_f16u13__SVFloat16_tS_ +// CPP-CHECK-LABEL: define dso_local @_Z15test_svextq_f16u13__SVFloat16_tS_ // CPP-CHECK-SAME: ( [[ZN:%.*]], [[ZM:%.*]]) #[[ATTR0]] { // CPP-CHECK-NEXT: entry: -// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.extq.lane.nxv8f16( [[ZN]], [[ZM]], i32 8) +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.extq.nxv8f16( [[ZN]], [[ZM]], i32 8) // CPP-CHECK-NEXT: ret [[TMP0]] // -svfloat16_t test_svextq_lane_f16(svfloat16_t zn, svfloat16_t zm) { - return SVE_ACLE_FUNC(svextq_lane, _f16,,)(zn, zm, 8); +svfloat16_t test_svextq_f16(svfloat16_t zn, svfloat16_t zm) { + return SVE_ACLE_FUNC(svextq, _f16,,)(zn, zm, 8); } -// CHECK-LABEL: define dso_local @test_svextq_lane_f32 +// CHECK-LABEL: define dso_local @test_svextq_f32 // CHECK-SAME: ( [[ZN:%.*]], [[ZM:%.*]]) #[[ATTR0]] { // CHECK-NEXT: entry: -// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.extq.lane.nxv4f32( [[ZN]], [[ZM]], i32 9) +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.extq.nxv4f32( [[ZN]], [[ZM]], i32 9) // CHECK-NEXT: ret [[TMP0]] // -// CPP-CHECK-LABEL: define dso_local @_Z20test_svextq_lane_f32u13__SVFloat32_tS_ +// CPP-CHECK-LABEL: define dso_local @_Z15test_svextq_f32u13__SVFloat32_tS_ // CPP-CHECK-SAME: ( [[ZN:%.*]], [[ZM:%.*]]) #[[ATTR0]] { // CPP-CHECK-NEXT: entry: -// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.extq.lane.nxv4f32( [[ZN]], [[ZM]], i32 9) +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.extq.nxv4f32( [[ZN]], [[ZM]], i32 9) // CPP-CHECK-NEXT: ret [[TMP0]] // -svfloat32_t test_svextq_lane_f32(svfloat32_t zn, svfloat32_t zm) { - return SVE_ACLE_FUNC(svextq_lane, _f32,,)(zn, zm, 9); +svfloat32_t test_svextq_f32(svfloat32_t zn, svfloat32_t zm) { + return SVE_ACLE_FUNC(svextq, _f32,,)(zn, zm, 9); } -// CHECK-LABEL: define dso_local @test_svextq_lane_f64 +// CHECK-LABEL: define dso_local @test_svextq_f64 // CHECK-SAME: ( [[ZN:%.*]], [[ZM:%.*]]) #[[ATTR0]] { // CHECK-NEXT: entry: -// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.extq.lane.nxv2f64( [[ZN]], [[ZM]], i32 10) +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.extq.nxv2f64( [[ZN]], [[ZM]], i32 10) // CHECK-NEXT: ret [[TMP0]] // -// CPP-CHECK-LABEL: define dso_local @_Z20test_svextq_lane_f64u13__SVFloat64_tS_ +// CPP-CHECK-LABEL: define dso_local @_Z15test_svextq_f64u13__SVFloat64_tS_ // CPP-CHECK-SAME: ( [[ZN:%.*]], [[ZM:%.*]]) #[[ATTR0]] { // CPP-CHECK-NEXT: entry: -// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.extq.lane.nxv2f64( [[ZN]], [[ZM]], i32 10) +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.extq.nxv2f64( [[ZN]], [[ZM]], i32 10) // CPP-CHECK-NEXT: ret [[TMP0]] // -svfloat64_t test_svextq_lane_f64(svfloat64_t zn, svfloat64_t zm) { - return SVE_ACLE_FUNC(svextq_lane, _f64,,)(zn, zm, 10); +svfloat64_t test_svextq_f64(svfloat64_t zn, svfloat64_t zm) { + return SVE_ACLE_FUNC(svextq, _f64,,)(zn, zm, 10); } -// CHECK-LABEL: define dso_local @test_svextq_lane_bf16 +// CHECK-LABEL: define dso_local @test_svextq_bf16 // CHECK-SAME: ( [[ZN:%.*]], [[ZM:%.*]]) #[[ATTR0]] { // CHECK-NEXT: entry: -// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.extq.lane.nxv8bf16( [[ZN]], [[ZM]], i32 11) +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.extq.nxv8bf16( [[ZN]], [[ZM]], i32 11) // CHECK-NEXT: ret [[TMP0]] // -// CPP-CHECK-LABEL: define dso_local @_Z21test_svextq_lane_bf16u14__SVBfloat16_tS_ +// CPP-CHECK-LABEL: define dso_local @_Z16test_svextq_bf16u14__SVBfloat16_tS_ // CPP-CHECK-SAME: ( [[ZN:%.*]], [[ZM:%.*]]) #[[ATTR0]] { // CPP-CHECK-NEXT: entry: -// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.extq.lane.nxv8bf16( [[ZN]], [[ZM]], i32 11) +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.extq.nxv8bf16( [[ZN]], [[ZM]], i32 11) // CPP-CHECK-NEXT: ret [[TMP0]] // -svbfloat16_t test_svextq_lane_bf16(svbfloat16_t zn, svbfloat16_t zm) { - return SVE_ACLE_FUNC(svextq_lane, _bf16,,)(zn, zm, 11); +svbfloat16_t test_svextq_bf16(svbfloat16_t zn, svbfloat16_t zm) { + return SVE_ACLE_FUNC(svextq, _bf16,,)(zn, zm, 11); } diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_st1_single.c b/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_st1_single.c index 52c16faec7f32b2013a794511b8e8d5d6fe34396..27f7b8be7f18429a069834ec4fc4a09f85fdf43d 100644 --- a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_st1_single.c +++ b/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_st1_single.c @@ -23,233 +23,233 @@ // ST1W -// CHECK-LABEL: define dso_local void @test_svst1uwq_u32 +// CHECK-LABEL: define dso_local void @test_svst1wq_u32 // CHECK-SAME: ( [[PRED:%.*]], ptr noundef [[BASE:%.*]], [[ZT:%.*]]) #[[ATTR0:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PRED]]) -// CHECK-NEXT: tail call void @llvm.aarch64.sve.st1uwq.nxv4i32( [[ZT]], [[TMP0]], ptr [[BASE]]) +// CHECK-NEXT: tail call void @llvm.aarch64.sve.st1wq.nxv4i32( [[ZT]], [[TMP0]], ptr [[BASE]]) // CHECK-NEXT: ret void // -// CPP-CHECK-LABEL: define dso_local void @_Z17test_svst1uwq_u32u10__SVBool_tPKju12__SVUint32_t +// CPP-CHECK-LABEL: define dso_local void @_Z16test_svst1wq_u32u10__SVBool_tPKju12__SVUint32_t // CPP-CHECK-SAME: ( [[PRED:%.*]], ptr noundef [[BASE:%.*]], [[ZT:%.*]]) #[[ATTR0:[0-9]+]] { // CPP-CHECK-NEXT: entry: // CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PRED]]) -// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sve.st1uwq.nxv4i32( [[ZT]], [[TMP0]], ptr [[BASE]]) +// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sve.st1wq.nxv4i32( [[ZT]], [[TMP0]], ptr [[BASE]]) // CPP-CHECK-NEXT: ret void // -void test_svst1uwq_u32(svbool_t pred, uint32_t const * base, svuint32_t zt) { - SVE_ACLE_FUNC(svst1uwq, _u32, , )(pred, base, zt); +void test_svst1wq_u32(svbool_t pred, uint32_t const * base, svuint32_t zt) { + SVE_ACLE_FUNC(svst1wq, _u32, , )(pred, base, zt); } -// CHECK-LABEL: define dso_local void @test_svst1uwq_vnum_u32 +// CHECK-LABEL: define dso_local void @test_svst1wq_vnum_u32 // CHECK-SAME: ( [[PRED:%.*]], ptr noundef [[BASE:%.*]], [[ZT:%.*]]) #[[ATTR0]] { // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PRED]]) // CHECK-NEXT: [[TMP1:%.*]] = getelementptr , ptr [[BASE]], i64 1 -// CHECK-NEXT: tail call void @llvm.aarch64.sve.st1uwq.nxv4i32( [[ZT]], [[TMP0]], ptr [[TMP1]]) +// CHECK-NEXT: tail call void @llvm.aarch64.sve.st1wq.nxv4i32( [[ZT]], [[TMP0]], ptr [[TMP1]]) // CHECK-NEXT: ret void // -// CPP-CHECK-LABEL: define dso_local void @_Z22test_svst1uwq_vnum_u32u10__SVBool_tPKju12__SVUint32_t +// CPP-CHECK-LABEL: define dso_local void @_Z21test_svst1wq_vnum_u32u10__SVBool_tPKju12__SVUint32_t // CPP-CHECK-SAME: ( [[PRED:%.*]], ptr noundef [[BASE:%.*]], [[ZT:%.*]]) #[[ATTR0]] { // CPP-CHECK-NEXT: entry: // CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PRED]]) // CPP-CHECK-NEXT: [[TMP1:%.*]] = getelementptr , ptr [[BASE]], i64 1 -// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sve.st1uwq.nxv4i32( [[ZT]], [[TMP0]], ptr [[TMP1]]) +// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sve.st1wq.nxv4i32( [[ZT]], [[TMP0]], ptr [[TMP1]]) // CPP-CHECK-NEXT: ret void // -void test_svst1uwq_vnum_u32(svbool_t pred, uint32_t const * base, svuint32_t zt) { - SVE_ACLE_FUNC(svst1uwq_vnum, _u32, , )(pred, base, 1, zt); +void test_svst1wq_vnum_u32(svbool_t pred, uint32_t const * base, svuint32_t zt) { + SVE_ACLE_FUNC(svst1wq_vnum, _u32, , )(pred, base, 1, zt); } -// CHECK-LABEL: define dso_local void @test_svst1uwq_s32 +// CHECK-LABEL: define dso_local void @test_svst1wq_s32 // CHECK-SAME: ( [[PRED:%.*]], ptr noundef [[BASE:%.*]], [[ZT:%.*]]) #[[ATTR0]] { // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PRED]]) -// CHECK-NEXT: tail call void @llvm.aarch64.sve.st1uwq.nxv4i32( [[ZT]], [[TMP0]], ptr [[BASE]]) +// CHECK-NEXT: tail call void @llvm.aarch64.sve.st1wq.nxv4i32( [[ZT]], [[TMP0]], ptr [[BASE]]) // CHECK-NEXT: ret void // -// CPP-CHECK-LABEL: define dso_local void @_Z17test_svst1uwq_s32u10__SVBool_tPKiu11__SVInt32_t +// CPP-CHECK-LABEL: define dso_local void @_Z16test_svst1wq_s32u10__SVBool_tPKiu11__SVInt32_t // CPP-CHECK-SAME: ( [[PRED:%.*]], ptr noundef [[BASE:%.*]], [[ZT:%.*]]) #[[ATTR0]] { // CPP-CHECK-NEXT: entry: // CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PRED]]) -// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sve.st1uwq.nxv4i32( [[ZT]], [[TMP0]], ptr [[BASE]]) +// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sve.st1wq.nxv4i32( [[ZT]], [[TMP0]], ptr [[BASE]]) // CPP-CHECK-NEXT: ret void // -void test_svst1uwq_s32(svbool_t pred, int32_t const * base, svint32_t zt) { - SVE_ACLE_FUNC(svst1uwq, _s32, , )(pred, base, zt); +void test_svst1wq_s32(svbool_t pred, int32_t const * base, svint32_t zt) { + SVE_ACLE_FUNC(svst1wq, _s32, , )(pred, base, zt); } -// CHECK-LABEL: define dso_local void @test_svst1uwq_vnum_s32 +// CHECK-LABEL: define dso_local void @test_svst1wq_vnum_s32 // CHECK-SAME: ( [[PRED:%.*]], ptr noundef [[BASE:%.*]], [[ZT:%.*]]) #[[ATTR0]] { // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PRED]]) // CHECK-NEXT: [[TMP1:%.*]] = getelementptr , ptr [[BASE]], i64 1 -// CHECK-NEXT: tail call void @llvm.aarch64.sve.st1uwq.nxv4i32( [[ZT]], [[TMP0]], ptr [[TMP1]]) +// CHECK-NEXT: tail call void @llvm.aarch64.sve.st1wq.nxv4i32( [[ZT]], [[TMP0]], ptr [[TMP1]]) // CHECK-NEXT: ret void // -// CPP-CHECK-LABEL: define dso_local void @_Z22test_svst1uwq_vnum_s32u10__SVBool_tPKiu11__SVInt32_t +// CPP-CHECK-LABEL: define dso_local void @_Z21test_svst1wq_vnum_s32u10__SVBool_tPKiu11__SVInt32_t // CPP-CHECK-SAME: ( [[PRED:%.*]], ptr noundef [[BASE:%.*]], [[ZT:%.*]]) #[[ATTR0]] { // CPP-CHECK-NEXT: entry: // CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PRED]]) // CPP-CHECK-NEXT: [[TMP1:%.*]] = getelementptr , ptr [[BASE]], i64 1 -// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sve.st1uwq.nxv4i32( [[ZT]], [[TMP0]], ptr [[TMP1]]) +// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sve.st1wq.nxv4i32( [[ZT]], [[TMP0]], ptr [[TMP1]]) // CPP-CHECK-NEXT: ret void // -void test_svst1uwq_vnum_s32(svbool_t pred, int32_t const * base, svint32_t zt) { - SVE_ACLE_FUNC(svst1uwq_vnum, _s32, , )(pred, base, 1, zt); +void test_svst1wq_vnum_s32(svbool_t pred, int32_t const * base, svint32_t zt) { + SVE_ACLE_FUNC(svst1wq_vnum, _s32, , )(pred, base, 1, zt); } -// CHECK-LABEL: define dso_local void @test_svst1uwq_f32 +// CHECK-LABEL: define dso_local void @test_svst1wq_f32 // CHECK-SAME: ( [[PRED:%.*]], ptr noundef [[BASE:%.*]], [[ZT:%.*]]) #[[ATTR0]] { // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PRED]]) -// CHECK-NEXT: tail call void @llvm.aarch64.sve.st1uwq.nxv4f32( [[ZT]], [[TMP0]], ptr [[BASE]]) +// CHECK-NEXT: tail call void @llvm.aarch64.sve.st1wq.nxv4f32( [[ZT]], [[TMP0]], ptr [[BASE]]) // CHECK-NEXT: ret void // -// CPP-CHECK-LABEL: define dso_local void @_Z17test_svst1uwq_f32u10__SVBool_tPKfu13__SVFloat32_t +// CPP-CHECK-LABEL: define dso_local void @_Z16test_svst1wq_f32u10__SVBool_tPKfu13__SVFloat32_t // CPP-CHECK-SAME: ( [[PRED:%.*]], ptr noundef [[BASE:%.*]], [[ZT:%.*]]) #[[ATTR0]] { // CPP-CHECK-NEXT: entry: // CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PRED]]) -// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sve.st1uwq.nxv4f32( [[ZT]], [[TMP0]], ptr [[BASE]]) +// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sve.st1wq.nxv4f32( [[ZT]], [[TMP0]], ptr [[BASE]]) // CPP-CHECK-NEXT: ret void // -void test_svst1uwq_f32(svbool_t pred, float32_t const * base, svfloat32_t zt) { - SVE_ACLE_FUNC(svst1uwq, _f32, , )(pred, base, zt); +void test_svst1wq_f32(svbool_t pred, float32_t const * base, svfloat32_t zt) { + SVE_ACLE_FUNC(svst1wq, _f32, , )(pred, base, zt); } -// CHECK-LABEL: define dso_local void @test_svst1uwq_vnum_f32 +// CHECK-LABEL: define dso_local void @test_svst1wq_vnum_f32 // CHECK-SAME: ( [[PRED:%.*]], ptr noundef [[BASE:%.*]], [[ZT:%.*]]) #[[ATTR0]] { // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PRED]]) // CHECK-NEXT: [[TMP1:%.*]] = getelementptr , ptr [[BASE]], i64 1 -// CHECK-NEXT: tail call void @llvm.aarch64.sve.st1uwq.nxv4f32( [[ZT]], [[TMP0]], ptr [[TMP1]]) +// CHECK-NEXT: tail call void @llvm.aarch64.sve.st1wq.nxv4f32( [[ZT]], [[TMP0]], ptr [[TMP1]]) // CHECK-NEXT: ret void // -// CPP-CHECK-LABEL: define dso_local void @_Z22test_svst1uwq_vnum_f32u10__SVBool_tPKfu13__SVFloat32_t +// CPP-CHECK-LABEL: define dso_local void @_Z21test_svst1wq_vnum_f32u10__SVBool_tPKfu13__SVFloat32_t // CPP-CHECK-SAME: ( [[PRED:%.*]], ptr noundef [[BASE:%.*]], [[ZT:%.*]]) #[[ATTR0]] { // CPP-CHECK-NEXT: entry: // CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PRED]]) // CPP-CHECK-NEXT: [[TMP1:%.*]] = getelementptr , ptr [[BASE]], i64 1 -// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sve.st1uwq.nxv4f32( [[ZT]], [[TMP0]], ptr [[TMP1]]) +// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sve.st1wq.nxv4f32( [[ZT]], [[TMP0]], ptr [[TMP1]]) // CPP-CHECK-NEXT: ret void // -void test_svst1uwq_vnum_f32(svbool_t pred, float32_t const * base, svfloat32_t zt) { - SVE_ACLE_FUNC(svst1uwq_vnum, _f32, , )(pred, base, 1, zt); +void test_svst1wq_vnum_f32(svbool_t pred, float32_t const * base, svfloat32_t zt) { + SVE_ACLE_FUNC(svst1wq_vnum, _f32, , )(pred, base, 1, zt); } // ST1D -// CHECK-LABEL: define dso_local void @test_svst1udq_u64 +// CHECK-LABEL: define dso_local void @test_svst1dq_u64 // CHECK-SAME: ( [[PRED:%.*]], ptr noundef [[BASE:%.*]], [[ZT:%.*]]) #[[ATTR0]] { // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PRED]]) -// CHECK-NEXT: tail call void @llvm.aarch64.sve.st1udq.nxv2i64( [[ZT]], [[TMP0]], ptr [[BASE]]) +// CHECK-NEXT: tail call void @llvm.aarch64.sve.st1dq.nxv2i64( [[ZT]], [[TMP0]], ptr [[BASE]]) // CHECK-NEXT: ret void // -// CPP-CHECK-LABEL: define dso_local void @_Z17test_svst1udq_u64u10__SVBool_tPKmu12__SVUint64_t +// CPP-CHECK-LABEL: define dso_local void @_Z16test_svst1dq_u64u10__SVBool_tPKmu12__SVUint64_t // CPP-CHECK-SAME: ( [[PRED:%.*]], ptr noundef [[BASE:%.*]], [[ZT:%.*]]) #[[ATTR0]] { // CPP-CHECK-NEXT: entry: // CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PRED]]) -// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sve.st1udq.nxv2i64( [[ZT]], [[TMP0]], ptr [[BASE]]) +// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sve.st1dq.nxv2i64( [[ZT]], [[TMP0]], ptr [[BASE]]) // CPP-CHECK-NEXT: ret void // -void test_svst1udq_u64(svbool_t pred, uint64_t const * base, svuint64_t zt) { - SVE_ACLE_FUNC(svst1udq, _u64, , )(pred, base, zt); +void test_svst1dq_u64(svbool_t pred, uint64_t const * base, svuint64_t zt) { + SVE_ACLE_FUNC(svst1dq, _u64, , )(pred, base, zt); } -// CHECK-LABEL: define dso_local void @test_svst1udq_vnum_u64 +// CHECK-LABEL: define dso_local void @test_svst1dq_vnum_u64 // CHECK-SAME: ( [[PRED:%.*]], ptr noundef [[BASE:%.*]], [[ZT:%.*]]) #[[ATTR0]] { // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PRED]]) // CHECK-NEXT: [[TMP1:%.*]] = getelementptr , ptr [[BASE]], i64 -8 -// CHECK-NEXT: tail call void @llvm.aarch64.sve.st1udq.nxv2i64( [[ZT]], [[TMP0]], ptr [[TMP1]]) +// CHECK-NEXT: tail call void @llvm.aarch64.sve.st1dq.nxv2i64( [[ZT]], [[TMP0]], ptr [[TMP1]]) // CHECK-NEXT: ret void // -// CPP-CHECK-LABEL: define dso_local void @_Z22test_svst1udq_vnum_u64u10__SVBool_tPKmu12__SVUint64_t +// CPP-CHECK-LABEL: define dso_local void @_Z21test_svst1dq_vnum_u64u10__SVBool_tPKmu12__SVUint64_t // CPP-CHECK-SAME: ( [[PRED:%.*]], ptr noundef [[BASE:%.*]], [[ZT:%.*]]) #[[ATTR0]] { // CPP-CHECK-NEXT: entry: // CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PRED]]) // CPP-CHECK-NEXT: [[TMP1:%.*]] = getelementptr , ptr [[BASE]], i64 -8 -// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sve.st1udq.nxv2i64( [[ZT]], [[TMP0]], ptr [[TMP1]]) +// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sve.st1dq.nxv2i64( [[ZT]], [[TMP0]], ptr [[TMP1]]) // CPP-CHECK-NEXT: ret void // -void test_svst1udq_vnum_u64(svbool_t pred, uint64_t const * base, svuint64_t zt) { - SVE_ACLE_FUNC(svst1udq_vnum, _u64, , )(pred, base, -8, zt); +void test_svst1dq_vnum_u64(svbool_t pred, uint64_t const * base, svuint64_t zt) { + SVE_ACLE_FUNC(svst1dq_vnum, _u64, , )(pred, base, -8, zt); } -// CHECK-LABEL: define dso_local void @test_svst1udq_s64 +// CHECK-LABEL: define dso_local void @test_svst1dq_s64 // CHECK-SAME: ( [[PRED:%.*]], ptr noundef [[BASE:%.*]], [[ZT:%.*]]) #[[ATTR0]] { // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PRED]]) -// CHECK-NEXT: tail call void @llvm.aarch64.sve.st1udq.nxv2i64( [[ZT]], [[TMP0]], ptr [[BASE]]) +// CHECK-NEXT: tail call void @llvm.aarch64.sve.st1dq.nxv2i64( [[ZT]], [[TMP0]], ptr [[BASE]]) // CHECK-NEXT: ret void // -// CPP-CHECK-LABEL: define dso_local void @_Z17test_svst1udq_s64u10__SVBool_tPKlu11__SVInt64_t +// CPP-CHECK-LABEL: define dso_local void @_Z16test_svst1dq_s64u10__SVBool_tPKlu11__SVInt64_t // CPP-CHECK-SAME: ( [[PRED:%.*]], ptr noundef [[BASE:%.*]], [[ZT:%.*]]) #[[ATTR0]] { // CPP-CHECK-NEXT: entry: // CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PRED]]) -// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sve.st1udq.nxv2i64( [[ZT]], [[TMP0]], ptr [[BASE]]) +// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sve.st1dq.nxv2i64( [[ZT]], [[TMP0]], ptr [[BASE]]) // CPP-CHECK-NEXT: ret void // -void test_svst1udq_s64(svbool_t pred, int64_t const * base, svint64_t zt) { - SVE_ACLE_FUNC(svst1udq, _s64, , )(pred, base, zt); +void test_svst1dq_s64(svbool_t pred, int64_t const * base, svint64_t zt) { + SVE_ACLE_FUNC(svst1dq, _s64, , )(pred, base, zt); } -// CHECK-LABEL: define dso_local void @test_svst1udq_vnum_s64 +// CHECK-LABEL: define dso_local void @test_svst1dq_vnum_s64 // CHECK-SAME: ( [[PRED:%.*]], ptr noundef [[BASE:%.*]], [[ZT:%.*]]) #[[ATTR0]] { // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PRED]]) // CHECK-NEXT: [[TMP1:%.*]] = getelementptr , ptr [[BASE]], i64 -8 -// CHECK-NEXT: tail call void @llvm.aarch64.sve.st1udq.nxv2i64( [[ZT]], [[TMP0]], ptr [[TMP1]]) +// CHECK-NEXT: tail call void @llvm.aarch64.sve.st1dq.nxv2i64( [[ZT]], [[TMP0]], ptr [[TMP1]]) // CHECK-NEXT: ret void // -// CPP-CHECK-LABEL: define dso_local void @_Z22test_svst1udq_vnum_s64u10__SVBool_tPKlu11__SVInt64_t +// CPP-CHECK-LABEL: define dso_local void @_Z21test_svst1dq_vnum_s64u10__SVBool_tPKlu11__SVInt64_t // CPP-CHECK-SAME: ( [[PRED:%.*]], ptr noundef [[BASE:%.*]], [[ZT:%.*]]) #[[ATTR0]] { // CPP-CHECK-NEXT: entry: // CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PRED]]) // CPP-CHECK-NEXT: [[TMP1:%.*]] = getelementptr , ptr [[BASE]], i64 -8 -// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sve.st1udq.nxv2i64( [[ZT]], [[TMP0]], ptr [[TMP1]]) +// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sve.st1dq.nxv2i64( [[ZT]], [[TMP0]], ptr [[TMP1]]) // CPP-CHECK-NEXT: ret void // -void test_svst1udq_vnum_s64(svbool_t pred, int64_t const * base, svint64_t zt) { - SVE_ACLE_FUNC(svst1udq_vnum, _s64, , )(pred, base, -8, zt); +void test_svst1dq_vnum_s64(svbool_t pred, int64_t const * base, svint64_t zt) { + SVE_ACLE_FUNC(svst1dq_vnum, _s64, , )(pred, base, -8, zt); } -// CHECK-LABEL: define dso_local void @test_svst1udq_f64 +// CHECK-LABEL: define dso_local void @test_svst1dq_f64 // CHECK-SAME: ( [[PRED:%.*]], ptr noundef [[BASE:%.*]], [[ZT:%.*]]) #[[ATTR0]] { // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PRED]]) -// CHECK-NEXT: tail call void @llvm.aarch64.sve.st1udq.nxv2f64( [[ZT]], [[TMP0]], ptr [[BASE]]) +// CHECK-NEXT: tail call void @llvm.aarch64.sve.st1dq.nxv2f64( [[ZT]], [[TMP0]], ptr [[BASE]]) // CHECK-NEXT: ret void // -// CPP-CHECK-LABEL: define dso_local void @_Z17test_svst1udq_f64u10__SVBool_tPKdu13__SVFloat64_t +// CPP-CHECK-LABEL: define dso_local void @_Z16test_svst1dq_f64u10__SVBool_tPKdu13__SVFloat64_t // CPP-CHECK-SAME: ( [[PRED:%.*]], ptr noundef [[BASE:%.*]], [[ZT:%.*]]) #[[ATTR0]] { // CPP-CHECK-NEXT: entry: // CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PRED]]) -// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sve.st1udq.nxv2f64( [[ZT]], [[TMP0]], ptr [[BASE]]) +// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sve.st1dq.nxv2f64( [[ZT]], [[TMP0]], ptr [[BASE]]) // CPP-CHECK-NEXT: ret void // -void test_svst1udq_f64(svbool_t pred, float64_t const * base, svfloat64_t zt) { - SVE_ACLE_FUNC(svst1udq, _f64, , )(pred, base, zt); +void test_svst1dq_f64(svbool_t pred, float64_t const * base, svfloat64_t zt) { + SVE_ACLE_FUNC(svst1dq, _f64, , )(pred, base, zt); } -// CHECK-LABEL: define dso_local void @test_svst1udq_vnum_f64 +// CHECK-LABEL: define dso_local void @test_svst1dq_vnum_f64 // CHECK-SAME: ( [[PRED:%.*]], ptr noundef [[BASE:%.*]], [[ZT:%.*]]) #[[ATTR0]] { // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PRED]]) // CHECK-NEXT: [[TMP1:%.*]] = getelementptr , ptr [[BASE]], i64 -8 -// CHECK-NEXT: tail call void @llvm.aarch64.sve.st1udq.nxv2f64( [[ZT]], [[TMP0]], ptr [[TMP1]]) +// CHECK-NEXT: tail call void @llvm.aarch64.sve.st1dq.nxv2f64( [[ZT]], [[TMP0]], ptr [[TMP1]]) // CHECK-NEXT: ret void // -// CPP-CHECK-LABEL: define dso_local void @_Z22test_svst1udq_vnum_f64u10__SVBool_tPKdu13__SVFloat64_t +// CPP-CHECK-LABEL: define dso_local void @_Z21test_svst1dq_vnum_f64u10__SVBool_tPKdu13__SVFloat64_t // CPP-CHECK-SAME: ( [[PRED:%.*]], ptr noundef [[BASE:%.*]], [[ZT:%.*]]) #[[ATTR0]] { // CPP-CHECK-NEXT: entry: // CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PRED]]) // CPP-CHECK-NEXT: [[TMP1:%.*]] = getelementptr , ptr [[BASE]], i64 -8 -// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sve.st1udq.nxv2f64( [[ZT]], [[TMP0]], ptr [[TMP1]]) +// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sve.st1dq.nxv2f64( [[ZT]], [[TMP0]], ptr [[TMP1]]) // CPP-CHECK-NEXT: ret void // -void test_svst1udq_vnum_f64(svbool_t pred, float64_t const * base, svfloat64_t zt) { - SVE_ACLE_FUNC(svst1udq_vnum, _f64, , )(pred, base, -8, zt); +void test_svst1dq_vnum_f64(svbool_t pred, float64_t const * base, svfloat64_t zt) { + SVE_ACLE_FUNC(svst1dq_vnum, _f64, , )(pred, base, -8, zt); } diff --git a/clang/test/CodeGen/aarch64-targetattr.c b/clang/test/CodeGen/aarch64-targetattr.c index 9664b723a2b2cddae1d7ae26af205e28f2415db7..5f557532a4b4a7aaa9aa77186a094a6f0aba5830 100644 --- a/clang/test/CodeGen/aarch64-targetattr.c +++ b/clang/test/CodeGen/aarch64-targetattr.c @@ -110,6 +110,6 @@ void minusarch() {} // CHECK: attributes #13 = { {{.*}} "target-features"="+fp-armv8,+fullfp16,+neon,+sve,-sve2" } // CHECK: attributes #14 = { {{.*}} "target-features"="+fullfp16" } // CHECK: attributes #15 = { {{.*}} "target-cpu"="neoverse-n1" "target-features"="+aes,+bf16,+crc,+dotprod,+fp-armv8,+fullfp16,+i8mm,+lse,+neon,+ras,+rcpc,+rdm,+sha2,+spe,+ssbs,+sve,+sve2,+v8.1a,+v8.2a,+v8.3a,+v8.4a,+v8.5a,+v8.6a,+v8a" "tune-cpu"="cortex-a710" } -// CHECK: attributes #16 = { {{.*}} "branch-target-enforcement"="true" {{.*}} "target-features"="+aes,+bf16,+crc,+dotprod,+fp-armv8,+fullfp16,+i8mm,+lse,+neon,+ras,+rcpc,+rdm,+sha2,+spe,+ssbs,+sve,+sve2,+v8.1a,+v8.2a,+v8.3a,+v8.4a,+v8.5a,+v8.6a,+v8a" "tune-cpu"="cortex-a710" } +// CHECK: attributes #16 = { {{.*}} "branch-target-enforcement"="true" "guarded-control-stack"="true" {{.*}} "target-features"="+aes,+bf16,+crc,+dotprod,+fp-armv8,+fullfp16,+i8mm,+lse,+neon,+ras,+rcpc,+rdm,+sha2,+spe,+ssbs,+sve,+sve2,+v8.1a,+v8.2a,+v8.3a,+v8.4a,+v8.5a,+v8.6a,+v8a" "tune-cpu"="cortex-a710" } // CHECK: attributes #17 = { {{.*}} "target-features"="-neon" } // CHECK: attributes #18 = { {{.*}} "target-features"="-v9.3a" } diff --git a/clang/test/CodeGen/aarch64-varargs.c b/clang/test/CodeGen/aarch64-varargs.c index f2ce7d59a8cce9bf03faca83007fb3a48d061098..44b87029e7b3d3fe1e43edd2f32e302d24e19be3 100644 --- a/clang/test/CodeGen/aarch64-varargs.c +++ b/clang/test/CodeGen/aarch64-varargs.c @@ -601,7 +601,7 @@ typedef struct __attribute__((aligned(32))) { __int128 val; } overaligned_int128_struct; overaligned_int128_struct overaligned_int128_struct_test(void) { -// CHECK-LABEL: define{{.*}} void @overaligned_int128_struct_test(ptr noalias sret(%struct.overaligned_int128_struct) align 32 %agg.result) +// CHECK-LABEL: define{{.*}} void @overaligned_int128_struct_test(ptr dead_on_unwind noalias writable sret(%struct.overaligned_int128_struct) align 32 %agg.result) return va_arg(the_list, overaligned_int128_struct); // CHECK: [[GR_OFFS:%[a-z_0-9]+]] = load i32, ptr getelementptr inbounds (%struct.__va_list, ptr @the_list, i32 0, i32 3) // CHECK: [[EARLY_ONSTACK:%[a-z_0-9]+]] = icmp sge i32 [[GR_OFFS]], 0 @@ -804,7 +804,7 @@ typedef struct { __int128 val __attribute__((aligned(32))); } overaligned_int128_struct_member; overaligned_int128_struct_member overaligned_int128_struct_member_test(void) { -// CHECK-LABEL: define{{.*}} void @overaligned_int128_struct_member_test(ptr noalias sret(%struct.overaligned_int128_struct_member) align 32 %agg.result) +// CHECK-LABEL: define{{.*}} void @overaligned_int128_struct_member_test(ptr dead_on_unwind noalias writable sret(%struct.overaligned_int128_struct_member) align 32 %agg.result) return va_arg(the_list, overaligned_int128_struct_member); // CHECK: [[GR_OFFS:%[a-z_0-9]+]] = load i32, ptr getelementptr inbounds (%struct.__va_list, ptr @the_list, i32 0, i32 3) // CHECK: [[EARLY_ONSTACK:%[a-z_0-9]+]] = icmp sge i32 [[GR_OFFS]], 0 diff --git a/clang/test/CodeGen/aggregate-assign-call.c b/clang/test/CodeGen/aggregate-assign-call.c index b5c7f213dcbe2acbbbab6c206ecb6ae4fa282f12..d6571269456a4c51d8b04a12ce6a60640096f263 100644 --- a/clang/test/CodeGen/aggregate-assign-call.c +++ b/clang/test/CodeGen/aggregate-assign-call.c @@ -63,11 +63,11 @@ struct S baz(int i, volatile int *j) { // // O1: call void @llvm.lifetime.end.p0({{[^,]*}}, ptr %[[TMP1_ALLOCA]]) // - // O1: call void @foo_int(ptr sret(%struct.S) align 4 %[[TMP1_ALLOCA]], + // O1: call void @foo_int(ptr dead_on_unwind writable sret(%struct.S) align 4 %[[TMP1_ALLOCA]], // O1: call void @llvm.memcpy // O1: call void @llvm.lifetime.end.p0({{[^,]*}}, ptr %[[TMP1_ALLOCA]]) // O1: call void @llvm.lifetime.start.p0({{[^,]*}}, ptr %[[TMP2_ALLOCA]]) - // O1: call void @foo_int(ptr sret(%struct.S) align 4 %[[TMP2_ALLOCA]], + // O1: call void @foo_int(ptr dead_on_unwind writable sret(%struct.S) align 4 %[[TMP2_ALLOCA]], // O1: call void @llvm.memcpy // O1: call void @llvm.lifetime.end.p0({{[^,]*}}, ptr %[[TMP2_ALLOCA]]) r = foo_int(({ diff --git a/clang/test/CodeGen/aligned-sret.c b/clang/test/CodeGen/aligned-sret.c index 4759d69219a6aa68b846af063cabe05ce531214e..4e1f86e7f07a65d0fa2ddd8deb7a45053b80b500 100644 --- a/clang/test/CodeGen/aligned-sret.c +++ b/clang/test/CodeGen/aligned-sret.c @@ -4,7 +4,7 @@ typedef __attribute__((__ext_vector_type__(4),__aligned__(16))) double simd_doub typedef struct { simd_double4 columns[4]; } simd_double4x4; typedef simd_double4x4 matrix_double4x4; -// CHECK: define{{.*}} void @ident(ptr noalias sret(%struct.simd_double4x4) align 16 %agg.result +// CHECK: define{{.*}} void @ident(ptr dead_on_unwind noalias writable sret(%struct.simd_double4x4) align 16 %agg.result matrix_double4x4 ident(matrix_double4x4 x) { return x; } diff --git a/clang/test/CodeGen/arc/arguments.c b/clang/test/CodeGen/arc/arguments.c index a913984e13f85743d7242b1324b81f60563af80a..648a2ea3ce9c10fbb002e6d22224a8593129375b 100644 --- a/clang/test/CodeGen/arc/arguments.c +++ b/clang/test/CodeGen/arc/arguments.c @@ -22,7 +22,7 @@ void cf1(cs1 i) {} typedef struct { int cc; } s2; -// CHECK: define{{.*}} void @f2(ptr noalias sret(%struct.s2) align 4 %agg.result) +// CHECK: define{{.*}} void @f2(ptr dead_on_unwind noalias writable sret(%struct.s2) align 4 %agg.result) s2 f2(void) { s2 foo; return foo; @@ -32,7 +32,7 @@ typedef struct { int cc; int dd; } s3; -// CHECK: define{{.*}} void @f3(ptr noalias sret(%struct.s3) align 4 %agg.result) +// CHECK: define{{.*}} void @f3(ptr dead_on_unwind noalias writable sret(%struct.s3) align 4 %agg.result) s3 f3(void) { s3 foo; return foo; @@ -128,8 +128,8 @@ void st3(s16 a, s16 b, s16 c) {} // 1 sret + 1 i32 + 2*(i32 coerce) + 4*(i32 coerce) + 1 byval s16 st4(int x, s8 a, s16 b, s16 c) { return b; } -// CHECK: define{{.*}} void @st4(ptr noalias sret(%struct.s16) align 4 %agg.result, i32 inreg noundef %x, i32 inreg %a.coerce0, i32 inreg %a.coerce1, i32 inreg %b.coerce0, i32 inreg %b.coerce1, i32 inreg %b.coerce2, i32 inreg %b.coerce3, { i32, i32, i32, i32 } %c.coerce) +// CHECK: define{{.*}} void @st4(ptr dead_on_unwind noalias writable sret(%struct.s16) align 4 %agg.result, i32 inreg noundef %x, i32 inreg %a.coerce0, i32 inreg %a.coerce1, i32 inreg %b.coerce0, i32 inreg %b.coerce1, i32 inreg %b.coerce2, i32 inreg %b.coerce3, { i32, i32, i32, i32 } %c.coerce) // 1 sret + 2*(i32 coerce) + 4*(i32 coerce) + 4*(i32 coerce) s16 st5(s8 a, s16 b, s16 c) { return b; } -// CHECK: define{{.*}} void @st5(ptr noalias sret(%struct.s16) align 4 %agg.result, i32 inreg %a.coerce0, i32 inreg %a.coerce1, i32 inreg %b.coerce0, i32 inreg %b.coerce1, i32 inreg %b.coerce2, i32 inreg %b.coerce3, { i32, i32, i32, i32 } %c.coerce) +// CHECK: define{{.*}} void @st5(ptr dead_on_unwind noalias writable sret(%struct.s16) align 4 %agg.result, i32 inreg %a.coerce0, i32 inreg %a.coerce1, i32 inreg %b.coerce0, i32 inreg %b.coerce1, i32 inreg %b.coerce2, i32 inreg %b.coerce3, { i32, i32, i32, i32 } %c.coerce) diff --git a/clang/test/CodeGen/arm-aapcs-vfp.c b/clang/test/CodeGen/arm-aapcs-vfp.c index 5caf93016cd2ec014a1a7b3fe710a111cdb9d72a..9fae33f476d355db47a0448496d30bd1f265888f 100644 --- a/clang/test/CodeGen/arm-aapcs-vfp.c +++ b/clang/test/CodeGen/arm-aapcs-vfp.c @@ -126,7 +126,7 @@ void test_vfp_stack_gpr_split_1(double a, double b, double c, double d, double e // CHECK: define{{.*}} arm_aapcs_vfpcc void @test_vfp_stack_gpr_split_2(double noundef %a, double noundef %b, double noundef %c, double noundef %d, double noundef %e, double noundef %f, double noundef %g, double noundef %h, double noundef %i, i32 noundef %j, [2 x i64] %k.coerce) void test_vfp_stack_gpr_split_2(double a, double b, double c, double d, double e, double f, double g, double h, double i, int j, struct_long_long_int k) {} -// CHECK: define{{.*}} arm_aapcs_vfpcc void @test_vfp_stack_gpr_split_3(ptr noalias sret(%struct.struct_long_long_int) align 8 %agg.result, double noundef %a, double noundef %b, double noundef %c, double noundef %d, double noundef %e, double noundef %f, double noundef %g, double noundef %h, double noundef %i, [2 x i64] %k.coerce) +// CHECK: define{{.*}} arm_aapcs_vfpcc void @test_vfp_stack_gpr_split_3(ptr dead_on_unwind noalias writable sret(%struct.struct_long_long_int) align 8 %agg.result, double noundef %a, double noundef %b, double noundef %c, double noundef %d, double noundef %e, double noundef %f, double noundef %g, double noundef %h, double noundef %i, [2 x i64] %k.coerce) struct_long_long_int test_vfp_stack_gpr_split_3(double a, double b, double c, double d, double e, double f, double g, double h, double i, struct_long_long_int k) {} typedef struct { int a; int b:4; int c; } struct_int_bitfield_int; diff --git a/clang/test/CodeGen/arm-acle-coproc.c b/clang/test/CodeGen/arm-acle-coproc.c new file mode 100644 index 0000000000000000000000000000000000000000..cf87130932edfe93a149ac5b2fb3f2f3a20e5dee --- /dev/null +++ b/clang/test/CodeGen/arm-acle-coproc.c @@ -0,0 +1,383 @@ +// RUN: %clang_cc1 -triple armv4 %s -E -dD -o - | FileCheck --check-prefix=CHECK-V4 %s +// RUN: %clang_cc1 -triple armv4t %s -E -dD -o - | FileCheck --check-prefix=CHECK-V4 %s +// RUN: %clang_cc1 -triple armv5 %s -E -dD -o - | FileCheck --check-prefix=CHECK-V5 %s +// RUN: %clang_cc1 -triple armv5te %s -E -dD -o - | FileCheck --check-prefix=CHECK-V5-TE %s +// RUN: %clang_cc1 -triple armv5tej %s -E -dD -o - | FileCheck --check-prefix=CHECK-V5-TE %s +// RUN: %clang_cc1 -triple armv6 %s -E -dD -o - | FileCheck --check-prefix=CHECK-V6 %s +// RUN: %clang_cc1 -triple armv6m %s -E -dD -o - | FileCheck --check-prefix=CHECK-V6M %s +// RUN: %clang_cc1 -triple armv7a %s -E -dD -o - | FileCheck --check-prefix=CHECK-V7 %s +// RUN: %clang_cc1 -triple armv7r %s -E -dD -o - | FileCheck --check-prefix=CHECK-V7 %s +// RUN: %clang_cc1 -triple armv7m %s -E -dD -o - | FileCheck --check-prefix=CHECK-V7 %s +// RUN: %clang_cc1 -triple armv8a %s -E -dD -o - | FileCheck --check-prefix=CHECK-V8 %s +// RUN: %clang_cc1 -triple armv8r %s -E -dD -o - | FileCheck --check-prefix=CHECK-V8 %s +// RUN: %clang_cc1 -triple armv8.1a %s -E -dD -o - | FileCheck --check-prefix=CHECK-V8 %s +// RUN: %clang_cc1 -triple armv8.2a %s -E -dD -o - | FileCheck --check-prefix=CHECK-V8 %s +// RUN: %clang_cc1 -triple armv8.3a %s -E -dD -o - | FileCheck --check-prefix=CHECK-V8 %s +// RUN: %clang_cc1 -triple armv8.4a %s -E -dD -o - | FileCheck --check-prefix=CHECK-V8 %s +// RUN: %clang_cc1 -triple armv8.5a %s -E -dD -o - | FileCheck --check-prefix=CHECK-V8 %s +// RUN: %clang_cc1 -triple armv8.6a %s -E -dD -o - | FileCheck --check-prefix=CHECK-V8 %s +// RUN: %clang_cc1 -triple armv8.7a %s -E -dD -o - | FileCheck --check-prefix=CHECK-V8 %s +// RUN: %clang_cc1 -triple armv8.8a %s -E -dD -o - | FileCheck --check-prefix=CHECK-V8 %s +// RUN: %clang_cc1 -triple armv8.9a %s -E -dD -o - | FileCheck --check-prefix=CHECK-V8 %s +// RUN: %clang_cc1 -triple armv9a %s -E -dD -o - | FileCheck --check-prefix=CHECK-V8 %s +// RUN: %clang_cc1 -triple armv9.1a %s -E -dD -o - | FileCheck --check-prefix=CHECK-V8 %s +// RUN: %clang_cc1 -triple armv9.2a %s -E -dD -o - | FileCheck --check-prefix=CHECK-V8 %s +// RUN: %clang_cc1 -triple armv9.3a %s -E -dD -o - | FileCheck --check-prefix=CHECK-V8 %s +// RUN: %clang_cc1 -triple armv9.4a %s -E -dD -o - | FileCheck --check-prefix=CHECK-V8 %s +// RUN: %clang_cc1 -triple thumbv4 %s -E -dD -o - | FileCheck --check-prefix=CHECK-V4-THUMB %s +// RUN: %clang_cc1 -triple thumbv4t %s -E -dD -o - | FileCheck --check-prefix=CHECK-V4-THUMB %s +// RUN: %clang_cc1 -triple thumbv5 %s -E -dD -o - | FileCheck --check-prefix=CHECK-V5-THUMB %s +// RUN: %clang_cc1 -triple thumbv5te %s -E -dD -o - | FileCheck --check-prefix=CHECK-V5-TE-THUMB %s +// RUN: %clang_cc1 -triple thumbv5tej %s -E -dD -o - | FileCheck --check-prefix=CHECK-V5-TE-THUMB %s +// RUN: %clang_cc1 -triple thumbv6 %s -E -dD -o - | FileCheck --check-prefix=CHECK-V6-THUMB %s +// RUN: %clang_cc1 -triple thumbv6k %s -E -dD -o - | FileCheck --check-prefix=CHECK-V6-THUMB %s +// RUN: %clang_cc1 -triple thumbv6kz %s -E -dD -o - | FileCheck --check-prefix=CHECK-V6-THUMB %s +// RUN: %clang_cc1 -triple thumbv6m %s -E -dD -o - | FileCheck --check-prefix=CHECK-V6M %s +// RUN: %clang_cc1 -triple thumbv7a %s -E -dD -o - | FileCheck --check-prefix=CHECK-V7 %s +// RUN: %clang_cc1 -triple thumbv7r %s -E -dD -o - | FileCheck --check-prefix=CHECK-V7 %s +// RUN: %clang_cc1 -triple thumbv7m %s -E -dD -o - | FileCheck --check-prefix=CHECK-V7 %s +// RUN: %clang_cc1 -triple thumbv8a %s -E -dD -o - | FileCheck --check-prefix=CHECK-V8 %s +// RUN: %clang_cc1 -triple thumbv8r %s -E -dD -o - | FileCheck --check-prefix=CHECK-V8 %s +// RUN: %clang_cc1 -triple thumbv8.1a %s -E -dD -o - | FileCheck --check-prefix=CHECK-V8 %s +// RUN: %clang_cc1 -triple thumbv8.2a %s -E -dD -o - | FileCheck --check-prefix=CHECK-V8 %s +// RUN: %clang_cc1 -triple thumbv8.3a %s -E -dD -o - | FileCheck --check-prefix=CHECK-V8 %s +// RUN: %clang_cc1 -triple thumbv8.4a %s -E -dD -o - | FileCheck --check-prefix=CHECK-V8 %s +// RUN: %clang_cc1 -triple thumbv8.5a %s -E -dD -o - | FileCheck --check-prefix=CHECK-V8 %s +// RUN: %clang_cc1 -triple thumbv8.6a %s -E -dD -o - | FileCheck --check-prefix=CHECK-V8 %s +// RUN: %clang_cc1 -triple thumbv8.7a %s -E -dD -o - | FileCheck --check-prefix=CHECK-V8 %s +// RUN: %clang_cc1 -triple thumbv8.8a %s -E -dD -o - | FileCheck --check-prefix=CHECK-V8 %s +// RUN: %clang_cc1 -triple thumbv8.9a %s -E -dD -o - | FileCheck --check-prefix=CHECK-V8 %s +// RUN: %clang_cc1 -triple thumbv9a %s -E -dD -o - | FileCheck --check-prefix=CHECK-V8 %s +// RUN: %clang_cc1 -triple thumbv9.1a %s -E -dD -o - | FileCheck --check-prefix=CHECK-V8 %s +// RUN: %clang_cc1 -triple thumbv9.2a %s -E -dD -o - | FileCheck --check-prefix=CHECK-V8 %s +// RUN: %clang_cc1 -triple thumbv9.3a %s -E -dD -o - | FileCheck --check-prefix=CHECK-V8 %s +// RUN: %clang_cc1 -triple thumbv9.4a %s -E -dD -o - | FileCheck --check-prefix=CHECK-V8 %s +// RUN: %clang_cc1 -triple thumbv8m.base %s -E -dD -o - | FileCheck --check-prefix=CHECK-V8-BASE %s +// RUN: %clang_cc1 -triple thumbv8m.main %s -E -dD -o - | FileCheck --check-prefix=CHECK-V8-MAIN %s +// RUN: %clang_cc1 -triple thumbv8.1m.main %s -E -dD -o - | FileCheck --check-prefix=CHECK-V8-MAIN %s + +#include + +void cdp() { + __arm_cdp(1, 2, 3, 4, 5, 6); + // CHECK-LABEL: void cdp() + // CHECK-V4: __builtin_arm_cdp + // CHECK-V4-THUMB-NOT: __builtin_arm_cdp + // CHECK-V5: __builtin_arm_cdp + // CHECK-V5-TE: __builtin_arm_cdp + // CHECK-V5-THUMB-NOT: __builtin_arm_cdp + // CHECK-V5-TE-THUMB-NOT: __builtin_arm_cdp + // CHECK-V6: __builtin_arm_cdp + // CHECK-V6-THUMB-NOT: __builtin_arm_cdp + // CHECK-V6M-NOT: __builtin_arm_cdp + // CHECK-V7: __builtin_arm_cdp + // CHECK-V8-NOT: __builtin_arm_cdp + // CHECK-V8-BASE-NOT: __builtin_arm_cdp + // CHECK-V8-MAIN: __builtin_arm_cdp +} + +void cdp2() { + __arm_cdp2(1, 2, 3, 4, 5, 6); + // CHECK-LABEL: void cdp2() + // CHECK-V4-NOT: __builtin_arm_cdp2 + // CHECK-V4-THUMB-NOT: __builtin_arm_cdp2 + // CHECK-V5: __builtin_arm_cdp2 + // CHECK-V5-TE: __builtin_arm_cdp2 + // CHECK-V5-THUMB-NOT: __builtin_arm_cdp2 + // CHECK-V5-TE-THUMB-NOT: __builtin_arm_cdp2 + // CHECK-V6: __builtin_arm_cdp2 + // CHECK-V6-THUMB-NOT: __builtin_arm_cdp2 + // CHECK-V6M-NOT: __builtin_arm_cdp2 + // CHECK-V7: __builtin_arm_cdp2 + // CHECK-V8-NOT: __builtin_arm_cdp2 + // CHECK-V8-BASE-NOT: __builtin_arm_cdp2 + // CHECK-V8-MAIN: __builtin_arm_cdp2 +} + +void ldc(int i) { + __arm_ldc(1, 2, &i); + // CHECK-LABEL: void ldc() + // CHECK-V4: __builtin_arm_ldc + // CHECK-V4-THUMB-NOT: __builtin_arm_ldc + // CHECK-V5: __builtin_arm_ldc + // CHECK-V5-TE: __builtin_arm_ldc + // CHECK-V5-THUMB-NOT: __builtin_arm_ldc + // CHECK-V5-TE-THUMB-NOT: __builtin_arm_ldc + // CHECK-V6: __builtin_arm_ldc + // CHECK-V6-THUMB-NOT: __builtin_arm_ldc + // CHECK-V6M-NOT: __builtin_arm_ldc + // CHECK-V7: __builtin_arm_ldc + // CHECK-V8: __builtin_arm_ldc + // CHECK-V8-BASE-NOT: __builtin_arm_ldc + // CHECK-V8-MAIN: __builtin_arm_ldc +} + +void ldcl(int i) { + __arm_ldcl(1, 2, &i); + // CHECK-LABEL: void ldcl() + // CHECK-V4-NOT: __builtin_arm_ldcl + // CHECK-V4-THUMB-NOT: __builtin_arm_ldcl + // CHECK-V5: __builtin_arm_ldcl + // CHECK-V5-TE: __builtin_arm_ldcl + // CHECK-V5-THUMB-NOT: __builtin_arm_ldcl + // CHECK-V5-TE-THUMB-NOT: __builtin_arm_ldcl + // CHECK-V6: __builtin_arm_ldcl + // CHECK-V6-THUMB-NOT: __builtin_arm_ldcl + // CHECK-V6M-NOT: __builtin_arm_ldcl + // CHECK-V7: __builtin_arm_ldcl + // CHECK-V8-NOT: __builtin_arm_ldcl + // CHECK-V8-BASE-NOT: __builtin_arm_ldcl + // CHECK-V8-MAIN: __builtin_arm_ldcl +} + +void ldc2(int i) { + __arm_ldc2(1, 2, &i); + // CHECK-LABEL: void ldc2() + // CHECK-V4-NOT: __builtin_arm_ldc2 + // CHECK-V4-THUMB-NOT: __builtin_arm_ldc2 + // CHECK-V5: __builtin_arm_ldc2 + // CHECK-V5-TE: __builtin_arm_ldc2 + // CHECK-V5-THUMB-NOT: __builtin_arm_ldc2 + // CHECK-V5-TE-THUMB-NOT: __builtin_arm_ldc2 + // CHECK-V6: __builtin_arm_ldc2 + // CHECK-V6-THUMB-NOT: __builtin_arm_ldc2 + // CHECK-V6M-NOT: __builtin_arm_ldc2 + // CHECK-V7: __builtin_arm_ldc2 + // CHECK-V8-NOT: __builtin_arm_ldc2 + // CHECK-V8-BASE-NOT: __builtin_arm_ldc2 + // CHECK-V8-MAIN: __builtin_arm_ldc2 +} + +void ldc2l(int i) { + __arm_ldc2l(1, 2, &i); + // CHECK-LABEL: void ldc2l() + // CHECK-V4-NOT: __builtin_arm_ldc2l + // CHECK-V4-THUMB-NOT: __builtin_arm_ldc2l + // CHECK-V5: __builtin_arm_ldc2l + // CHECK-V5-TE: __builtin_arm_ldc2l + // CHECK-V5-THUMB-NOT: __builtin_arm_ldc2l + // CHECK-V5-TE-THUMB-NOT: __builtin_arm_ldc2l + // CHECK-V6: __builtin_arm_ldc2l + // CHECK-V6-THUMB-NOT: __builtin_arm_ldc2l + // CHECK-V6M-NOT: __builtin_arm_ldc2l + // CHECK-V7: __builtin_arm_ldc2l + // CHECK-V8-NOT: __builtin_arm_ldc2l + // CHECK-V8-BASE-NOT: __builtin_arm_ldc2l + // CHECK-V8-MAIN: __builtin_arm_ldc2l +} + +void stc(int i) { + __arm_stc(1, 2, &i); + // CHECK-LABEL: void stc() + // CHECK-V4: __builtin_arm_stc + // CHECK-V4-THUMB-NOT: __builtin_arm_stc + // CHECK-V5: __builtin_arm_stc + // CHECK-V5-TE: __builtin_arm_stc + // CHECK-V5-THUMB-NOT: __builtin_arm_stc + // CHECK-V5-TE-THUMB-NOT: __builtin_arm_stc + // CHECK-V6: __builtin_arm_stc + // CHECK-V6-THUMB-NOT: __builtin_arm_stc + // CHECK-V6M-NOT: __builtin_arm_stc + // CHECK-V7: __builtin_arm_stc + // CHECK-V8: __builtin_arm_stc + // CHECK-V8-BASE-NOT: __builtin_arm_stc + // CHECK-V8-MAIN: __builtin_arm_stc +} + +void stcl(int i) { + __arm_stcl(1, 2, &i); + // CHECK-LABEL: void stcl() + // CHECK-V4-NOT: __builtin_arm_stcl + // CHECK-V4-THUMB-NOT: __builtin_arm_stcl + // CHECK-V5: __builtin_arm_stcl + // CHECK-V5-TE: __builtin_arm_stcl + // CHECK-V5-THUMB-NOT: __builtin_arm_stcl + // CHECK-V5-TE-THUMB-NOT: __builtin_arm_stcl + // CHECK-V6: __builtin_arm_stcl + // CHECK-V6-THUMB-NOT: __builtin_arm_stcl + // CHECK-V6M-NOT: __builtin_arm_stcl + // CHECK-V7: __builtin_arm_stcl + // CHECK-V8-NOT: __builtin_arm_stcl + // CHECK-V8-BASE-NOT: __builtin_arm_stcl + // CHECK-V8-MAIN: __builtin_arm_stcl +} + +void stc2(int i) { + __arm_stc2(1, 2, &i); + // CHECK-LABEL: void stc2() + // CHECK-V4-NOT: __builtin_arm_stc2 + // CHECK-V4-THUMB-NOT: __builtin_arm_stc2 + // CHECK-V5: __builtin_arm_stc2 + // CHECK-V5-TE: __builtin_arm_stc2 + // CHECK-V5-THUMB-NOT: __builtin_arm_stc2 + // CHECK-V5-TE-THUMB-NOT: __builtin_arm_stc2 + // CHECK-V6: __builtin_arm_stc2 + // CHECK-V6-THUMB-NOT: __builtin_arm_stc2 + // CHECK-V6M-NOT: __builtin_arm_stc2 + // CHECK-V7: __builtin_arm_stc2 + // CHECK-V8-NOT: __builtin_arm_stc2 + // CHECK-V8-BASE-NOT: __builtin_arm_stc2 + // CHECK-V8-MAIN: __builtin_arm_stc2 +} + +void stc2l(int i) { + __arm_stc2l(1, 2, &i); + // CHECK-LABEL: void stc2l() + // CHECK-V4-NOT: __builtin_arm_stc2l + // CHECK-V4-THUMB-NOT: __builtin_arm_stc2l + // CHECK-V5: __builtin_arm_stc2l + // CHECK-V5-TE: __builtin_arm_stc2l + // CHECK-V5-THUMB-NOT: __builtin_arm_stc2l + // CHECK-V5-TE-THUMB-NOT: __builtin_arm_stc2l + // CHECK-V6: __builtin_arm_stc2l + // CHECK-V6-THUMB-NOT: __builtin_arm_stc2l + // CHECK-V6M-NOT: __builtin_arm_stc2l + // CHECK-V7: __builtin_arm_stc2l + // CHECK-V8-NOT: __builtin_arm_stc2l + // CHECK-V8-BASE-NOT: __builtin_arm_stc2l + // CHECK-V8-MAIN: __builtin_arm_stc2l +} + +void mcr() { + __arm_mcr(1, 2, 3, 4, 5, 6); + // CHECK-LABEL: void mcr() + // CHECK-V4: __builtin_arm_mcr + // CHECK-V4-THUMB-NOT: __builtin_arm_mcr + // CHECK-V5: __builtin_arm_mcr + // CHECK-V5-TE: __builtin_arm_mcr + // CHECK-V5-THUMB-NOT: __builtin_arm_mcr + // CHECK-V5-TE-THUMB-NOT: __builtin_arm_mcr + // CHECK-V6: __builtin_arm_mcr + // CHECK-V6-THUMB-NOT: __builtin_arm_mcr + // CHECK-V6M-NOT: __builtin_arm_mcr + // CHECK-V7: __builtin_arm_mcr + // CHECK-V8: __builtin_arm_mcr + // CHECK-V8-BASE-NOT: __builtin_arm_mcr + // CHECK-V8-MAIN: __builtin_arm_mcr +} + +void mcr2() { + __arm_mcr2(1, 2, 3, 4, 5, 6); + // CHECK-LABEL: void mcr2() + // CHECK-V4-NOT: __builtin_arm_mcr2 + // CHECK-V4-THUMB-NOT: __builtin_arm_mcr2 + // CHECK-V5: __builtin_arm_mcr2 + // CHECK-V5-TE: __builtin_arm_mcr2 + // CHECK-V5-THUMB-NOT: __builtin_arm_mcr2 + // CHECK-V5-TE-THUMB-NOT: __builtin_arm_mcr2 + // CHECK-V6: __builtin_arm_mcr2 + // CHECK-V6-THUMB-NOT: __builtin_arm_mcr2 + // CHECK-V6M-NOT: __builtin_arm_mcr2 + // CHECK-V7: __builtin_arm_mcr2 + // CHECK-V8-NOT: __builtin_arm_mcr2 + // CHECK-V8-BASE-NOT: __builtin_arm_mcr2 + // CHECK-V8-MAIN: __builtin_arm_mcr2 +} + +void mrc() { + __arm_mrc(1, 2, 3, 4, 5); + // CHECK-LABEL: void mrc() + // CHECK-V4: __builtin_arm_mrc + // CHECK-V4-THUMB-NOT: __builtin_arm_mrc + // CHECK-V5: __builtin_arm_mrc + // CHECK-V5-TE: __builtin_arm_mrc + // CHECK-V5-THUMB-NOT: __builtin_arm_mrc + // CHECK-V5-TE-THUMB-NOT: __builtin_arm_mrc + // CHECK-V6: __builtin_arm_mrc + // CHECK-V6-THUMB-NOT: __builtin_arm_mrc + // CHECK-V6M-NOT: __builtin_arm_mrc + // CHECK-V7: __builtin_arm_mrc + // CHECK-V8: __builtin_arm_mrc + // CHECK-V8-BASE-NOT: __builtin_arm_mrc + // CHECK-V8-MAIN: __builtin_arm_mrc +} + +void mrc2() { + __arm_mrc2(1, 2, 3, 4, 5); + // CHECK-LABEL: void mrc2() + // CHECK-V4-NOT: __builtin_arm_mrc2 + // CHECK-V4-THUMB-NOT: __builtin_arm_mrc2 + // CHECK-V5: __builtin_arm_mrc2 + // CHECK-V5-TE: __builtin_arm_mrc2 + // CHECK-V5-THUMB-NOT: __builtin_arm_mrc2 + // CHECK-V5-TE-THUMB-NOT: __builtin_arm_mrc2 + // CHECK-V6: __builtin_arm_mrc2 + // CHECK-V6-THUMB-NOT: __builtin_arm_mrc2 + // CHECK-V6M-NOT: __builtin_arm_mrc2 + // CHECK-V7: __builtin_arm_mrc2 + // CHECK-V8-NOT: __builtin_arm_mrc2 + // CHECK-V8-BASE-NOT: __builtin_arm_mrc2 + // CHECK-V8-MAIN: __builtin_arm_mrc2 +} + +void mcrr() { + __arm_mcrr(1, 2, 3, 4); + // CHECK-LABEL: void mcrr() + // CHECK-V4-NOT: __builtin_arm_mcrr + // CHECK-V4-THUMB-NOT: __builtin_arm_mcrr + // CHECK-V5-NOT: __builtin_arm_mcrr + // CHECK-V5-TE: __builtin_arm_mcrr + // CHECK-V5-THUMB-NOT: __builtin_arm_mcrr + // CHECK-V5-THUMB-NOT: __builtin_arm_mcrr + // CHECK-V6: __builtin_arm_mcrr + // CHECK-V6-THUMB-NOT: __builtin_arm_mcrr + // CHECK-V6M-NOT: __builtin_arm_mcrr + // CHECK-V7: __builtin_arm_mcrr + // CHECK-V8: __builtin_arm_mcrr + // CHECK-V8-BASE-NOT: __builtin_arm_mcrr + // CHECK-V8-MAIN: __builtin_arm_mcrr +} + +void mcrr2() { + __arm_mcrr2(1, 2, 3, 4); + // CHECK-LABEL: void mcrr2() + // CHECK-V4-NOT: __builtin_arm_mcrr2 + // CHECK-V4-THUMB-NOT: __builtin_arm_mcrr2 + // CHECK-V5-NOT: __builtin_arm_mcrr2 + // CHECK-V5-TE-NOT: __builtin_arm_mcrr2 + // CHECK-V5-THUMB-NOT: __builtin_arm_mcrr2 + // CHECK-V5-TE-THUMB-NOT: __builtin_arm_mcrr2 + // CHECK-V6: __builtin_arm_mcrr2 + // CHECK-V6-THUMB-NOT: __builtin_arm_mcrr2 + // CHECK-V6M-NOT: __builtin_arm_mcrr2 + // CHECK-V7: __builtin_arm_mcrr2 + // CHECK-V8-NOT: __builtin_arm_mcrr2 + // CHECK-V8-BASE-NOT: __builtin_arm_mcrr2 + // CHECK-V8-MAIN: __builtin_arm_mcrr2 +} + +void mrrc() { + __arm_mrrc(1, 2, 3); + // CHECK-LABEL: void mrrc() + // CHECK-V4-NOT: __builtin_arm_mrrc + // CHECK-V4-THUMB-NOT: __builtin_arm_mrrc + // CHECK-V5-NOT: __builtin_arm_mrrc + // CHECK-V5-TE: __builtin_arm_mrrc + // CHECK-V5-THUMB-NOT: __builtin_arm_mrrc + // CHECK-V5-THUMB-TE-NOT: __builtin_arm_mrrc + // CHECK-V6: __builtin_arm_mrrc + // CHECK-V6-THUMB-NOT: __builtin_arm_mrrc + // CHECK-V6M-NOT: __builtin_arm_mrrc + // CHECK-V7: __builtin_arm_mrrc + // CHECK-V8: __builtin_arm_mrrc + // CHECK-V8-BASE-NOT: __builtin_arm_mrrc + // CHECK-V8-MAIN: __builtin_arm_mrrc +} + +void mrrc2() { + __arm_mrrc2(1, 2, 3); + // CHECK-LABEL: void mrrc2() + // CHECK-V4-NOT: __builtin_arm_mrrc2 + // CHECK-V4-THUMB-NOT: __builtin_arm_mrrc2 + // CHECK-V5-NOT: __builtin_arm_mrrc2 + // CHECK-V5-TE-NOT: __builtin_arm_mrrc2 + // CHECK-V5-THUMB-NOT: __builtin_arm_mrrc2 + // CHECK-V5-TE-THUMB-NOT: __builtin_arm_mrrc2 + // CHECK-V6: __builtin_arm_mrrc2 + // CHECK-V6-THUMB-NOT: __builtin_arm_mrrc2 + // CHECK-V6M-NOT: __builtin_arm_mrrc2 + // CHECK-V7: __builtin_arm_mrrc2 + // CHECK-V8-NOT: __builtin_arm_mrrc2 + // CHECK-V8-BASE-NOT: __builtin_arm_mrrc2 + // CHECK-V8-MAIN: __builtin_arm_mrrc2 +} diff --git a/clang/test/CodeGen/arm-arguments.c b/clang/test/CodeGen/arm-arguments.c index 17e4d3abd976783cbee610a13fb5ea0ec433b970..8fe2016315f27eb0a2149f1c59bac765e98fc287 100644 --- a/clang/test/CodeGen/arm-arguments.c +++ b/clang/test/CodeGen/arm-arguments.c @@ -29,13 +29,13 @@ struct s4 { struct s4_0 { int f0; } f0; }; struct s4 f4(void) {} // APCS-GNU-LABEL: define{{.*}} void @f5( -// APCS-GNU: ptr noalias sret +// APCS-GNU: ptr dead_on_unwind noalias writable sret // AAPCS-LABEL: define{{.*}} arm_aapcscc i32 @f5() struct s5 { struct { } f0; int f1; }; struct s5 f5(void) {} // APCS-GNU-LABEL: define{{.*}} void @f6( -// APCS-GNU: ptr noalias sret +// APCS-GNU: ptr dead_on_unwind noalias writable sret // AAPCS-LABEL: define{{.*}} arm_aapcscc i32 @f6() struct s6 { int f0[1]; }; struct s6 f6(void) {} @@ -46,7 +46,7 @@ struct s7 { struct { int : 0; } f0; }; struct s7 f7(void) {} // APCS-GNU-LABEL: define{{.*}} void @f8( -// APCS-GNU: ptr noalias sret +// APCS-GNU: ptr dead_on_unwind noalias writable sret // AAPCS-LABEL: define{{.*}} arm_aapcscc void @f8() struct s8 { struct { int : 0; } f0[1]; }; struct s8 f8(void) {} @@ -62,7 +62,7 @@ struct s10 { int f0; int : 0; int : 0; }; struct s10 f10(void) {} // APCS-GNU-LABEL: define{{.*}} void @f11( -// APCS-GNU: ptr noalias sret +// APCS-GNU: ptr dead_on_unwind noalias writable sret // AAPCS-LABEL: define{{.*}} arm_aapcscc i32 @f11() struct s11 { int : 0; int f0; }; struct s11 f11(void) {} @@ -73,7 +73,7 @@ union u12 { char f0; short f1; int f2; }; union u12 f12(void) {} // APCS-GNU-LABEL: define{{.*}} void @f13( -// APCS-GNU: ptr noalias sret +// APCS-GNU: ptr dead_on_unwind noalias writable sret // FIXME: This should return a float. // AAPCS-FIXME: darm_aapcscc efine float @f13() @@ -81,7 +81,7 @@ struct s13 { float f0; }; struct s13 f13(void) {} // APCS-GNU-LABEL: define{{.*}} void @f14( -// APCS-GNU: ptr noalias sret +// APCS-GNU: ptr dead_on_unwind noalias writable sret // AAPCS-LABEL: define{{.*}} arm_aapcscc i32 @f14() union u14 { float f0; }; union u14 f14(void) {} @@ -105,13 +105,13 @@ struct s18 { short f0; char f1 : 4; }; struct s18 f18(void) {} // APCS-GNU-LABEL: define{{.*}} void @f19( -// APCS-GNU: ptr noalias sret +// APCS-GNU: ptr dead_on_unwind noalias writable sret // AAPCS-LABEL: define{{.*}} arm_aapcscc i32 @f19() struct s19 { int f0; struct s8 f1; }; struct s19 f19(void) {} // APCS-GNU-LABEL: define{{.*}} void @f20( -// APCS-GNU: ptr noalias sret +// APCS-GNU: ptr dead_on_unwind noalias writable sret // AAPCS-LABEL: define{{.*}} arm_aapcscc i32 @f20() struct s20 { struct s8 f1; int f0; }; struct s20 f20(void) {} @@ -129,10 +129,10 @@ struct s21 f21(void) {} // APCS-GNU-LABEL: define{{.*}} i128 @f27() // AAPCS-LABEL: define{{.*}} arm_aapcscc i16 @f22() // AAPCS-LABEL: define{{.*}} arm_aapcscc i32 @f23() -// AAPCS: define{{.*}} arm_aapcscc void @f24({{.*}} noalias sret -// AAPCS: define{{.*}} arm_aapcscc void @f25({{.*}} noalias sret -// AAPCS: define{{.*}} arm_aapcscc void @f26({{.*}} noalias sret -// AAPCS: define{{.*}} arm_aapcscc void @f27({{.*}} noalias sret +// AAPCS: define{{.*}} arm_aapcscc void @f24({{.*}} dead_on_unwind noalias writable sret +// AAPCS: define{{.*}} arm_aapcscc void @f25({{.*}} dead_on_unwind noalias writable sret +// AAPCS: define{{.*}} arm_aapcscc void @f26({{.*}} dead_on_unwind noalias writable sret +// AAPCS: define{{.*}} arm_aapcscc void @f27({{.*}} dead_on_unwind noalias writable sret _Complex char f22(void) {} _Complex short f23(void) {} _Complex int f24(void) {} @@ -150,8 +150,8 @@ struct s28 f28() {} struct s29 { _Complex short f0; }; struct s29 f29() {} -// APCS-GNU: define{{.*}} void @f30({{.*}} noalias sret -// AAPCS: define{{.*}} arm_aapcscc void @f30({{.*}} noalias sret +// APCS-GNU: define{{.*}} void @f30({{.*}} dead_on_unwind noalias writable sret +// AAPCS: define{{.*}} arm_aapcscc void @f30({{.*}} dead_on_unwind noalias writable sret struct s30 { _Complex int f0; }; struct s30 f30() {} diff --git a/clang/test/CodeGen/arm-homogenous.c b/clang/test/CodeGen/arm-homogenous.c index dbfb5fb284467e596b07d2581c9e94f1fc686546..44a539598eb9bbbd655193ba43c651ea1d1045bf 100644 --- a/clang/test/CodeGen/arm-homogenous.c +++ b/clang/test/CodeGen/arm-homogenous.c @@ -27,7 +27,7 @@ void test_union_with_first_floats(void) { void test_return_union_with_first_floats(void) { g_u_f = returns_union_with_first_floats(); } -// CHECK: declare arm_aapcs_vfpcc void @returns_union_with_first_floats(ptr sret(%union.union_with_first_floats) align 4) +// CHECK: declare arm_aapcs_vfpcc void @returns_union_with_first_floats(ptr dead_on_unwind writable sret(%union.union_with_first_floats) align 4) /* This is not a homogenous aggregate - fundamental types are different */ typedef union { @@ -47,7 +47,7 @@ void test_union_with_non_first_floats(void) { void test_return_union_with_non_first_floats(void) { g_u_nf_f = returns_union_with_non_first_floats(); } -// CHECK: declare arm_aapcs_vfpcc void @returns_union_with_non_first_floats(ptr sret(%union.union_with_non_first_floats) align 4) +// CHECK: declare arm_aapcs_vfpcc void @returns_union_with_non_first_floats(ptr dead_on_unwind writable sret(%union.union_with_non_first_floats) align 4) /* This is not a homogenous aggregate - fundamental types are different */ typedef struct { @@ -67,7 +67,7 @@ void test_struct_with_union_with_first_floats(void) { void test_return_struct_with_union_with_first_floats(void) { g_s_f = returns_struct_with_union_with_first_floats(); } -// CHECK: declare arm_aapcs_vfpcc void @returns_struct_with_union_with_first_floats(ptr sret(%struct.struct_with_union_with_first_floats) align 4) +// CHECK: declare arm_aapcs_vfpcc void @returns_struct_with_union_with_first_floats(ptr dead_on_unwind writable sret(%struct.struct_with_union_with_first_floats) align 4) /* This is not a homogenous aggregate - fundamental types are different */ typedef struct { @@ -87,7 +87,7 @@ void test_struct_with_union_with_non_first_floats(void) { void test_return_struct_with_union_with_non_first_floats(void) { g_s_nf_f = returns_struct_with_union_with_non_first_floats(); } -// CHECK: declare arm_aapcs_vfpcc void @returns_struct_with_union_with_non_first_floats(ptr sret(%struct.struct_with_union_with_non_first_floats) align 4) +// CHECK: declare arm_aapcs_vfpcc void @returns_struct_with_union_with_non_first_floats(ptr dead_on_unwind writable sret(%struct.struct_with_union_with_non_first_floats) align 4) /* Plain array is not a homogenous aggregate */ extern void takes_array_of_floats(float a[4]); diff --git a/clang/test/CodeGen/arm-neon-vld.c b/clang/test/CodeGen/arm-neon-vld.c index 697992edb5f6f447bbd387f948a0682ab75e089f..959c07cc2219b42e60a6ca019bdaff9aeec4a3c0 100644 --- a/clang/test/CodeGen/arm-neon-vld.c +++ b/clang/test/CodeGen/arm-neon-vld.c @@ -11,7 +11,7 @@ // CHECK-LABEL: @test_vld1_f16_x2( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.float16x4x2_t, align 8 -// CHECK-A32: ptr noalias sret(%struct.float16x4x2_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.float16x4x2_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.float16x4x2_t, align 8 // CHECK: [[VLD1XN:%.*]] = call { <4 x [[HALF:half|i16]]>, <4 x [[HALF]]> } @llvm.{{aarch64.neon.ld1x2.v4f16.p0|arm.neon.vld1x2.v4i16.p0}}(ptr %a) // CHECK: store { <4 x [[HALF]]>, <4 x [[HALF]]> } [[VLD1XN]], ptr [[__RET]] @@ -25,7 +25,7 @@ float16x4x2_t test_vld1_f16_x2(float16_t const *a) { // CHECK-LABEL: @test_vld1_f16_x3( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.float16x4x3_t, align 8 -// CHECK-A32: ptr noalias sret(%struct.float16x4x3_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.float16x4x3_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.float16x4x3_t, align 8 // CHECK: [[VLD1XN:%.*]] = call { <4 x [[HALF:half|i16]]>, <4 x [[HALF]]>, <4 x [[HALF]]> } @llvm.{{aarch64.neon.ld1x3.v4f16.p0|arm.neon.vld1x3.v4i16.p0}}(ptr %a) // CHECK: store { <4 x [[HALF]]>, <4 x [[HALF]]>, <4 x [[HALF]]> } [[VLD1XN]], ptr [[__RET]] @@ -39,7 +39,7 @@ float16x4x3_t test_vld1_f16_x3(float16_t const *a) { // CHECK-LABEL: @test_vld1_f16_x4( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.float16x4x4_t, align 8 -// CHECK-A32: ptr noalias sret(%struct.float16x4x4_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.float16x4x4_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.float16x4x4_t, align 8 // CHECK: [[VLD1XN:%.*]] = call { <4 x [[HALF:half|i16]]>, <4 x [[HALF]]>, <4 x [[HALF]]>, <4 x [[HALF]]> } @llvm.{{aarch64.neon.ld1x4.v4f16.p0|arm.neon.vld1x4.v4i16.p0}}(ptr %a) // CHECK: store { <4 x [[HALF]]>, <4 x [[HALF]]>, <4 x [[HALF]]>, <4 x [[HALF]]> } [[VLD1XN]], ptr [[__RET]] @@ -53,7 +53,7 @@ float16x4x4_t test_vld1_f16_x4(float16_t const *a) { // CHECK-LABEL: @test_vld1_f32_x2( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.float32x2x2_t, align 8 -// CHECK-A32: ptr noalias sret(%struct.float32x2x2_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.float32x2x2_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.float32x2x2_t, align 8 // CHECK: [[VLD1XN:%.*]] = call { <2 x float>, <2 x float> } @llvm.{{aarch64.neon.ld1x2|arm.neon.vld1x2}}.v2f32.p0(ptr %a) // CHECK: store { <2 x float>, <2 x float> } [[VLD1XN]], ptr [[__RET]] @@ -67,7 +67,7 @@ float32x2x2_t test_vld1_f32_x2(float32_t const *a) { // CHECK-LABEL: @test_vld1_f32_x3( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.float32x2x3_t, align 8 -// CHECK-A32: ptr noalias sret(%struct.float32x2x3_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.float32x2x3_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.float32x2x3_t, align 8 // CHECK: [[VLD1XN:%.*]] = call { <2 x float>, <2 x float>, <2 x float> } @llvm.{{aarch64.neon.ld1x3|arm.neon.vld1x3}}.v2f32.p0(ptr %a) // CHECK: store { <2 x float>, <2 x float>, <2 x float> } [[VLD1XN]], ptr [[__RET]] @@ -80,7 +80,7 @@ float32x2x3_t test_vld1_f32_x3(float32_t const *a) { // CHECK-LABEL: @test_vld1_f32_x4( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.float32x2x4_t, align 8 -// CHECK-A32: ptr noalias sret(%struct.float32x2x4_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.float32x2x4_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.float32x2x4_t, align 8 // CHECK: [[VLD1XN:%.*]] = call { <2 x float>, <2 x float>, <2 x float>, <2 x float> } @llvm.{{aarch64.neon.ld1x4|arm.neon.vld1x4}}.v2f32.p0(ptr %a) // CHECK: store { <2 x float>, <2 x float>, <2 x float>, <2 x float> } [[VLD1XN]], ptr [[__RET]] @@ -94,7 +94,7 @@ float32x2x4_t test_vld1_f32_x4(float32_t const *a) { // CHECK-LABEL: @test_vld1_p16_x2( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.poly16x4x2_t, align 8 -// CHECK-A32: ptr noalias sret(%struct.poly16x4x2_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.poly16x4x2_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.poly16x4x2_t, align 8 // CHECK: [[VLD1XN:%.*]] = call { <4 x i16>, <4 x i16> } @llvm.{{aarch64.neon.ld1x2|arm.neon.vld1x2}}.v4i16.p0(ptr %a) // CHECK: store { <4 x i16>, <4 x i16> } [[VLD1XN]], ptr [[__RET]] @@ -108,7 +108,7 @@ poly16x4x2_t test_vld1_p16_x2(poly16_t const *a) { // CHECK-LABEL: @test_vld1_p16_x3( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.poly16x4x3_t, align 8 -// CHECK-A32: ptr noalias sret(%struct.poly16x4x3_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.poly16x4x3_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.poly16x4x3_t, align 8 // CHECK: [[VLD1XN:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16> } @llvm.{{aarch64.neon.ld1x3|arm.neon.vld1x3}}.v4i16.p0(ptr %a) // CHECK: store { <4 x i16>, <4 x i16>, <4 x i16> } [[VLD1XN]], ptr [[__RET]] @@ -122,7 +122,7 @@ poly16x4x3_t test_vld1_p16_x3(poly16_t const *a) { // CHECK-LABEL: @test_vld1_p16_x4( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.poly16x4x4_t, align 8 -// CHECK-A32: ptr noalias sret(%struct.poly16x4x4_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.poly16x4x4_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.poly16x4x4_t, align 8 // CHECK: [[VLD1XN:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } @llvm.{{aarch64.neon.ld1x4|arm.neon.vld1x4}}.v4i16.p0(ptr %a) // CHECK: store { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } [[VLD1XN]], ptr [[__RET]] @@ -136,7 +136,7 @@ poly16x4x4_t test_vld1_p16_x4(poly16_t const *a) { // CHECK-LABEL: @test_vld1_p8_x2( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.poly8x8x2_t, align 8 -// CHECK-A32: ptr noalias sret(%struct.poly8x8x2_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.poly8x8x2_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.poly8x8x2_t, align 8 // CHECK: [[VLD1XN:%.*]] = call { <8 x i8>, <8 x i8> } @llvm.{{aarch64.neon.ld1x2|arm.neon.vld1x2}}.v8i8.p0(ptr %a) // CHECK: store { <8 x i8>, <8 x i8> } [[VLD1XN]], ptr [[__RET]] @@ -150,7 +150,7 @@ poly8x8x2_t test_vld1_p8_x2(poly8_t const *a) { // CHECK-LABEL: @test_vld1_p8_x3( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.poly8x8x3_t, align 8 -// CHECK-A32: ptr noalias sret(%struct.poly8x8x3_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.poly8x8x3_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.poly8x8x3_t, align 8 // CHECK: [[VLD1XN:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8> } @llvm.{{aarch64.neon.ld1x3|arm.neon.vld1x3}}.v8i8.p0(ptr %a) // CHECK: store { <8 x i8>, <8 x i8>, <8 x i8> } [[VLD1XN]], ptr [[__RET]] @@ -164,7 +164,7 @@ poly8x8x3_t test_vld1_p8_x3(poly8_t const *a) { // CHECK-LABEL: @test_vld1_p8_x4( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.poly8x8x4_t, align 8 -// CHECK-A32: ptr noalias sret(%struct.poly8x8x4_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.poly8x8x4_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.poly8x8x4_t, align 8 // CHECK: [[VLD1XN:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } @llvm.{{aarch64.neon.ld1x4|arm.neon.vld1x4}}.v8i8.p0(ptr %a) // CHECK: store { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } [[VLD1XN]], ptr [[__RET]] @@ -178,7 +178,7 @@ poly8x8x4_t test_vld1_p8_x4(poly8_t const *a) { // CHECK-LABEL: @test_vld1_s16_x2( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.int16x4x2_t, align 8 -// CHECK-A32: ptr noalias sret(%struct.int16x4x2_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.int16x4x2_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.int16x4x2_t, align 8 // CHECK: [[VLD1XN:%.*]] = call { <4 x i16>, <4 x i16> } @llvm.{{aarch64.neon.ld1x2|arm.neon.vld1x2}}.v4i16.p0(ptr %a) // CHECK: store { <4 x i16>, <4 x i16> } [[VLD1XN]], ptr [[__RET]] @@ -192,7 +192,7 @@ int16x4x2_t test_vld1_s16_x2(int16_t const *a) { // CHECK-LABEL: @test_vld1_s16_x3( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.int16x4x3_t, align 8 -// CHECK-A32: ptr noalias sret(%struct.int16x4x3_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.int16x4x3_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.int16x4x3_t, align 8 // CHECK: [[VLD1XN:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16> } @llvm.{{aarch64.neon.ld1x3|arm.neon.vld1x3}}.v4i16.p0(ptr %a) // CHECK: store { <4 x i16>, <4 x i16>, <4 x i16> } [[VLD1XN]], ptr [[__RET]] @@ -206,7 +206,7 @@ int16x4x3_t test_vld1_s16_x3(int16_t const *a) { // CHECK-LABEL: @test_vld1_s16_x4( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.int16x4x4_t, align 8 -// CHECK-A32: ptr noalias sret(%struct.int16x4x4_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.int16x4x4_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.int16x4x4_t, align 8 // CHECK: [[VLD1XN:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } @llvm.{{aarch64.neon.ld1x4|arm.neon.vld1x4}}.v4i16.p0(ptr %a) // CHECK: store { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } [[VLD1XN]], ptr [[__RET]] @@ -220,7 +220,7 @@ int16x4x4_t test_vld1_s16_x4(int16_t const *a) { // CHECK-LABEL: @test_vld1_s32_x2( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.int32x2x2_t, align 8 -// CHECK-A32: ptr noalias sret(%struct.int32x2x2_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.int32x2x2_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.int32x2x2_t, align 8 // CHECK: [[VLD1XN:%.*]] = call { <2 x i32>, <2 x i32> } @llvm.{{aarch64.neon.ld1x2|arm.neon.vld1x2}}.v2i32.p0(ptr %a) // CHECK: store { <2 x i32>, <2 x i32> } [[VLD1XN]], ptr [[__RET]] @@ -234,7 +234,7 @@ int32x2x2_t test_vld1_s32_x2(int32_t const *a) { // CHECK-LABEL: @test_vld1_s32_x3( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.int32x2x3_t, align 8 -// CHECK-A32: ptr noalias sret(%struct.int32x2x3_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.int32x2x3_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.int32x2x3_t, align 8 // CHECK: [[VLD1XN:%.*]] = call { <2 x i32>, <2 x i32>, <2 x i32> } @llvm.{{aarch64.neon.ld1x3|arm.neon.vld1x3}}.v2i32.p0(ptr %a) // CHECK: store { <2 x i32>, <2 x i32>, <2 x i32> } [[VLD1XN]], ptr [[__RET]] @@ -248,7 +248,7 @@ int32x2x3_t test_vld1_s32_x3(int32_t const *a) { // CHECK-LABEL: @test_vld1_s32_x4( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.int32x2x4_t, align 8 -// CHECK-A32: ptr noalias sret(%struct.int32x2x4_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.int32x2x4_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.int32x2x4_t, align 8 // CHECK: [[VLD1XN:%.*]] = call { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } @llvm.{{aarch64.neon.ld1x4|arm.neon.vld1x4}}.v2i32.p0(ptr %a) // CHECK: store { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } [[VLD1XN]], ptr [[__RET]] @@ -262,7 +262,7 @@ int32x2x4_t test_vld1_s32_x4(int32_t const *a) { // CHECK-LABEL: @test_vld1_s64_x2( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.int64x1x2_t, align 8 -// CHECK-A32: ptr noalias sret(%struct.int64x1x2_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.int64x1x2_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.int64x1x2_t, align 8 // CHECK: [[VLD1XN:%.*]] = call { <1 x i64>, <1 x i64> } @llvm.{{aarch64.neon.ld1x2|arm.neon.vld1x2}}.v1i64.p0(ptr %a) // CHECK: store { <1 x i64>, <1 x i64> } [[VLD1XN]], ptr [[__RET]] @@ -276,7 +276,7 @@ int64x1x2_t test_vld1_s64_x2(int64_t const *a) { // CHECK-LABEL: @test_vld1_s64_x3( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.int64x1x3_t, align 8 -// CHECK-A32: ptr noalias sret(%struct.int64x1x3_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.int64x1x3_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.int64x1x3_t, align 8 // CHECK: [[VLD1XN:%.*]] = call { <1 x i64>, <1 x i64>, <1 x i64> } @llvm.{{aarch64.neon.ld1x3|arm.neon.vld1x3}}.v1i64.p0(ptr %a) // CHECK: store { <1 x i64>, <1 x i64>, <1 x i64> } [[VLD1XN]], ptr [[__RET]] @@ -290,7 +290,7 @@ int64x1x3_t test_vld1_s64_x3(int64_t const *a) { // CHECK-LABEL: @test_vld1_s64_x4( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.int64x1x4_t, align 8 -// CHECK-A32: ptr noalias sret(%struct.int64x1x4_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.int64x1x4_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.int64x1x4_t, align 8 // CHECK: [[VLD1XN:%.*]] = call { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> } @llvm.{{aarch64.neon.ld1x4|arm.neon.vld1x4}}.v1i64.p0(ptr %a) // CHECK: store { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> } [[VLD1XN]], ptr [[__RET]] @@ -304,7 +304,7 @@ int64x1x4_t test_vld1_s64_x4(int64_t const *a) { // CHECK-LABEL: @test_vld1_s8_x2( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.int8x8x2_t, align 8 -// CHECK-A32: ptr noalias sret(%struct.int8x8x2_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.int8x8x2_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.int8x8x2_t, align 8 // CHECK: [[VLD1XN:%.*]] = call { <8 x i8>, <8 x i8> } @llvm.{{aarch64.neon.ld1x2|arm.neon.vld1x2}}.v8i8.p0(ptr %a) // CHECK: store { <8 x i8>, <8 x i8> } [[VLD1XN]], ptr [[__RET]] @@ -318,7 +318,7 @@ int8x8x2_t test_vld1_s8_x2(int8_t const *a) { // CHECK-LABEL: @test_vld1_s8_x3( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.int8x8x3_t, align 8 -// CHECK-A32: ptr noalias sret(%struct.int8x8x3_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.int8x8x3_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.int8x8x3_t, align 8 // CHECK: [[VLD1XN:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8> } @llvm.{{aarch64.neon.ld1x3|arm.neon.vld1x3}}.v8i8.p0(ptr %a) // CHECK: store { <8 x i8>, <8 x i8>, <8 x i8> } [[VLD1XN]], ptr [[__RET]] @@ -332,7 +332,7 @@ int8x8x3_t test_vld1_s8_x3(int8_t const *a) { // CHECK-LABEL: @test_vld1_s8_x4( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.int8x8x4_t, align 8 -// CHECK-A32: ptr noalias sret(%struct.int8x8x4_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.int8x8x4_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.int8x8x4_t, align 8 // CHECK: [[VLD1XN:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } @llvm.{{aarch64.neon.ld1x4|arm.neon.vld1x4}}.v8i8.p0(ptr %a) // CHECK: store { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } [[VLD1XN]], ptr [[__RET]] @@ -346,7 +346,7 @@ int8x8x4_t test_vld1_s8_x4(int8_t const *a) { // CHECK-LABEL: @test_vld1_u16_x2( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.uint16x4x2_t, align 8 -// CHECK-A32: ptr noalias sret(%struct.uint16x4x2_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.uint16x4x2_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.uint16x4x2_t, align 8 // CHECK: [[VLD1XN:%.*]] = call { <4 x i16>, <4 x i16> } @llvm.{{aarch64.neon.ld1x2|arm.neon.vld1x2}}.v4i16.p0(ptr %a) // CHECK: store { <4 x i16>, <4 x i16> } [[VLD1XN]], ptr [[__RET]] @@ -360,7 +360,7 @@ uint16x4x2_t test_vld1_u16_x2(uint16_t const *a) { // CHECK-LABEL: @test_vld1_u16_x3( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.uint16x4x3_t, align 8 -// CHECK-A32: ptr noalias sret(%struct.uint16x4x3_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.uint16x4x3_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.uint16x4x3_t, align 8 // CHECK: [[VLD1XN:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16> } @llvm.{{aarch64.neon.ld1x3|arm.neon.vld1x3}}.v4i16.p0(ptr %a) // CHECK: store { <4 x i16>, <4 x i16>, <4 x i16> } [[VLD1XN]], ptr [[__RET]] @@ -374,7 +374,7 @@ uint16x4x3_t test_vld1_u16_x3(uint16_t const *a) { // CHECK-LABEL: @test_vld1_u16_x4( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.uint16x4x4_t, align 8 -// CHECK-A32: ptr noalias sret(%struct.uint16x4x4_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.uint16x4x4_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.uint16x4x4_t, align 8 // CHECK: [[VLD1XN:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } @llvm.{{aarch64.neon.ld1x4|arm.neon.vld1x4}}.v4i16.p0(ptr %a) // CHECK: store { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } [[VLD1XN]], ptr [[__RET]] @@ -388,7 +388,7 @@ uint16x4x4_t test_vld1_u16_x4(uint16_t const *a) { // CHECK-LABEL: @test_vld1_u32_x2( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.uint32x2x2_t, align 8 -// CHECK-A32: ptr noalias sret(%struct.uint32x2x2_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.uint32x2x2_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.uint32x2x2_t, align 8 // CHECK: [[VLD1XN:%.*]] = call { <2 x i32>, <2 x i32> } @llvm.{{aarch64.neon.ld1x2|arm.neon.vld1x2}}.v2i32.p0(ptr %a) // CHECK: store { <2 x i32>, <2 x i32> } [[VLD1XN]], ptr [[__RET]] @@ -402,7 +402,7 @@ uint32x2x2_t test_vld1_u32_x2(uint32_t const *a) { // CHECK-LABEL: @test_vld1_u32_x3( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.uint32x2x3_t, align 8 -// CHECK-A32: ptr noalias sret(%struct.uint32x2x3_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.uint32x2x3_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.uint32x2x3_t, align 8 // CHECK: [[VLD1XN:%.*]] = call { <2 x i32>, <2 x i32>, <2 x i32> } @llvm.{{aarch64.neon.ld1x3|arm.neon.vld1x3}}.v2i32.p0(ptr %a) // CHECK: store { <2 x i32>, <2 x i32>, <2 x i32> } [[VLD1XN]], ptr [[__RET]] @@ -416,7 +416,7 @@ uint32x2x3_t test_vld1_u32_x3(uint32_t const *a) { // CHECK-LABEL: @test_vld1_u32_x4( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.uint32x2x4_t, align 8 -// CHECK-A32: ptr noalias sret(%struct.uint32x2x4_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.uint32x2x4_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.uint32x2x4_t, align 8 // CHECK: [[VLD1XN:%.*]] = call { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } @llvm.{{aarch64.neon.ld1x4|arm.neon.vld1x4}}.v2i32.p0(ptr %a) // CHECK: store { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } [[VLD1XN]], ptr [[__RET]] @@ -430,7 +430,7 @@ uint32x2x4_t test_vld1_u32_x4(uint32_t const *a) { // CHECK-LABEL: @test_vld1_u64_x2( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.uint64x1x2_t, align 8 -// CHECK-A32: ptr noalias sret(%struct.uint64x1x2_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.uint64x1x2_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.uint64x1x2_t, align 8 // CHECK: [[VLD1XN:%.*]] = call { <1 x i64>, <1 x i64> } @llvm.{{aarch64.neon.ld1x2|arm.neon.vld1x2}}.v1i64.p0(ptr %a) // CHECK: store { <1 x i64>, <1 x i64> } [[VLD1XN]], ptr [[__RET]] @@ -444,7 +444,7 @@ uint64x1x2_t test_vld1_u64_x2(uint64_t const *a) { // CHECK-LABEL: @test_vld1_u64_x3( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.uint64x1x3_t, align 8 -// CHECK-A32: ptr noalias sret(%struct.uint64x1x3_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.uint64x1x3_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.uint64x1x3_t, align 8 // CHECK: [[VLD1XN:%.*]] = call { <1 x i64>, <1 x i64>, <1 x i64> } @llvm.{{aarch64.neon.ld1x3|arm.neon.vld1x3}}.v1i64.p0(ptr %a) // CHECK: store { <1 x i64>, <1 x i64>, <1 x i64> } [[VLD1XN]], ptr [[__RET]] @@ -458,7 +458,7 @@ uint64x1x3_t test_vld1_u64_x3(uint64_t const *a) { // CHECK-LABEL: @test_vld1_u64_x4( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.uint64x1x4_t, align 8 -// CHECK-A32: ptr noalias sret(%struct.uint64x1x4_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.uint64x1x4_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.uint64x1x4_t, align 8 // CHECK: [[VLD1XN:%.*]] = call { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> } @llvm.{{aarch64.neon.ld1x4|arm.neon.vld1x4}}.v1i64.p0(ptr %a) // CHECK: store { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> } [[VLD1XN]], ptr [[__RET]] @@ -472,7 +472,7 @@ uint64x1x4_t test_vld1_u64_x4(uint64_t const *a) { // CHECK-LABEL: @test_vld1_u8_x2( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.uint8x8x2_t, align 8 -// CHECK-A32: ptr noalias sret(%struct.uint8x8x2_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.uint8x8x2_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.uint8x8x2_t, align 8 // CHECK: [[VLD1XN:%.*]] = call { <8 x i8>, <8 x i8> } @llvm.{{aarch64.neon.ld1x2|arm.neon.vld1x2}}.v8i8.p0(ptr %a) // CHECK: store { <8 x i8>, <8 x i8> } [[VLD1XN]], ptr [[__RET]] @@ -486,7 +486,7 @@ uint8x8x2_t test_vld1_u8_x2(uint8_t const *a) { // CHECK-LABEL: @test_vld1_u8_x3( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.uint8x8x3_t, align 8 -// CHECK-A32: ptr noalias sret(%struct.uint8x8x3_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.uint8x8x3_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.uint8x8x3_t, align 8 // CHECK: [[VLD1XN:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8> } @llvm.{{aarch64.neon.ld1x3|arm.neon.vld1x3}}.v8i8.p0(ptr %a) // CHECK: store { <8 x i8>, <8 x i8>, <8 x i8> } [[VLD1XN]], ptr [[__RET]] @@ -500,7 +500,7 @@ uint8x8x3_t test_vld1_u8_x3(uint8_t const *a) { // CHECK-LABEL: @test_vld1_u8_x4( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.uint8x8x4_t, align 8 -// CHECK-A32: ptr noalias sret(%struct.uint8x8x4_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.uint8x8x4_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.uint8x8x4_t, align 8 // CHECK: [[VLD1XN:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } @llvm.{{aarch64.neon.ld1x4|arm.neon.vld1x4}}.v8i8.p0(ptr %a) // CHECK: store { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } [[VLD1XN]], ptr [[__RET]] @@ -514,7 +514,7 @@ uint8x8x4_t test_vld1_u8_x4(uint8_t const *a) { // CHECK-LABEL: @test_vld1q_f16_x2( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.float16x8x2_t, align 16 -// CHECK-A32: ptr noalias sret(%struct.float16x8x2_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.float16x8x2_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.float16x8x2_t, align {{16|8}} // CHECK: [[VLD1XN:%.*]] = call { <8 x [[HALF:half|i16]]>, <8 x [[HALF]]> } @llvm.{{aarch64.neon.ld1x2.v8f16.p0|arm.neon.vld1x2.v8i16.p0}}(ptr %a) // CHECK: store { <8 x [[HALF]]>, <8 x [[HALF]]> } [[VLD1XN]], ptr [[__RET]] @@ -528,7 +528,7 @@ float16x8x2_t test_vld1q_f16_x2(float16_t const *a) { // CHECK-LABEL: @test_vld1q_f16_x3( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.float16x8x3_t, align 16 -// CHECK-A32: ptr noalias sret(%struct.float16x8x3_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.float16x8x3_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.float16x8x3_t, align {{16|8}} // CHECK: [[VLD1XN:%.*]] = call { <8 x [[HALF:half|i16]]>, <8 x [[HALF]]>, <8 x [[HALF]]> } @llvm.{{aarch64.neon.ld1x3.v8f16.p0|arm.neon.vld1x3.v8i16.p0}}(ptr %a) // CHECK: store { <8 x [[HALF]]>, <8 x [[HALF]]>, <8 x [[HALF]]> } [[VLD1XN]], ptr [[__RET]] @@ -542,7 +542,7 @@ float16x8x3_t test_vld1q_f16_x3(float16_t const *a) { // CHECK-LABEL: @test_vld1q_f16_x4( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.float16x8x4_t, align 16 -// CHECK-A32: ptr noalias sret(%struct.float16x8x4_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.float16x8x4_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.float16x8x4_t, align {{16|8}} // CHECK: [[VLD1XN:%.*]] = call { <8 x [[HALF:half|i16]]>, <8 x [[HALF]]>, <8 x [[HALF]]>, <8 x [[HALF]]> } @llvm.{{aarch64.neon.ld1x4.v8f16.p0|arm.neon.vld1x4.v8i16.p0}}(ptr %a) // CHECK: store { <8 x [[HALF]]>, <8 x [[HALF]]>, <8 x [[HALF]]>, <8 x [[HALF]]> } [[VLD1XN]], ptr [[__RET]] @@ -556,7 +556,7 @@ float16x8x4_t test_vld1q_f16_x4(float16_t const *a) { // CHECK-LABEL: @test_vld1q_f32_x2( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.float32x4x2_t, align 16 -// CHECK-A32: ptr noalias sret(%struct.float32x4x2_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.float32x4x2_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.float32x4x2_t, align {{16|8}} // CHECK: [[VLD1XN:%.*]] = call { <4 x float>, <4 x float> } @llvm.{{aarch64.neon.ld1x2|arm.neon.vld1x2}}.v4f32.p0(ptr %a) // CHECK: store { <4 x float>, <4 x float> } [[VLD1XN]], ptr [[__RET]] @@ -570,7 +570,7 @@ float32x4x2_t test_vld1q_f32_x2(float32_t const *a) { // CHECK-LABEL: @test_vld1q_f32_x3( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.float32x4x3_t, align 16 -// CHECK-A32: ptr noalias sret(%struct.float32x4x3_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.float32x4x3_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.float32x4x3_t, align {{16|8}} // CHECK: [[VLD1XN:%.*]] = call { <4 x float>, <4 x float>, <4 x float> } @llvm.{{aarch64.neon.ld1x3|arm.neon.vld1x3}}.v4f32.p0(ptr %a) // CHECK: store { <4 x float>, <4 x float>, <4 x float> } [[VLD1XN]], ptr [[__RET]] @@ -584,7 +584,7 @@ float32x4x3_t test_vld1q_f32_x3(float32_t const *a) { // CHECK-LABEL: @test_vld1q_f32_x4( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.float32x4x4_t, align 16 -// CHECK-A32: ptr noalias sret(%struct.float32x4x4_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.float32x4x4_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.float32x4x4_t, align {{16|8}} // CHECK: [[VLD1XN:%.*]] = call { <4 x float>, <4 x float>, <4 x float>, <4 x float> } @llvm.{{aarch64.neon.ld1x4|arm.neon.vld1x4}}.v4f32.p0(ptr %a) // CHECK: store { <4 x float>, <4 x float>, <4 x float>, <4 x float> } [[VLD1XN]], ptr [[__RET]] @@ -598,7 +598,7 @@ float32x4x4_t test_vld1q_f32_x4(float32_t const *a) { // CHECK-LABEL: @test_vld1q_p16_x2( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.poly16x8x2_t, align 16 -// CHECK-A32: ptr noalias sret(%struct.poly16x8x2_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.poly16x8x2_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.poly16x8x2_t, align {{16|8}} // CHECK: [[VLD1XN:%.*]] = call { <8 x i16>, <8 x i16> } @llvm.{{aarch64.neon.ld1x2|arm.neon.vld1x2}}.v8i16.p0(ptr %a) // CHECK: store { <8 x i16>, <8 x i16> } [[VLD1XN]], ptr [[__RET]] @@ -612,7 +612,7 @@ poly16x8x2_t test_vld1q_p16_x2(poly16_t const *a) { // CHECK-LABEL: @test_vld1q_p16_x3( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.poly16x8x3_t, align 16 -// CHECK-A32: ptr noalias sret(%struct.poly16x8x3_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.poly16x8x3_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.poly16x8x3_t, align {{16|8}} // CHECK: [[VLD1XN:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16> } @llvm.{{aarch64.neon.ld1x3|arm.neon.vld1x3}}.v8i16.p0(ptr %a) // CHECK: store { <8 x i16>, <8 x i16>, <8 x i16> } [[VLD1XN]], ptr [[__RET]] @@ -626,7 +626,7 @@ poly16x8x3_t test_vld1q_p16_x3(poly16_t const *a) { // CHECK-LABEL: @test_vld1q_p16_x4( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.poly16x8x4_t, align 16 -// CHECK-A32: ptr noalias sret(%struct.poly16x8x4_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.poly16x8x4_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.poly16x8x4_t, align {{16|8}} // CHECK: [[VLD1XN:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } @llvm.{{aarch64.neon.ld1x4|arm.neon.vld1x4}}.v8i16.p0(ptr %a) // CHECK: store { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } [[VLD1XN]], ptr [[__RET]] @@ -640,7 +640,7 @@ poly16x8x4_t test_vld1q_p16_x4(poly16_t const *a) { // CHECK-LABEL: @test_vld1q_p8_x2( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.poly8x16x2_t, align 16 -// CHECK-A32: ptr noalias sret(%struct.poly8x16x2_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.poly8x16x2_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.poly8x16x2_t, align {{16|8}} // CHECK: [[VLD1XN:%.*]] = call { <16 x i8>, <16 x i8> } @llvm.{{aarch64.neon.ld1x2|arm.neon.vld1x2}}.v16i8.p0(ptr %a) // CHECK: store { <16 x i8>, <16 x i8> } [[VLD1XN]], ptr [[__RET]] @@ -654,7 +654,7 @@ poly8x16x2_t test_vld1q_p8_x2(poly8_t const *a) { // CHECK-LABEL: @test_vld1q_p8_x3( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.poly8x16x3_t, align 16 -// CHECK-A32: ptr noalias sret(%struct.poly8x16x3_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.poly8x16x3_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.poly8x16x3_t, align {{16|8}} // CHECK: [[VLD1XN:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8> } @llvm.{{aarch64.neon.ld1x3|arm.neon.vld1x3}}.v16i8.p0(ptr %a) // CHECK: store { <16 x i8>, <16 x i8>, <16 x i8> } [[VLD1XN]], ptr [[__RET]] @@ -668,7 +668,7 @@ poly8x16x3_t test_vld1q_p8_x3(poly8_t const *a) { // CHECK-LABEL: @test_vld1q_p8_x4( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.poly8x16x4_t, align 16 -// CHECK-A32: ptr noalias sret(%struct.poly8x16x4_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.poly8x16x4_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.poly8x16x4_t, align {{16|8}} // CHECK: [[VLD1XN:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> } @llvm.{{aarch64.neon.ld1x4|arm.neon.vld1x4}}.v16i8.p0(ptr %a) // CHECK: store { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> } [[VLD1XN]], ptr [[__RET]] @@ -682,7 +682,7 @@ poly8x16x4_t test_vld1q_p8_x4(poly8_t const *a) { // CHECK-LABEL: @test_vld1q_s16_x2( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.int16x8x2_t, align 16 -// CHECK-A32: ptr noalias sret(%struct.int16x8x2_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.int16x8x2_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.int16x8x2_t, align {{16|8}} // CHECK: [[VLD1XN:%.*]] = call { <8 x i16>, <8 x i16> } @llvm.{{aarch64.neon.ld1x2|arm.neon.vld1x2}}.v8i16.p0(ptr %a) // CHECK: store { <8 x i16>, <8 x i16> } [[VLD1XN]], ptr [[__RET]] @@ -696,7 +696,7 @@ int16x8x2_t test_vld1q_s16_x2(int16_t const *a) { // CHECK-LABEL: @test_vld1q_s16_x3( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.int16x8x3_t, align 16 -// CHECK-A32: ptr noalias sret(%struct.int16x8x3_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.int16x8x3_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.int16x8x3_t, align {{16|8}} // CHECK: [[VLD1XN:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16> } @llvm.{{aarch64.neon.ld1x3|arm.neon.vld1x3}}.v8i16.p0(ptr %a) // CHECK: store { <8 x i16>, <8 x i16>, <8 x i16> } [[VLD1XN]], ptr [[__RET]] @@ -710,7 +710,7 @@ int16x8x3_t test_vld1q_s16_x3(int16_t const *a) { // CHECK-LABEL: @test_vld1q_s16_x4( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.int16x8x4_t, align 16 -// CHECK-A32: ptr noalias sret(%struct.int16x8x4_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.int16x8x4_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.int16x8x4_t, align {{16|8}} // CHECK: [[VLD1XN:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } @llvm.{{aarch64.neon.ld1x4|arm.neon.vld1x4}}.v8i16.p0(ptr %a) // CHECK: store { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } [[VLD1XN]], ptr [[__RET]] @@ -724,7 +724,7 @@ int16x8x4_t test_vld1q_s16_x4(int16_t const *a) { // CHECK-LABEL: @test_vld1q_s32_x2( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.int32x4x2_t, align 16 -// CHECK-A32: ptr noalias sret(%struct.int32x4x2_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.int32x4x2_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.int32x4x2_t, align {{16|8}} // CHECK: [[VLD1XN:%.*]] = call { <4 x i32>, <4 x i32> } @llvm.{{aarch64.neon.ld1x2|arm.neon.vld1x2}}.v4i32.p0(ptr %a) // CHECK: store { <4 x i32>, <4 x i32> } [[VLD1XN]], ptr [[__RET]] @@ -738,7 +738,7 @@ int32x4x2_t test_vld1q_s32_x2(int32_t const *a) { // CHECK-LABEL: @test_vld1q_s32_x3( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.int32x4x3_t, align 16 -// CHECK-A32: ptr noalias sret(%struct.int32x4x3_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.int32x4x3_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.int32x4x3_t, align {{16|8}} // CHECK: [[VLD1XN:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32> } @llvm.{{aarch64.neon.ld1x3|arm.neon.vld1x3}}.v4i32.p0(ptr %a) // CHECK: store { <4 x i32>, <4 x i32>, <4 x i32> } [[VLD1XN]], ptr [[__RET]] @@ -752,7 +752,7 @@ int32x4x3_t test_vld1q_s32_x3(int32_t const *a) { // CHECK-LABEL: @test_vld1q_s32_x4( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.int32x4x4_t, align 16 -// CHECK-A32: ptr noalias sret(%struct.int32x4x4_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.int32x4x4_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.int32x4x4_t, align {{16|8}} // CHECK: [[VLD1XN:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } @llvm.{{aarch64.neon.ld1x4|arm.neon.vld1x4}}.v4i32.p0(ptr %a) // CHECK: store { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } [[VLD1XN]], ptr [[__RET]] @@ -766,7 +766,7 @@ int32x4x4_t test_vld1q_s32_x4(int32_t const *a) { // CHECK-LABEL: @test_vld1q_s64_x2( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.int64x2x2_t, align 16 -// CHECK-A32: ptr noalias sret(%struct.int64x2x2_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.int64x2x2_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.int64x2x2_t, align {{16|8}} // CHECK: [[VLD1XN:%.*]] = call { <2 x i64>, <2 x i64> } @llvm.{{aarch64.neon.ld1x2|arm.neon.vld1x2}}.v2i64.p0(ptr %a) // CHECK: store { <2 x i64>, <2 x i64> } [[VLD1XN]], ptr [[__RET]] @@ -780,7 +780,7 @@ int64x2x2_t test_vld1q_s64_x2(int64_t const *a) { // CHECK-LABEL: @test_vld1q_s64_x3( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.int64x2x3_t, align 16 -// CHECK-A32: ptr noalias sret(%struct.int64x2x3_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.int64x2x3_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.int64x2x3_t, align {{16|8}} // CHECK: [[VLD1XN:%.*]] = call { <2 x i64>, <2 x i64>, <2 x i64> } @llvm.{{aarch64.neon.ld1x3|arm.neon.vld1x3}}.v2i64.p0(ptr %a) // CHECK: store { <2 x i64>, <2 x i64>, <2 x i64> } [[VLD1XN]], ptr [[__RET]] @@ -794,7 +794,7 @@ int64x2x3_t test_vld1q_s64_x3(int64_t const *a) { // CHECK-LABEL: @test_vld1q_s64_x4( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.int64x2x4_t, align 16 -// CHECK-A32: ptr noalias sret(%struct.int64x2x4_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.int64x2x4_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.int64x2x4_t, align {{16|8}} // CHECK: [[VLD1XN:%.*]] = call { <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64> } @llvm.{{aarch64.neon.ld1x4|arm.neon.vld1x4}}.v2i64.p0(ptr %a) // CHECK: store { <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64> } [[VLD1XN]], ptr [[__RET]] @@ -808,7 +808,7 @@ int64x2x4_t test_vld1q_s64_x4(int64_t const *a) { // CHECK-LABEL: @test_vld1q_s8_x2( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.int8x16x2_t, align 16 -// CHECK-A32: ptr noalias sret(%struct.int8x16x2_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.int8x16x2_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.int8x16x2_t, align {{16|8}} // CHECK: [[VLD1XN:%.*]] = call { <16 x i8>, <16 x i8> } @llvm.{{aarch64.neon.ld1x2|arm.neon.vld1x2}}.v16i8.p0(ptr %a) // CHECK: store { <16 x i8>, <16 x i8> } [[VLD1XN]], ptr [[__RET]] @@ -822,7 +822,7 @@ int8x16x2_t test_vld1q_s8_x2(int8_t const *a) { // CHECK-LABEL: @test_vld1q_s8_x3( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.int8x16x3_t, align 16 -// CHECK-A32: ptr noalias sret(%struct.int8x16x3_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.int8x16x3_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.int8x16x3_t, align {{16|8}} // CHECK: [[VLD1XN:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8> } @llvm.{{aarch64.neon.ld1x3|arm.neon.vld1x3}}.v16i8.p0(ptr %a) // CHECK: store { <16 x i8>, <16 x i8>, <16 x i8> } [[VLD1XN]], ptr [[__RET]] @@ -836,7 +836,7 @@ int8x16x3_t test_vld1q_s8_x3(int8_t const *a) { // CHECK-LABEL: @test_vld1q_s8_x4( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.int8x16x4_t, align 16 -// CHECK-A32: ptr noalias sret(%struct.int8x16x4_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.int8x16x4_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.int8x16x4_t, align {{16|8}} // CHECK: [[VLD1XN:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> } @llvm.{{aarch64.neon.ld1x4|arm.neon.vld1x4}}.v16i8.p0(ptr %a) // CHECK: store { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> } [[VLD1XN]], ptr [[__RET]] @@ -850,7 +850,7 @@ int8x16x4_t test_vld1q_s8_x4(int8_t const *a) { // CHECK-LABEL: @test_vld1q_u16_x2( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.uint16x8x2_t, align 16 -// CHECK-A32: ptr noalias sret(%struct.uint16x8x2_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.uint16x8x2_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.uint16x8x2_t, align {{16|8}} // CHECK: [[VLD1XN:%.*]] = call { <8 x i16>, <8 x i16> } @llvm.{{aarch64.neon.ld1x2|arm.neon.vld1x2}}.v8i16.p0(ptr %a) // CHECK: store { <8 x i16>, <8 x i16> } [[VLD1XN]], ptr [[__RET]] @@ -864,7 +864,7 @@ uint16x8x2_t test_vld1q_u16_x2(uint16_t const *a) { // CHECK-LABEL: @test_vld1q_u16_x3( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.uint16x8x3_t, align 16 -// CHECK-A32: ptr noalias sret(%struct.uint16x8x3_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.uint16x8x3_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.uint16x8x3_t, align {{16|8}} // CHECK: [[VLD1XN:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16> } @llvm.{{aarch64.neon.ld1x3|arm.neon.vld1x3}}.v8i16.p0(ptr %a) // CHECK: store { <8 x i16>, <8 x i16>, <8 x i16> } [[VLD1XN]], ptr [[__RET]] @@ -878,7 +878,7 @@ uint16x8x3_t test_vld1q_u16_x3(uint16_t const *a) { // CHECK-LABEL: @test_vld1q_u16_x4( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.uint16x8x4_t, align 16 -// CHECK-A32: ptr noalias sret(%struct.uint16x8x4_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.uint16x8x4_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.uint16x8x4_t, align {{16|8}} // CHECK: [[VLD1XN:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } @llvm.{{aarch64.neon.ld1x4|arm.neon.vld1x4}}.v8i16.p0(ptr %a) // CHECK: store { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } [[VLD1XN]], ptr [[__RET]] @@ -892,7 +892,7 @@ uint16x8x4_t test_vld1q_u16_x4(uint16_t const *a) { // CHECK-LABEL: @test_vld1q_u32_x2( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.uint32x4x2_t, align 16 -// CHECK-A32: ptr noalias sret(%struct.uint32x4x2_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.uint32x4x2_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.uint32x4x2_t, align {{16|8}} // CHECK: [[VLD1XN:%.*]] = call { <4 x i32>, <4 x i32> } @llvm.{{aarch64.neon.ld1x2|arm.neon.vld1x2}}.v4i32.p0(ptr %a) // CHECK: store { <4 x i32>, <4 x i32> } [[VLD1XN]], ptr [[__RET]] @@ -906,7 +906,7 @@ uint32x4x2_t test_vld1q_u32_x2(uint32_t const *a) { // CHECK-LABEL: @test_vld1q_u32_x3( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.uint32x4x3_t, align 16 -// CHECK-A32: ptr noalias sret(%struct.uint32x4x3_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.uint32x4x3_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.uint32x4x3_t, align {{16|8}} // CHECK: [[VLD1XN:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32> } @llvm.{{aarch64.neon.ld1x3|arm.neon.vld1x3}}.v4i32.p0(ptr %a) // CHECK: store { <4 x i32>, <4 x i32>, <4 x i32> } [[VLD1XN]], ptr [[__RET]] @@ -920,7 +920,7 @@ uint32x4x3_t test_vld1q_u32_x3(uint32_t const *a) { // CHECK-LABEL: @test_vld1q_u32_x4( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.uint32x4x4_t, align 16 -// CHECK-A32: ptr noalias sret(%struct.uint32x4x4_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.uint32x4x4_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.uint32x4x4_t, align {{16|8}} // CHECK: [[VLD1XN:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } @llvm.{{aarch64.neon.ld1x4|arm.neon.vld1x4}}.v4i32.p0(ptr %a) // CHECK: store { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } [[VLD1XN]], ptr [[__RET]] @@ -934,7 +934,7 @@ uint32x4x4_t test_vld1q_u32_x4(uint32_t const *a) { // CHECK-LABEL: @test_vld1q_u64_x2( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.uint64x2x2_t, align 16 -// CHECK-A32: ptr noalias sret(%struct.uint64x2x2_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.uint64x2x2_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.uint64x2x2_t, align {{16|8}} // CHECK: [[VLD1XN:%.*]] = call { <2 x i64>, <2 x i64> } @llvm.{{aarch64.neon.ld1x2|arm.neon.vld1x2}}.v2i64.p0(ptr %a) // CHECK: store { <2 x i64>, <2 x i64> } [[VLD1XN]], ptr [[__RET]] @@ -948,7 +948,7 @@ uint64x2x2_t test_vld1q_u64_x2(uint64_t const *a) { // CHECK-LABEL: @test_vld1q_u64_x3( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.uint64x2x3_t, align 16 -// CHECK-A32: ptr noalias sret(%struct.uint64x2x3_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.uint64x2x3_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.uint64x2x3_t, align {{16|8}} // CHECK: [[VLD1XN:%.*]] = call { <2 x i64>, <2 x i64>, <2 x i64> } @llvm.{{aarch64.neon.ld1x3|arm.neon.vld1x3}}.v2i64.p0(ptr %a) // CHECK: store { <2 x i64>, <2 x i64>, <2 x i64> } [[VLD1XN]], ptr [[__RET]] @@ -962,7 +962,7 @@ uint64x2x3_t test_vld1q_u64_x3(uint64_t const *a) { // CHECK-LABEL: @test_vld1q_u64_x4( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.uint64x2x4_t, align 16 -// CHECK-A32: ptr noalias sret(%struct.uint64x2x4_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.uint64x2x4_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.uint64x2x4_t, align {{16|8}} // CHECK: [[VLD1XN:%.*]] = call { <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64> } @llvm.{{aarch64.neon.ld1x4|arm.neon.vld1x4}}.v2i64.p0(ptr %a) // CHECK: store { <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64> } [[VLD1XN]], ptr [[__RET]] @@ -976,7 +976,7 @@ uint64x2x4_t test_vld1q_u64_x4(uint64_t const *a) { // CHECK-LABEL: @test_vld1q_u8_x2( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.uint8x16x2_t, align 16 -// CHECK-A32: ptr noalias sret(%struct.uint8x16x2_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.uint8x16x2_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.uint8x16x2_t, align {{16|8}} // CHECK: [[VLD1XN:%.*]] = call { <16 x i8>, <16 x i8> } @llvm.{{aarch64.neon.ld1x2|arm.neon.vld1x2}}.v16i8.p0(ptr %a) // CHECK: store { <16 x i8>, <16 x i8> } [[VLD1XN]], ptr [[__RET]] @@ -990,7 +990,7 @@ uint8x16x2_t test_vld1q_u8_x2(uint8_t const *a) { // CHECK-LABEL: @test_vld1q_u8_x3( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.uint8x16x3_t, align 16 -// CHECK-A32: ptr noalias sret(%struct.uint8x16x3_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.uint8x16x3_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.uint8x16x3_t, align {{16|8}} // CHECK: [[VLD1XN:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8> } @llvm.{{aarch64.neon.ld1x3|arm.neon.vld1x3}}.v16i8.p0(ptr %a) // CHECK: store { <16 x i8>, <16 x i8>, <16 x i8> } [[VLD1XN]], ptr [[__RET]] @@ -1004,7 +1004,7 @@ uint8x16x3_t test_vld1q_u8_x3(uint8_t const *a) { // CHECK-LABEL: @test_vld1q_u8_x4( // CHECK-A64: [[RETVAL:%.*]] = alloca %struct.uint8x16x4_t, align 16 -// CHECK-A32: ptr noalias sret(%struct.uint8x16x4_t) align 8 [[RETVAL:%.*]], +// CHECK-A32: ptr dead_on_unwind noalias writable sret(%struct.uint8x16x4_t) align 8 [[RETVAL:%.*]], // CHECK: [[__RET:%.*]] = alloca %struct.uint8x16x4_t, align {{16|8}} // CHECK: [[VLD1XN:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> } @llvm.{{aarch64.neon.ld1x4|arm.neon.vld1x4}}.v16i8.p0(ptr %a) // CHECK: store { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> } [[VLD1XN]], ptr [[__RET]] diff --git a/clang/test/CodeGen/arm-swiftcall.c b/clang/test/CodeGen/arm-swiftcall.c index 12bccb5087c8e8e5ea333ac91c1c44f31b494036..9fa607a968ccf0cfd4313fdc4613f42384ab8656 100644 --- a/clang/test/CodeGen/arm-swiftcall.c +++ b/clang/test/CodeGen/arm-swiftcall.c @@ -22,7 +22,7 @@ SWIFTCALL int indirect_result_2(OUT int *arg0, OUT float *arg1) { __builtin_unr typedef struct { char array[1024]; } struct_reallybig; SWIFTCALL struct_reallybig indirect_result_3(OUT int *arg0, OUT float *arg1) { __builtin_unreachable(); } -// CHECK-LABEL: define{{.*}} void @indirect_result_3(ptr noalias sret(%struct.struct_reallybig) {{.*}}, ptr noalias align 4 dereferenceable(4){{.*}}, ptr noalias align 4 dereferenceable(4){{.*}}) +// CHECK-LABEL: define{{.*}} void @indirect_result_3(ptr dead_on_unwind noalias writable sret(%struct.struct_reallybig) {{.*}}, ptr noalias align 4 dereferenceable(4){{.*}}, ptr noalias align 4 dereferenceable(4){{.*}}) SWIFTCALL void context_1(CONTEXT void *self) {} // CHECK-LABEL: define{{.*}} void @context_1(ptr swiftself @@ -258,7 +258,7 @@ typedef struct { } struct_big_1; TEST(struct_big_1) -// CHECK-LABEL: define{{.*}} void @return_struct_big_1({{.*}} noalias sret({{.*}}) +// CHECK-LABEL: define{{.*}} void @return_struct_big_1({{.*}} dead_on_unwind noalias writable sret({{.*}}) // Should not be byval. // CHECK-LABEL: define{{.*}} void @take_struct_big_1(ptr{{( %.*)?}}) @@ -553,7 +553,7 @@ typedef struct { double d4; } struct_d5; TEST(struct_d5) -// CHECK: define{{.*}} swiftcc void @return_struct_d5(ptr noalias sret([[STRUCT5:%.*]]) +// CHECK: define{{.*}} swiftcc void @return_struct_d5(ptr dead_on_unwind noalias writable sret([[STRUCT5:%.*]]) // CHECK: define{{.*}} swiftcc void @take_struct_d5(ptr typedef struct { @@ -703,7 +703,7 @@ typedef struct { long long l2; } struct_l3; TEST(struct_l3) -// CHECK: define{{.*}} swiftcc void @return_struct_l3(ptr noalias sret([[STRUCT:%.*]]) +// CHECK: define{{.*}} swiftcc void @return_struct_l3(ptr dead_on_unwind noalias writable sret([[STRUCT:%.*]]) // CHECK: define{{.*}} swiftcc void @take_struct_l3(ptr typedef struct { @@ -713,7 +713,7 @@ typedef struct { long long l3; } struct_l4; TEST(struct_l4) -// CHECK: define{{.*}} swiftcc void @return_struct_l4(ptr noalias sret([[STRUCT:%.*]]) +// CHECK: define{{.*}} swiftcc void @return_struct_l4(ptr dead_on_unwind noalias writable sret([[STRUCT:%.*]]) // CHECK: define{{.*}} swiftcc void @take_struct_l4(ptr typedef struct { @@ -724,7 +724,7 @@ typedef struct { long long l4; } struct_l5; TEST(struct_l5) -// CHECK: define{{.*}} swiftcc void @return_struct_l5(ptr noalias sret([[STRUCT5:%.*]]) +// CHECK: define{{.*}} swiftcc void @return_struct_l5(ptr dead_on_unwind noalias writable sret([[STRUCT5:%.*]]) // CHECK: define{{.*}} swiftcc void @take_struct_l5(ptr typedef struct { @@ -769,7 +769,7 @@ typedef struct { char16 c4; } struct_vc5; TEST(struct_vc5) -// CHECK: define{{.*}} swiftcc void @return_struct_vc5(ptr noalias sret([[STRUCT:%.*]]) +// CHECK: define{{.*}} swiftcc void @return_struct_vc5(ptr dead_on_unwind noalias writable sret([[STRUCT:%.*]]) // CHECK: define{{.*}} swiftcc void @take_struct_vc5(ptr typedef struct { @@ -814,7 +814,7 @@ typedef struct { short8 c4; } struct_vs5; TEST(struct_vs5) -// CHECK: define{{.*}} swiftcc void @return_struct_vs5(ptr noalias sret([[STRUCT:%.*]]) +// CHECK: define{{.*}} swiftcc void @return_struct_vs5(ptr dead_on_unwind noalias writable sret([[STRUCT:%.*]]) // CHECK: define{{.*}} swiftcc void @take_struct_vs5(ptr typedef struct { @@ -859,7 +859,7 @@ typedef struct { int4 c4; } struct_vi5; TEST(struct_vi5) -// CHECK: define{{.*}} swiftcc void @return_struct_vi5(ptr noalias sret([[STRUCT:%.*]]) +// CHECK: define{{.*}} swiftcc void @return_struct_vi5(ptr dead_on_unwind noalias writable sret([[STRUCT:%.*]]) // CHECK: define{{.*}} swiftcc void @take_struct_vi5(ptr typedef struct { @@ -887,7 +887,7 @@ typedef struct { long2 c4; } struct_vl5; TEST(struct_vl5) -// CHECK: define{{.*}} swiftcc void @return_struct_vl5(ptr noalias sret([[STRUCT:%.*]]) +// CHECK: define{{.*}} swiftcc void @return_struct_vl5(ptr dead_on_unwind noalias writable sret([[STRUCT:%.*]]) // CHECK: define{{.*}} swiftcc void @take_struct_vl5(ptr typedef struct { @@ -915,7 +915,7 @@ typedef struct { double2 c4; } struct_vd5; TEST(struct_vd5) -// CHECK: define{{.*}} swiftcc void @return_struct_vd5(ptr noalias sret([[STRUCT:%.*]]) +// CHECK: define{{.*}} swiftcc void @return_struct_vd5(ptr dead_on_unwind noalias writable sret([[STRUCT:%.*]]) // CHECK: define{{.*}} swiftcc void @take_struct_vd5(ptr typedef struct { @@ -939,7 +939,7 @@ typedef struct { double4 c2; } struct_vd43; TEST(struct_vd43) -// CHECK: define{{.*}} swiftcc void @return_struct_vd43(ptr noalias sret([[STRUCT:%.*]]) +// CHECK: define{{.*}} swiftcc void @return_struct_vd43(ptr dead_on_unwind noalias writable sret([[STRUCT:%.*]]) // CHECK: define{{.*}} swiftcc void @take_struct_vd43(ptr typedef struct { @@ -975,7 +975,7 @@ typedef struct { float4 c4; } struct_vf5; TEST(struct_vf5) -// CHECK: define{{.*}} swiftcc void @return_struct_vf5(ptr noalias sret([[STRUCT:%.*]]) +// CHECK: define{{.*}} swiftcc void @return_struct_vf5(ptr dead_on_unwind noalias writable sret([[STRUCT:%.*]]) // CHECK: define{{.*}} swiftcc void @take_struct_vf5(ptr typedef struct { diff --git a/clang/test/CodeGen/arm-varargs.c b/clang/test/CodeGen/arm-varargs.c index 17330262e6ad6111e7f7ff0fc39173581586ca5d..f754c7f52e59046e5cf659023be5a58f282b792a 100644 --- a/clang/test/CodeGen/arm-varargs.c +++ b/clang/test/CodeGen/arm-varargs.c @@ -23,7 +23,7 @@ struct bigstruct { }; struct bigstruct simple_struct(void) { -// CHECK-LABEL: define{{.*}} void @simple_struct(ptr noalias sret(%struct.bigstruct) align 4 %agg.result) +// CHECK-LABEL: define{{.*}} void @simple_struct(ptr dead_on_unwind noalias writable sret(%struct.bigstruct) align 4 %agg.result) return va_arg(the_list, struct bigstruct); // CHECK: [[CUR:%[a-z0-9._]+]] = load ptr, ptr @the_list, align 4 // CHECK: [[NEXT:%[a-z0-9._]+]] = getelementptr inbounds i8, ptr [[CUR]], i32 40 @@ -38,7 +38,7 @@ struct aligned_bigstruct { }; struct aligned_bigstruct simple_aligned_struct(void) { -// CHECK-LABEL: define{{.*}} void @simple_aligned_struct(ptr noalias sret(%struct.aligned_bigstruct) align 8 %agg.result) +// CHECK-LABEL: define{{.*}} void @simple_aligned_struct(ptr dead_on_unwind noalias writable sret(%struct.aligned_bigstruct) align 8 %agg.result) return va_arg(the_list, struct aligned_bigstruct); // CHECK: [[CUR:%[a-z0-9._]+]] = load ptr, ptr @the_list, align 4 // CHECK: [[CUR_INT_ADD:%[a-z0-9._]+]] = getelementptr inbounds i8, ptr [[CUR]], i32 7 @@ -66,7 +66,7 @@ struct hfa { }; struct hfa simple_hfa(void) { -// CHECK-LABEL: define{{.*}} void @simple_hfa(ptr noalias sret(%struct.hfa) align 4 %agg.result) +// CHECK-LABEL: define{{.*}} void @simple_hfa(ptr dead_on_unwind noalias writable sret(%struct.hfa) align 4 %agg.result) return va_arg(the_list, struct hfa); // CHECK: [[CUR:%[a-z0-9._]+]] = load ptr, ptr @the_list, align 4 // CHECK: [[NEXT:%[a-z0-9._]+]] = getelementptr inbounds i8, ptr [[CUR]], i32 8 @@ -159,7 +159,7 @@ typedef struct __attribute__((aligned(16))) { int val; } overaligned_int_struct; overaligned_int_struct overaligned_int_struct_test(void) { -// CHECK-LABEL: define{{.*}} void @overaligned_int_struct_test(ptr noalias sret(%struct.overaligned_int_struct) align 16 %agg.result) +// CHECK-LABEL: define{{.*}} void @overaligned_int_struct_test(ptr dead_on_unwind noalias writable sret(%struct.overaligned_int_struct) align 16 %agg.result) return va_arg(the_list, overaligned_int_struct); // CHECK: [[CUR:%[a-z0-9._]+]] = load ptr, ptr @the_list, align 4 // CHECK: [[NEXT:%[a-z0-9._]+]] = getelementptr inbounds i8, ptr [[CUR]], i32 16 @@ -172,7 +172,7 @@ typedef struct __attribute__((packed,aligned(2))) { long long val; } underaligned_long_long_struct; underaligned_long_long_struct underaligned_long_long_struct_test(void) { -// CHECK-LABEL: define{{.*}} void @underaligned_long_long_struct_test(ptr noalias sret(%struct.underaligned_long_long_struct) align 2 %agg.result) +// CHECK-LABEL: define{{.*}} void @underaligned_long_long_struct_test(ptr dead_on_unwind noalias writable sret(%struct.underaligned_long_long_struct) align 2 %agg.result) return va_arg(the_list, underaligned_long_long_struct); // CHECK: [[CUR:%[a-z0-9._]+]] = load ptr, ptr @the_list, align 4 // CHECK: [[NEXT:%[a-z0-9._]+]] = getelementptr inbounds i8, ptr [[CUR]], i32 8 @@ -185,7 +185,7 @@ typedef struct __attribute__((aligned(16))) { long long val; } overaligned_long_long_struct; overaligned_long_long_struct overaligned_long_long_struct_test(void) { -// CHECK-LABEL: define{{.*}} void @overaligned_long_long_struct_test(ptr noalias sret(%struct.overaligned_long_long_struct) align 16 %agg.result) +// CHECK-LABEL: define{{.*}} void @overaligned_long_long_struct_test(ptr dead_on_unwind noalias writable sret(%struct.overaligned_long_long_struct) align 16 %agg.result) return va_arg(the_list, overaligned_long_long_struct); // CHECK: [[CUR:%[a-z0-9._]+]] = load ptr, ptr @the_list, align 4 // CHECK: [[CUR_INT_ADD:%[a-z0-9._]+]] = getelementptr inbounds i8, ptr [[CUR]], i32 7 @@ -219,7 +219,7 @@ typedef struct { int val __attribute__((aligned(16))); } overaligned_int_struct_member; overaligned_int_struct_member overaligned_int_struct_member_test(void) { -// CHECK-LABEL: define{{.*}} void @overaligned_int_struct_member_test(ptr noalias sret(%struct.overaligned_int_struct_member) align 16 %agg.result) +// CHECK-LABEL: define{{.*}} void @overaligned_int_struct_member_test(ptr dead_on_unwind noalias writable sret(%struct.overaligned_int_struct_member) align 16 %agg.result) return va_arg(the_list, overaligned_int_struct_member); // CHECK: [[CUR:%[a-z0-9._]+]] = load ptr, ptr @the_list, align 4 // CHECK: [[CUR_INT_ADD:%[a-z0-9._]+]] = getelementptr inbounds i8, ptr [[CUR]], i32 7 @@ -234,7 +234,7 @@ typedef struct { long long val __attribute__((packed,aligned(2))); } underaligned_long_long_struct_member; underaligned_long_long_struct_member underaligned_long_long_struct_member_test(void) { -// CHECK-LABEL: define{{.*}} void @underaligned_long_long_struct_member_test(ptr noalias sret(%struct.underaligned_long_long_struct_member) align 2 %agg.result) +// CHECK-LABEL: define{{.*}} void @underaligned_long_long_struct_member_test(ptr dead_on_unwind noalias writable sret(%struct.underaligned_long_long_struct_member) align 2 %agg.result) return va_arg(the_list, underaligned_long_long_struct_member); // CHECK: [[CUR:%[a-z0-9._]+]] = load ptr, ptr @the_list, align 4 // CHECK: [[NEXT:%[a-z0-9._]+]] = getelementptr inbounds i8, ptr [[CUR]], i32 8 @@ -247,7 +247,7 @@ typedef struct { long long val __attribute__((aligned(16))); } overaligned_long_long_struct_member; overaligned_long_long_struct_member overaligned_long_long_struct_member_test(void) { -// CHECK-LABEL: define{{.*}} void @overaligned_long_long_struct_member_test(ptr noalias sret(%struct.overaligned_long_long_struct_member) align 16 %agg.result) +// CHECK-LABEL: define{{.*}} void @overaligned_long_long_struct_member_test(ptr dead_on_unwind noalias writable sret(%struct.overaligned_long_long_struct_member) align 16 %agg.result) return va_arg(the_list, overaligned_long_long_struct_member); // CHECK: [[CUR:%[a-z0-9._]+]] = load ptr, ptr @the_list, align 4 // CHECK: [[CUR_INT_ADD:%[a-z0-9._]+]] = getelementptr inbounds i8, ptr [[CUR]], i32 7 diff --git a/clang/test/CodeGen/arm-vector-arguments.c b/clang/test/CodeGen/arm-vector-arguments.c index a92e5a84798bc227a580aa68fce20eb9fdc0d0c7..0e3abfb7e5a06f8ae13b2af75cabeb417bfcc25c 100644 --- a/clang/test/CodeGen/arm-vector-arguments.c +++ b/clang/test/CodeGen/arm-vector-arguments.c @@ -9,7 +9,7 @@ #include -// CHECK: define{{.*}} void @f0(ptr noalias sret(%struct.int8x16x2_t) align 16 %agg.result, <16 x i8> noundef %{{.*}}, <16 x i8> noundef %{{.*}}) +// CHECK: define{{.*}} void @f0(ptr dead_on_unwind noalias writable sret(%struct.int8x16x2_t) align 16 %agg.result, <16 x i8> noundef %{{.*}}, <16 x i8> noundef %{{.*}}) int8x16x2_t f0(int8x16_t a0, int8x16_t a1) { return vzipq_s8(a0, a1); } @@ -25,7 +25,7 @@ typedef float T_float32x16 __attribute__ ((__vector_size__ (64))); T_float32x2 f1_0(T_float32x2 a0) { return a0; } // CHECK: define{{.*}} <4 x float> @f1_1(<4 x float> noundef %{{.*}}) T_float32x4 f1_1(T_float32x4 a0) { return a0; } -// CHECK: define{{.*}} void @f1_2(ptr noalias sret(<8 x float>) align 32 %{{.*}}, <8 x float> noundef %{{.*}}) +// CHECK: define{{.*}} void @f1_2(ptr dead_on_unwind noalias writable sret(<8 x float>) align 32 %{{.*}}, <8 x float> noundef %{{.*}}) T_float32x8 f1_2(T_float32x8 a0) { return a0; } -// CHECK: define{{.*}} void @f1_3(ptr noalias sret(<16 x float>) align 64 %{{.*}}, <16 x float> noundef %{{.*}}) +// CHECK: define{{.*}} void @f1_3(ptr dead_on_unwind noalias writable sret(<16 x float>) align 64 %{{.*}}, <16 x float> noundef %{{.*}}) T_float32x16 f1_3(T_float32x16 a0) { return a0; } diff --git a/clang/test/CodeGen/arm-vfp16-arguments.c b/clang/test/CodeGen/arm-vfp16-arguments.c index 59120c1cc7f1482c771cc753cfda48047d1c6b9e..da034626024f82c633adf035ed7c45a3d0aa3e58 100644 --- a/clang/test/CodeGen/arm-vfp16-arguments.c +++ b/clang/test/CodeGen/arm-vfp16-arguments.c @@ -71,6 +71,6 @@ void test_hfa(hfa_t a) {} hfa_t ghfa; hfa_t test_ret_hfa(void) { return ghfa; } -// CHECK-SOFT: define{{.*}} void @test_ret_hfa(ptr noalias nocapture writeonly sret(%struct.hfa_t) align 8 %agg.result) +// CHECK-SOFT: define{{.*}} void @test_ret_hfa(ptr dead_on_unwind noalias nocapture writable writeonly sret(%struct.hfa_t) align 8 %agg.result) // CHECK-HARD: define{{.*}} arm_aapcs_vfpcc [2 x <2 x i32>] @test_ret_hfa() // CHECK-FULL: define{{.*}} arm_aapcs_vfpcc %struct.hfa_t @test_ret_hfa() diff --git a/clang/test/CodeGen/arm-vfp16-arguments2.cpp b/clang/test/CodeGen/arm-vfp16-arguments2.cpp index 2ba0c0d349ab7be63ead547face5679c74d1c6bc..6221e85e856b40a0b29c5a632570e07f7f7fccda 100644 --- a/clang/test/CodeGen/arm-vfp16-arguments2.cpp +++ b/clang/test/CodeGen/arm-vfp16-arguments2.cpp @@ -37,27 +37,27 @@ struct S5 : B1 { B1 M[1]; }; -// CHECK-SOFT: define{{.*}} void @_Z2f12S1(ptr noalias nocapture writeonly sret(%struct.S1) align 8 %agg.result, [2 x i64] %s1.coerce) +// CHECK-SOFT: define{{.*}} void @_Z2f12S1(ptr dead_on_unwind noalias nocapture writable writeonly sret(%struct.S1) align 8 %agg.result, [2 x i64] %s1.coerce) // CHECK-HARD: define{{.*}} arm_aapcs_vfpcc [2 x <2 x i32>] @_Z2f12S1([2 x <2 x i32>] returned %s1.coerce) // CHECK-FULL: define{{.*}} arm_aapcs_vfpcc %struct.S1 @_Z2f12S1(%struct.S1 returned %s1.coerce) struct S1 f1(struct S1 s1) { return s1; } -// CHECK-SOFT: define{{.*}} void @_Z2f22S2(ptr noalias nocapture writeonly sret(%struct.S2) align 8 %agg.result, [4 x i32] %s2.coerce) +// CHECK-SOFT: define{{.*}} void @_Z2f22S2(ptr dead_on_unwind noalias nocapture writable writeonly sret(%struct.S2) align 8 %agg.result, [4 x i32] %s2.coerce) // CHECK-HARD: define{{.*}} arm_aapcs_vfpcc [2 x <2 x i32>] @_Z2f22S2([2 x <2 x i32>] returned %s2.coerce) // CHECK-FULL: define{{.*}} arm_aapcs_vfpcc %struct.S2 @_Z2f22S2(%struct.S2 returned %s2.coerce) struct S2 f2(struct S2 s2) { return s2; } -// CHECK-SOFT: define{{.*}} void @_Z2f32S3(ptr noalias nocapture writeonly sret(%struct.S3) align 8 %agg.result, [2 x i64] %s3.coerce) +// CHECK-SOFT: define{{.*}} void @_Z2f32S3(ptr dead_on_unwind noalias nocapture writable writeonly sret(%struct.S3) align 8 %agg.result, [2 x i64] %s3.coerce) // CHECK-HARD: define{{.*}} arm_aapcs_vfpcc [2 x <2 x i32>] @_Z2f32S3([2 x <2 x i32>] returned %s3.coerce) // CHECK-FULL: define{{.*}} arm_aapcs_vfpcc %struct.S3 @_Z2f32S3(%struct.S3 returned %s3.coerce) struct S3 f3(struct S3 s3) { return s3; } -// CHECK-SOFT: define{{.*}} void @_Z2f42S4(ptr noalias nocapture writeonly sret(%struct.S4) align 8 %agg.result, [2 x i64] %s4.coerce) +// CHECK-SOFT: define{{.*}} void @_Z2f42S4(ptr dead_on_unwind noalias nocapture writable writeonly sret(%struct.S4) align 8 %agg.result, [2 x i64] %s4.coerce) // CHECK-HARD: define{{.*}} arm_aapcs_vfpcc [2 x <2 x i32>] @_Z2f42S4([2 x <2 x i32>] returned %s4.coerce) // CHECK-FULL: define{{.*}} arm_aapcs_vfpcc %struct.S4 @_Z2f42S4(%struct.S4 returned %s4.coerce) struct S4 f4(struct S4 s4) { return s4; } -// CHECK-SOFT: define{{.*}} void @_Z2f52S5(ptr noalias nocapture writeonly sret(%struct.S5) align 8 %agg.result, [2 x i64] %s5.coerce) +// CHECK-SOFT: define{{.*}} void @_Z2f52S5(ptr dead_on_unwind noalias nocapture writable writeonly sret(%struct.S5) align 8 %agg.result, [2 x i64] %s5.coerce) // CHECK-HARD: define{{.*}} arm_aapcs_vfpcc %struct.S5 @_Z2f52S5(%struct.S5 returned %s5.coerce) // CHECK-FULL: define{{.*}} arm_aapcs_vfpcc %struct.S5 @_Z2f52S5(%struct.S5 returned %s5.coerce) struct S5 f5(struct S5 s5) { return s5; } diff --git a/clang/test/CodeGen/arm64-arguments.c b/clang/test/CodeGen/arm64-arguments.c index caa71ced0a8aed151bb0f20b8bc478e4c598f217..8ed9d952f80c8c87b091fcb39fbb331ee0ea8608 100644 --- a/clang/test/CodeGen/arm64-arguments.c +++ b/clang/test/CodeGen/arm64-arguments.c @@ -226,9 +226,9 @@ T_float32x2 f1_0(T_float32x2 a0) { return a0; } // CHECK: define{{.*}} <4 x float> @f1_1(<4 x float> noundef %{{.*}}) T_float32x4 f1_1(T_float32x4 a0) { return a0; } // Vector with length bigger than 16-byte is illegal and is passed indirectly. -// CHECK: define{{.*}} void @f1_2(ptr noalias sret(<8 x float>) align 16 %{{.*}}, ptr noundef %0) +// CHECK: define{{.*}} void @f1_2(ptr dead_on_unwind noalias writable sret(<8 x float>) align 16 %{{.*}}, ptr noundef %0) T_float32x8 f1_2(T_float32x8 a0) { return a0; } -// CHECK: define{{.*}} void @f1_3(ptr noalias sret(<16 x float>) align 16 %{{.*}}, ptr noundef %0) +// CHECK: define{{.*}} void @f1_3(ptr dead_on_unwind noalias writable sret(<16 x float>) align 16 %{{.*}}, ptr noundef %0) T_float32x16 f1_3(T_float32x16 a0) { return a0; } // Testing alignment with aggregates: HFA, aggregates with size <= 16 bytes and diff --git a/clang/test/CodeGen/arm64-microsoft-arguments.cpp b/clang/test/CodeGen/arm64-microsoft-arguments.cpp index a9ae6911b16e339651ab74d11aec0c8598ef7cf8..e8309888dcfe21bb8563db2d57ac8ee70578446d 100644 --- a/clang/test/CodeGen/arm64-microsoft-arguments.cpp +++ b/clang/test/CodeGen/arm64-microsoft-arguments.cpp @@ -28,8 +28,8 @@ S2 f2() { } // Pass and return for type size > 16 bytes. -// CHECK: define {{.*}} void @{{.*}}f3{{.*}}(ptr noalias sret(%struct.S3) align 4 %agg.result) -// CHECK: call void {{.*}}func3{{.*}}(ptr sret(%struct.S3) align 4 %agg.result, ptr noundef %agg.tmp) +// CHECK: define {{.*}} void @{{.*}}f3{{.*}}(ptr dead_on_unwind noalias writable sret(%struct.S3) align 4 %agg.result) +// CHECK: call void {{.*}}func3{{.*}}(ptr dead_on_unwind writable sret(%struct.S3) align 4 %agg.result, ptr noundef %agg.tmp) struct S3 { int a[5]; }; @@ -42,8 +42,8 @@ S3 f3() { // Pass and return aggregate (of size < 16 bytes) with non-trivial destructor. // Passed directly but returned indirectly. -// CHECK: define {{.*}} void {{.*}}f4{{.*}}(ptr inreg noalias sret(%struct.S4) align 4 %agg.result) -// CHECK: call void {{.*}}func4{{.*}}(ptr inreg sret(%struct.S4) align 4 %agg.result, [2 x i64] %0) +// CHECK: define {{.*}} void {{.*}}f4{{.*}}(ptr dead_on_unwind inreg noalias writable sret(%struct.S4) align 4 %agg.result) +// CHECK: call void {{.*}}func4{{.*}}(ptr dead_on_unwind inreg writable sret(%struct.S4) align 4 %agg.result, [2 x i64] %0) struct S4 { int a[3]; ~S4(); @@ -56,8 +56,8 @@ S4 f4() { } // Pass and return from instance method called from instance method. -// CHECK: define {{.*}} void @{{.*}}bar@Q1{{.*}}(ptr {{[^,]*}} %this, ptr inreg noalias sret(%class.P1) align 1 %agg.result) -// CHECK: call void {{.*}}foo@P1{{.*}}(ptr noundef{{[^,]*}} %ref.tmp, ptr inreg sret(%class.P1) align 1 %agg.result, i8 %0) +// CHECK: define {{.*}} void @{{.*}}bar@Q1{{.*}}(ptr {{[^,]*}} %this, ptr dead_on_unwind inreg noalias writable sret(%class.P1) align 1 %agg.result) +// CHECK: call void {{.*}}foo@P1{{.*}}(ptr noundef{{[^,]*}} %ref.tmp, ptr dead_on_unwind inreg writable sret(%class.P1) align 1 %agg.result, i8 %0) class P1 { public: @@ -76,7 +76,7 @@ P1 Q1::bar() { // Pass and return from instance method called from free function. // CHECK: define {{.*}} void {{.*}}bar{{.*}}() -// CHECK: call void {{.*}}foo@P2{{.*}}(ptr noundef{{[^,]*}} %ref.tmp, ptr inreg sret(%class.P2) align 1 %retval, i8 %0) +// CHECK: call void {{.*}}foo@P2{{.*}}(ptr noundef{{[^,]*}} %ref.tmp, ptr dead_on_unwind inreg writable sret(%class.P2) align 1 %retval, i8 %0) class P2 { public: P2 foo(P2 x); @@ -89,8 +89,8 @@ P2 bar() { // Pass and return an object with a user-provided constructor (passed directly, // returned indirectly) -// CHECK: define {{.*}} void @{{.*}}f5{{.*}}(ptr inreg noalias sret(%struct.S5) align 4 %agg.result) -// CHECK: call void {{.*}}func5{{.*}}(ptr inreg sret(%struct.S5) align 4 %agg.result, i64 {{.*}}) +// CHECK: define {{.*}} void @{{.*}}f5{{.*}}(ptr dead_on_unwind inreg noalias writable sret(%struct.S5) align 4 %agg.result) +// CHECK: call void {{.*}}func5{{.*}}(ptr dead_on_unwind inreg writable sret(%struct.S5) align 4 %agg.result, i64 {{.*}}) struct S5 { S5(); int x; @@ -146,8 +146,8 @@ struct S8 { int y; }; -// CHECK: define {{.*}} void {{.*}}?f8{{.*}}(ptr inreg noalias sret(%struct.S8) align 4 {{.*}}) -// CHECK: call void {{.*}}func8{{.*}}(ptr inreg sret(%struct.S8) align 4 {{.*}}, i64 {{.*}}) +// CHECK: define {{.*}} void {{.*}}?f8{{.*}}(ptr dead_on_unwind inreg noalias writable sret(%struct.S8) align 4 {{.*}}) +// CHECK: call void {{.*}}func8{{.*}}(ptr dead_on_unwind inreg writable sret(%struct.S8) align 4 {{.*}}, i64 {{.*}}) S8 func8(S8 x); S8 f8() { S8 x; @@ -157,8 +157,8 @@ S8 f8() { // Pass and return an object with a non-trivial copy-assignment operator and // a trivial copy constructor (passed directly, returned indirectly) -// CHECK: define {{.*}} void @"?f9@@YA?AUS9@@XZ"(ptr inreg noalias sret(%struct.S9) align 4 {{.*}}) -// CHECK: call void {{.*}}func9{{.*}}(ptr inreg sret(%struct.S9) align 4 {{.*}}, i64 {{.*}}) +// CHECK: define {{.*}} void @"?f9@@YA?AUS9@@XZ"(ptr dead_on_unwind inreg noalias writable sret(%struct.S9) align 4 {{.*}}) +// CHECK: call void {{.*}}func9{{.*}}(ptr dead_on_unwind inreg writable sret(%struct.S9) align 4 {{.*}}, i64 {{.*}}) struct S9 { S9& operator=(const S9&); int x; @@ -174,8 +174,8 @@ S9 f9() { // Pass and return an object with a base class (passed directly, returned // indirectly). -// CHECK: define dso_local void {{.*}}f10{{.*}}(ptr inreg noalias sret(%struct.S10) align 4 {{.*}}) -// CHECK: call void {{.*}}func10{{.*}}(ptr inreg sret(%struct.S10) align 4 {{.*}}, [2 x i64] {{.*}}) +// CHECK: define dso_local void {{.*}}f10{{.*}}(ptr dead_on_unwind inreg noalias writable sret(%struct.S10) align 4 {{.*}}) +// CHECK: call void {{.*}}func10{{.*}}(ptr dead_on_unwind inreg writable sret(%struct.S10) align 4 {{.*}}, [2 x i64] {{.*}}) struct S10 : public S1 { int x; }; @@ -189,8 +189,8 @@ S10 f10() { // Pass and return a non aggregate object exceeding > 128 bits (passed // indirectly, returned indirectly) -// CHECK: define dso_local void {{.*}}f11{{.*}}(ptr inreg noalias sret(%struct.S11) align 8 {{.*}}) -// CHECK: call void {{.*}}func11{{.*}}(ptr inreg sret(%struct.S11) align 8 {{.*}}, ptr {{.*}}) +// CHECK: define dso_local void {{.*}}f11{{.*}}(ptr dead_on_unwind inreg noalias writable sret(%struct.S11) align 8 {{.*}}) +// CHECK: call void {{.*}}func11{{.*}}(ptr dead_on_unwind inreg writable sret(%struct.S11) align 8 {{.*}}, ptr {{.*}}) struct S11 { virtual void f(); int a[5]; diff --git a/clang/test/CodeGen/arm64_32.c b/clang/test/CodeGen/arm64_32.c index 31d94c610704a823c809f9bc18d8ce60f54d8349..f7473610d30d9eceab04b2616fe4148a8068e5ab 100644 --- a/clang/test/CodeGen/arm64_32.c +++ b/clang/test/CodeGen/arm64_32.c @@ -27,4 +27,4 @@ long double LongDoubleVar = 0.0; typedef float __attribute__((ext_vector_type(16))) v16f32; v16f32 func(v16f32 in) { return in; } -// CHECK: define{{.*}} void @func(ptr noalias sret(<16 x float>) align 16 {{%.*}}, <16 x float> noundef {{%.*}}) +// CHECK: define{{.*}} void @func(ptr dead_on_unwind noalias writable sret(<16 x float>) align 16 {{%.*}}, <16 x float> noundef {{%.*}}) diff --git a/clang/test/CodeGen/armv7k-abi.c b/clang/test/CodeGen/armv7k-abi.c index e070d5a9c704165863f02254430d7a704b6a331e..fd18dafa7d03f5a070e48790dec4902c1dad48ac 100644 --- a/clang/test/CodeGen/armv7k-abi.c +++ b/clang/test/CodeGen/armv7k-abi.c @@ -42,7 +42,7 @@ typedef struct { // CHECK: define{{.*}} void @big_struct_indirect(ptr noundef %b) void big_struct_indirect(BigStruct b) {} -// CHECK: define{{.*}} void @return_big_struct_indirect(ptr noalias sret +// CHECK: define{{.*}} void @return_big_struct_indirect(ptr dead_on_unwind noalias writable sret BigStruct return_big_struct_indirect() {} // Structs smaller than 16 bytes should be passed directly, and coerced to diff --git a/clang/test/CodeGen/attr-counted-by.c b/clang/test/CodeGen/attr-counted-by.c new file mode 100644 index 0000000000000000000000000000000000000000..74d5457e398b91dedfb0a7dd052202622d0e22e8 --- /dev/null +++ b/clang/test/CodeGen/attr-counted-by.c @@ -0,0 +1,1828 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 3 +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -DCOUNTED_BY -O2 -Wall -fsanitize=array-bounds,object-size,local-bounds -fstrict-flex-arrays=3 -emit-llvm -o - %s | FileCheck --check-prefix=SANITIZE-WITH-ATTR %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -DCOUNTED_BY -O2 -Wall -fstrict-flex-arrays=3 -emit-llvm -o - %s | FileCheck --check-prefix=NO-SANITIZE-WITH-ATTR %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O2 -Wall -fsanitize=array-bounds,object-size,local-bounds -fstrict-flex-arrays=3 -emit-llvm -o - %s | FileCheck --check-prefix=SANITIZE-WITHOUT-ATTR %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O2 -Wall -fstrict-flex-arrays=3 -emit-llvm -o - %s | FileCheck --check-prefix=NO-SANITIZE-WITHOUT-ATTR %s + +#if !__has_attribute(counted_by) +#error "has attribute broken" +#endif + +#ifdef COUNTED_BY +#define __counted_by(member) __attribute__((__counted_by__(member))) +#else +#define __counted_by(member) +#endif + +#define DECLARE_FLEX_ARRAY(TYPE, NAME) \ + struct { \ + struct { } __empty_ ## NAME; \ + TYPE NAME[]; \ + } + +#define DECLARE_BOUNDED_FLEX_ARRAY(COUNT_TYPE, COUNT, TYPE, NAME) \ + struct { \ + COUNT_TYPE COUNT; \ + TYPE NAME[] __counted_by(COUNT); \ + } + +#define DECLARE_FLEX_ARRAY_COUNTED_BY(TYPE, NAME, COUNTED_BY) \ + struct { \ + struct { } __empty_ ## NAME; \ + TYPE NAME[] __counted_by(COUNTED_BY); \ + } + +typedef long unsigned int size_t; + +struct annotated { + unsigned long flags; + int count; + int array[] __counted_by(count); +}; + +struct union_of_fams { + unsigned long flags; + union { + /* count member type intentionally mismatched to induce padding */ + DECLARE_BOUNDED_FLEX_ARRAY(int, count_bytes, unsigned char, bytes); + DECLARE_BOUNDED_FLEX_ARRAY(unsigned char, count_ints, unsigned char, ints); + DECLARE_FLEX_ARRAY(unsigned char, unsafe); + }; +}; + +struct anon_struct { + unsigned long flags; + size_t count; + DECLARE_FLEX_ARRAY_COUNTED_BY(int, array, count); +}; + +// SANITIZE-WITH-ATTR-LABEL: define dso_local void @test1( +// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]], i32 noundef [[VAL:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { +// SANITIZE-WITH-ATTR-NEXT: entry: +// SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 +// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_GEP:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED:%.*]], ptr [[P]], i64 0, i32 1 +// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOTCOUNTED_BY_GEP]], align 4 +// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = zext i32 [[DOTCOUNTED_BY_LOAD]] to i64, !nosanitize [[META2:![0-9]+]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp ult i64 [[IDXPROM]], [[TMP0]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP1]], label [[CONT3:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF3:![0-9]+]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR: handler.out_of_bounds: +// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB2:[0-9]+]], i64 [[IDXPROM]]) #[[ATTR10:[0-9]+]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META2]] +// SANITIZE-WITH-ATTR: cont3: +// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED]], ptr [[P]], i64 0, i32 2, i64 [[IDXPROM]] +// SANITIZE-WITH-ATTR-NEXT: store i32 [[VAL]], ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA4:![0-9]+]] +// SANITIZE-WITH-ATTR-NEXT: ret void +// +// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local void @test1( +// NO-SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef writeonly [[P:%.*]], i32 noundef [[INDEX:%.*]], i32 noundef [[VAL:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { +// NO-SANITIZE-WITH-ATTR-NEXT: entry: +// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 +// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED:%.*]], ptr [[P]], i64 0, i32 2, i64 [[IDXPROM]] +// NO-SANITIZE-WITH-ATTR-NEXT: store i32 [[VAL]], ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2:![0-9]+]] +// NO-SANITIZE-WITH-ATTR-NEXT: ret void +// +// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test1( +// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]], i32 noundef [[VAL:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { +// SANITIZE-WITHOUT-ATTR-NEXT: entry: +// SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 +// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED:%.*]], ptr [[P]], i64 0, i32 2, i64 [[IDXPROM]] +// SANITIZE-WITHOUT-ATTR-NEXT: store i32 [[VAL]], ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2:![0-9]+]] +// SANITIZE-WITHOUT-ATTR-NEXT: ret void +// +// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test1( +// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nocapture noundef writeonly [[P:%.*]], i32 noundef [[INDEX:%.*]], i32 noundef [[VAL:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { +// NO-SANITIZE-WITHOUT-ATTR-NEXT: entry: +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED:%.*]], ptr [[P]], i64 0, i32 2, i64 [[IDXPROM]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: store i32 [[VAL]], ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2:![0-9]+]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret void +// +void test1(struct annotated *p, int index, int val) { + p->array[index] = val; +} + +// SANITIZE-WITH-ATTR-LABEL: define dso_local void @test2( +// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i64 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] { +// SANITIZE-WITH-ATTR-NEXT: entry: +// SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED:%.*]], ptr [[P]], i64 0, i32 1 +// SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOT_COUNTED_BY_GEP]], align 4 +// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = zext i32 [[DOT_COUNTED_BY_LOAD]] to i64, !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp ugt i64 [[TMP0]], [[INDEX]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP1]], label [[CONT3:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF3]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR: handler.out_of_bounds: +// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB4:[0-9]+]], i64 [[INDEX]]) #[[ATTR10]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META2]] +// SANITIZE-WITH-ATTR: cont3: +// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED]], ptr [[P]], i64 0, i32 2, i64 [[INDEX]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = shl i32 [[DOT_COUNTED_BY_LOAD]], 2 +// SANITIZE-WITH-ATTR-NEXT: [[DOTINV:%.*]] = icmp slt i32 [[DOT_COUNTED_BY_LOAD]], 0 +// SANITIZE-WITH-ATTR-NEXT: [[CONV:%.*]] = select i1 [[DOTINV]], i32 0, i32 [[TMP2]] +// SANITIZE-WITH-ATTR-NEXT: store i32 [[CONV]], ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA4]] +// SANITIZE-WITH-ATTR-NEXT: ret void +// +// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local void @test2( +// NO-SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef [[P:%.*]], i64 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR1:[0-9]+]] { +// NO-SANITIZE-WITH-ATTR-NEXT: entry: +// NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED:%.*]], ptr [[P]], i64 0, i32 1 +// NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOT_COUNTED_BY_GEP]], align 4 +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = shl i32 [[DOT_COUNTED_BY_LOAD]], 2 +// NO-SANITIZE-WITH-ATTR-NEXT: [[DOTINV:%.*]] = icmp slt i32 [[DOT_COUNTED_BY_LOAD]], 0 +// NO-SANITIZE-WITH-ATTR-NEXT: [[CONV:%.*]] = select i1 [[DOTINV]], i32 0, i32 [[TMP0]] +// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED]], ptr [[P]], i64 0, i32 2, i64 [[INDEX]] +// NO-SANITIZE-WITH-ATTR-NEXT: store i32 [[CONV]], ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] +// NO-SANITIZE-WITH-ATTR-NEXT: ret void +// +// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test2( +// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i64 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] { +// SANITIZE-WITHOUT-ATTR-NEXT: entry: +// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED:%.*]], ptr [[P]], i64 0, i32 2, i64 [[INDEX]] +// SANITIZE-WITHOUT-ATTR-NEXT: store i32 -1, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] +// SANITIZE-WITHOUT-ATTR-NEXT: ret void +// +// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test2( +// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i64 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] { +// NO-SANITIZE-WITHOUT-ATTR-NEXT: entry: +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED:%.*]], ptr [[P]], i64 0, i32 2, i64 [[INDEX]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: store i32 -1, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret void +// +void test2(struct annotated *p, size_t index) { + p->array[index] = __builtin_dynamic_object_size(p->array, 1); +} + +// SANITIZE-WITH-ATTR-LABEL: define dso_local i64 @test2_bdos( +// SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef readonly [[P:%.*]]) local_unnamed_addr #[[ATTR2:[0-9]+]] { +// SANITIZE-WITH-ATTR-NEXT: entry: +// SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED:%.*]], ptr [[P]], i64 0, i32 1 +// SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOT_COUNTED_BY_GEP]], align 4 +// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = sext i32 [[DOT_COUNTED_BY_LOAD]] to i64 +// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = shl nsw i64 [[TMP0]], 2 +// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[DOT_COUNTED_BY_LOAD]], -1 +// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = select i1 [[TMP2]], i64 [[TMP1]], i64 0 +// SANITIZE-WITH-ATTR-NEXT: ret i64 [[TMP3]] +// +// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local i64 @test2_bdos( +// NO-SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef readonly [[P:%.*]]) local_unnamed_addr #[[ATTR2:[0-9]+]] { +// NO-SANITIZE-WITH-ATTR-NEXT: entry: +// NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED:%.*]], ptr [[P]], i64 0, i32 1 +// NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOT_COUNTED_BY_GEP]], align 4 +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = sext i32 [[DOT_COUNTED_BY_LOAD]] to i64 +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = shl nsw i64 [[TMP0]], 2 +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[DOT_COUNTED_BY_LOAD]], -1 +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = select i1 [[TMP2]], i64 [[TMP1]], i64 0 +// NO-SANITIZE-WITH-ATTR-NEXT: ret i64 [[TMP3]] +// +// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i64 @test2_bdos( +// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]]) local_unnamed_addr #[[ATTR0]] { +// SANITIZE-WITHOUT-ATTR-NEXT: entry: +// SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1 +// +// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i64 @test2_bdos( +// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr noundef readnone [[P:%.*]]) local_unnamed_addr #[[ATTR1:[0-9]+]] { +// NO-SANITIZE-WITHOUT-ATTR-NEXT: entry: +// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1 +// +size_t test2_bdos(struct annotated *p) { + return __builtin_dynamic_object_size(p->array, 1); +} + +// SANITIZE-WITH-ATTR-LABEL: define dso_local void @test3( +// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i64 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] { +// SANITIZE-WITH-ATTR-NEXT: entry: +// SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED:%.*]], ptr [[P]], i64 0, i32 1 +// SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOT_COUNTED_BY_GEP]], align 4 +// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = zext i32 [[DOT_COUNTED_BY_LOAD]] to i64, !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp ugt i64 [[TMP0]], [[INDEX]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP1]], label [[CONT3:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF3]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR: handler.out_of_bounds: +// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB5:[0-9]+]], i64 [[INDEX]]) #[[ATTR10]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META2]] +// SANITIZE-WITH-ATTR: cont3: +// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED]], ptr [[P]], i64 0, i32 2, i64 [[INDEX]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = sext i32 [[DOT_COUNTED_BY_LOAD]] to i64 +// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = shl nsw i64 [[TMP2]], 2 +// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = tail call i64 @llvm.smax.i64(i64 [[TMP3]], i64 4) +// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = trunc i64 [[TMP4]] to i32 +// SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = add i32 [[TMP5]], 12 +// SANITIZE-WITH-ATTR-NEXT: [[DOTINV:%.*]] = icmp slt i32 [[DOT_COUNTED_BY_LOAD]], 0 +// SANITIZE-WITH-ATTR-NEXT: [[CONV:%.*]] = select i1 [[DOTINV]], i32 0, i32 [[TMP6]] +// SANITIZE-WITH-ATTR-NEXT: store i32 [[CONV]], ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA4]] +// SANITIZE-WITH-ATTR-NEXT: ret void +// +// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local void @test3( +// NO-SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef [[P:%.*]], i64 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR1]] { +// NO-SANITIZE-WITH-ATTR-NEXT: entry: +// NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED:%.*]], ptr [[P]], i64 0, i32 1 +// NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOT_COUNTED_BY_GEP]], align 4 +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = sext i32 [[DOT_COUNTED_BY_LOAD]] to i64 +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = shl nsw i64 [[TMP0]], 2 +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = tail call i64 @llvm.smax.i64(i64 [[TMP1]], i64 4) +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = trunc i64 [[TMP2]] to i32 +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = add i32 [[TMP3]], 12 +// NO-SANITIZE-WITH-ATTR-NEXT: [[DOTINV:%.*]] = icmp slt i32 [[DOT_COUNTED_BY_LOAD]], 0 +// NO-SANITIZE-WITH-ATTR-NEXT: [[CONV:%.*]] = select i1 [[DOTINV]], i32 0, i32 [[TMP4]] +// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED]], ptr [[P]], i64 0, i32 2, i64 [[INDEX]] +// NO-SANITIZE-WITH-ATTR-NEXT: store i32 [[CONV]], ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] +// NO-SANITIZE-WITH-ATTR-NEXT: ret void +// +// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test3( +// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i64 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] { +// SANITIZE-WITHOUT-ATTR-NEXT: entry: +// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED:%.*]], ptr [[P]], i64 0, i32 2, i64 [[INDEX]] +// SANITIZE-WITHOUT-ATTR-NEXT: store i32 -1, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] +// SANITIZE-WITHOUT-ATTR-NEXT: ret void +// +// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test3( +// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i64 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] { +// NO-SANITIZE-WITHOUT-ATTR-NEXT: entry: +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED:%.*]], ptr [[P]], i64 0, i32 2, i64 [[INDEX]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: store i32 -1, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret void +// +void test3(struct annotated *p, size_t index) { + // This test differs from 'test2' by checking bdos on the whole array and not + // just the FAM. + p->array[index] = __builtin_dynamic_object_size(p, 1); +} + +// SANITIZE-WITH-ATTR-LABEL: define dso_local i64 @test3_bdos( +// SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef readonly [[P:%.*]]) local_unnamed_addr #[[ATTR2]] { +// SANITIZE-WITH-ATTR-NEXT: entry: +// SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED:%.*]], ptr [[P]], i64 0, i32 1 +// SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOT_COUNTED_BY_GEP]], align 4 +// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = sext i32 [[DOT_COUNTED_BY_LOAD]] to i64 +// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = shl nsw i64 [[TMP0]], 2 +// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = tail call i64 @llvm.smax.i64(i64 [[TMP1]], i64 4) +// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = add nuw nsw i64 [[TMP2]], 12 +// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = icmp sgt i32 [[DOT_COUNTED_BY_LOAD]], -1 +// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = select i1 [[TMP4]], i64 [[TMP3]], i64 0 +// SANITIZE-WITH-ATTR-NEXT: ret i64 [[TMP5]] +// +// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local i64 @test3_bdos( +// NO-SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef readonly [[P:%.*]]) local_unnamed_addr #[[ATTR2]] { +// NO-SANITIZE-WITH-ATTR-NEXT: entry: +// NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED:%.*]], ptr [[P]], i64 0, i32 1 +// NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOT_COUNTED_BY_GEP]], align 4 +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = sext i32 [[DOT_COUNTED_BY_LOAD]] to i64 +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = shl nsw i64 [[TMP0]], 2 +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = tail call i64 @llvm.smax.i64(i64 [[TMP1]], i64 4) +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = add nuw nsw i64 [[TMP2]], 12 +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = icmp sgt i32 [[DOT_COUNTED_BY_LOAD]], -1 +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = select i1 [[TMP4]], i64 [[TMP3]], i64 0 +// NO-SANITIZE-WITH-ATTR-NEXT: ret i64 [[TMP5]] +// +// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i64 @test3_bdos( +// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef readnone [[P:%.*]]) local_unnamed_addr #[[ATTR2:[0-9]+]] { +// SANITIZE-WITHOUT-ATTR-NEXT: entry: +// SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1 +// +// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i64 @test3_bdos( +// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr noundef readnone [[P:%.*]]) local_unnamed_addr #[[ATTR1]] { +// NO-SANITIZE-WITHOUT-ATTR-NEXT: entry: +// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1 +// +size_t test3_bdos(struct annotated *p) { + return __builtin_dynamic_object_size(p, 1); +} + +// SANITIZE-WITH-ATTR-LABEL: define dso_local void @test4( +// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]], i32 noundef [[FAM_IDX:%.*]]) local_unnamed_addr #[[ATTR0]] { +// SANITIZE-WITH-ATTR-NEXT: entry: +// SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED:%.*]], ptr [[P]], i64 0, i32 1 +// SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOT_COUNTED_BY_GEP]], align 4 +// SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 +// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = zext i32 [[DOT_COUNTED_BY_LOAD]] to i64, !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp ult i64 [[IDXPROM]], [[TMP0]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP1]], label [[CONT4:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF3]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR: handler.out_of_bounds: +// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB6:[0-9]+]], i64 [[IDXPROM]]) #[[ATTR10]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META2]] +// SANITIZE-WITH-ATTR: cont4: +// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[DOT_COUNTED_BY_LOAD]], 2 +// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = shl i32 [[DOT_COUNTED_BY_LOAD]], 2 +// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = add i32 [[TMP3]], 244 +// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = and i32 [[TMP4]], 252 +// SANITIZE-WITH-ATTR-NEXT: [[CONV1:%.*]] = select i1 [[TMP2]], i32 [[TMP5]], i32 0 +// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED]], ptr [[P]], i64 0, i32 2, i64 [[IDXPROM]] +// SANITIZE-WITH-ATTR-NEXT: store i32 [[CONV1]], ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA4]] +// SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_LOAD7:%.*]] = load i32, ptr [[DOT_COUNTED_BY_GEP]], align 4 +// SANITIZE-WITH-ATTR-NEXT: [[ADD:%.*]] = add nsw i32 [[INDEX]], 1 +// SANITIZE-WITH-ATTR-NEXT: [[IDXPROM13:%.*]] = sext i32 [[ADD]] to i64 +// SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = zext i32 [[DOT_COUNTED_BY_LOAD7]] to i64, !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP7:%.*]] = icmp ult i64 [[IDXPROM13]], [[TMP6]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP7]], label [[CONT20:%.*]], label [[HANDLER_OUT_OF_BOUNDS16:%.*]], !prof [[PROF3]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR: handler.out_of_bounds16: +// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB7:[0-9]+]], i64 [[IDXPROM13]]) #[[ATTR10]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META2]] +// SANITIZE-WITH-ATTR: cont20: +// SANITIZE-WITH-ATTR-NEXT: [[TMP8:%.*]] = icmp sgt i32 [[DOT_COUNTED_BY_LOAD7]], 3 +// SANITIZE-WITH-ATTR-NEXT: [[TMP9:%.*]] = shl i32 [[DOT_COUNTED_BY_LOAD7]], 2 +// SANITIZE-WITH-ATTR-NEXT: [[TMP10:%.*]] = add i32 [[TMP9]], 240 +// SANITIZE-WITH-ATTR-NEXT: [[TMP11:%.*]] = and i32 [[TMP10]], 252 +// SANITIZE-WITH-ATTR-NEXT: [[CONV9:%.*]] = select i1 [[TMP8]], i32 [[TMP11]], i32 0 +// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX18:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED]], ptr [[P]], i64 0, i32 2, i64 [[IDXPROM13]] +// SANITIZE-WITH-ATTR-NEXT: store i32 [[CONV9]], ptr [[ARRAYIDX18]], align 4, !tbaa [[TBAA4]] +// SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_LOAD23:%.*]] = load i32, ptr [[DOT_COUNTED_BY_GEP]], align 4 +// SANITIZE-WITH-ATTR-NEXT: [[ADD29:%.*]] = add nsw i32 [[INDEX]], 2 +// SANITIZE-WITH-ATTR-NEXT: [[IDXPROM30:%.*]] = sext i32 [[ADD29]] to i64 +// SANITIZE-WITH-ATTR-NEXT: [[TMP12:%.*]] = zext i32 [[DOT_COUNTED_BY_LOAD23]] to i64, !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP13:%.*]] = icmp ult i64 [[IDXPROM30]], [[TMP12]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP13]], label [[CONT37:%.*]], label [[HANDLER_OUT_OF_BOUNDS33:%.*]], !prof [[PROF3]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR: handler.out_of_bounds33: +// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB8:[0-9]+]], i64 [[IDXPROM30]]) #[[ATTR10]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META2]] +// SANITIZE-WITH-ATTR: cont37: +// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX35:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED]], ptr [[P]], i64 0, i32 2, i64 [[IDXPROM30]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP14:%.*]] = icmp sgt i32 [[FAM_IDX]], -1 +// SANITIZE-WITH-ATTR-NEXT: [[TMP15:%.*]] = sext i32 [[DOT_COUNTED_BY_LOAD23]] to i64 +// SANITIZE-WITH-ATTR-NEXT: [[TMP16:%.*]] = sext i32 [[FAM_IDX]] to i64 +// SANITIZE-WITH-ATTR-NEXT: [[TMP17:%.*]] = sub nsw i64 [[TMP15]], [[TMP16]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP18:%.*]] = icmp sgt i64 [[TMP17]], -1 +// SANITIZE-WITH-ATTR-NEXT: [[TMP19:%.*]] = and i1 [[TMP14]], [[TMP18]] +// SANITIZE-WITH-ATTR-NEXT: [[DOTTR:%.*]] = trunc i64 [[TMP17]] to i32 +// SANITIZE-WITH-ATTR-NEXT: [[TMP20:%.*]] = shl i32 [[DOTTR]], 2 +// SANITIZE-WITH-ATTR-NEXT: [[TMP21:%.*]] = and i32 [[TMP20]], 252 +// SANITIZE-WITH-ATTR-NEXT: [[CONV25:%.*]] = select i1 [[TMP19]], i32 [[TMP21]], i32 0 +// SANITIZE-WITH-ATTR-NEXT: store i32 [[CONV25]], ptr [[ARRAYIDX35]], align 4, !tbaa [[TBAA4]] +// SANITIZE-WITH-ATTR-NEXT: ret void +// +// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local void @test4( +// NO-SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef [[P:%.*]], i32 noundef [[INDEX:%.*]], i32 noundef [[FAM_IDX:%.*]]) local_unnamed_addr #[[ATTR1]] { +// NO-SANITIZE-WITH-ATTR-NEXT: entry: +// NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED:%.*]], ptr [[P]], i64 0, i32 1 +// NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOT_COUNTED_BY_GEP]], align 4 +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = shl i32 [[DOT_COUNTED_BY_LOAD]], 2 +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = add i32 [[TMP0]], 244 +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[DOT_COUNTED_BY_LOAD]], 2 +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = and i32 [[TMP1]], 252 +// NO-SANITIZE-WITH-ATTR-NEXT: [[CONV1:%.*]] = select i1 [[TMP2]], i32 [[TMP3]], i32 0 +// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 +// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED]], ptr [[P]], i64 0, i32 2, i64 [[IDXPROM]] +// NO-SANITIZE-WITH-ATTR-NEXT: store i32 [[CONV1]], ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] +// NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_LOAD4:%.*]] = load i32, ptr [[DOT_COUNTED_BY_GEP]], align 4 +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = shl i32 [[DOT_COUNTED_BY_LOAD4]], 2 +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = add i32 [[TMP4]], 240 +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = icmp sgt i32 [[DOT_COUNTED_BY_LOAD4]], 3 +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP7:%.*]] = and i32 [[TMP5]], 252 +// NO-SANITIZE-WITH-ATTR-NEXT: [[CONV6:%.*]] = select i1 [[TMP6]], i32 [[TMP7]], i32 0 +// NO-SANITIZE-WITH-ATTR-NEXT: [[ADD:%.*]] = add nsw i32 [[INDEX]], 1 +// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM8:%.*]] = sext i32 [[ADD]] to i64 +// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX9:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED]], ptr [[P]], i64 0, i32 2, i64 [[IDXPROM8]] +// NO-SANITIZE-WITH-ATTR-NEXT: store i32 [[CONV6]], ptr [[ARRAYIDX9]], align 4, !tbaa [[TBAA2]] +// NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_LOAD12:%.*]] = load i32, ptr [[DOT_COUNTED_BY_GEP]], align 4 +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP8:%.*]] = sext i32 [[DOT_COUNTED_BY_LOAD12]] to i64 +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP9:%.*]] = sext i32 [[FAM_IDX]] to i64 +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP10:%.*]] = sub nsw i64 [[TMP8]], [[TMP9]] +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP11:%.*]] = icmp sgt i64 [[TMP10]], -1 +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP12:%.*]] = icmp sgt i32 [[FAM_IDX]], -1 +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP13:%.*]] = and i1 [[TMP12]], [[TMP11]] +// NO-SANITIZE-WITH-ATTR-NEXT: [[DOTTR:%.*]] = trunc i64 [[TMP10]] to i32 +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP14:%.*]] = shl i32 [[DOTTR]], 2 +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP15:%.*]] = and i32 [[TMP14]], 252 +// NO-SANITIZE-WITH-ATTR-NEXT: [[CONV14:%.*]] = select i1 [[TMP13]], i32 [[TMP15]], i32 0 +// NO-SANITIZE-WITH-ATTR-NEXT: [[ADD16:%.*]] = add nsw i32 [[INDEX]], 2 +// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM17:%.*]] = sext i32 [[ADD16]] to i64 +// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX18:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED]], ptr [[P]], i64 0, i32 2, i64 [[IDXPROM17]] +// NO-SANITIZE-WITH-ATTR-NEXT: store i32 [[CONV14]], ptr [[ARRAYIDX18]], align 4, !tbaa [[TBAA2]] +// NO-SANITIZE-WITH-ATTR-NEXT: ret void +// +// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test4( +// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]], i32 noundef [[FAM_IDX:%.*]]) local_unnamed_addr #[[ATTR0]] { +// SANITIZE-WITHOUT-ATTR-NEXT: entry: +// SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 +// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX5:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED:%.*]], ptr [[P]], i64 0, i32 2, i64 [[IDXPROM]] +// SANITIZE-WITHOUT-ATTR-NEXT: store i32 255, ptr [[ARRAYIDX5]], align 4, !tbaa [[TBAA2]] +// SANITIZE-WITHOUT-ATTR-NEXT: [[ADD:%.*]] = add nsw i32 [[INDEX]], 1 +// SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM17:%.*]] = sext i32 [[ADD]] to i64 +// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX18:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED]], ptr [[P]], i64 0, i32 2, i64 [[IDXPROM17]] +// SANITIZE-WITHOUT-ATTR-NEXT: store i32 255, ptr [[ARRAYIDX18]], align 4, !tbaa [[TBAA2]] +// SANITIZE-WITHOUT-ATTR-NEXT: [[ADD31:%.*]] = add nsw i32 [[INDEX]], 2 +// SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM32:%.*]] = sext i32 [[ADD31]] to i64 +// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX33:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED]], ptr [[P]], i64 0, i32 2, i64 [[IDXPROM32]] +// SANITIZE-WITHOUT-ATTR-NEXT: store i32 255, ptr [[ARRAYIDX33]], align 4, !tbaa [[TBAA2]] +// SANITIZE-WITHOUT-ATTR-NEXT: ret void +// +// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test4( +// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]], i32 noundef [[FAM_IDX:%.*]]) local_unnamed_addr #[[ATTR0]] { +// NO-SANITIZE-WITHOUT-ATTR-NEXT: entry: +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX3:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED:%.*]], ptr [[P]], i64 0, i32 2, i64 [[IDXPROM]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: store i32 255, ptr [[ARRAYIDX3]], align 4, !tbaa [[TBAA2]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ADD:%.*]] = add nsw i32 [[INDEX]], 1 +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM9:%.*]] = sext i32 [[ADD]] to i64 +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX10:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED]], ptr [[P]], i64 0, i32 2, i64 [[IDXPROM9]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: store i32 255, ptr [[ARRAYIDX10]], align 4, !tbaa [[TBAA2]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ADD17:%.*]] = add nsw i32 [[INDEX]], 2 +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM18:%.*]] = sext i32 [[ADD17]] to i64 +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX19:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED]], ptr [[P]], i64 0, i32 2, i64 [[IDXPROM18]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: store i32 255, ptr [[ARRAYIDX19]], align 4, !tbaa [[TBAA2]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret void +// +void test4(struct annotated *p, int index, int fam_idx) { + // This tests calculating the size from a pointer inside the FAM. + p->array[index] = (unsigned char)__builtin_dynamic_object_size(&p->array[3], 1); + p->array[index + 1] = (unsigned char)__builtin_dynamic_object_size(&(p->array[4]), 1); + p->array[index + 2] = (unsigned char)__builtin_dynamic_object_size(&(p->array[fam_idx]), 1); +} + +// SANITIZE-WITH-ATTR-LABEL: define dso_local i64 @test4_bdos( +// SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef readonly [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR2]] { +// SANITIZE-WITH-ATTR-NEXT: entry: +// SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED:%.*]], ptr [[P]], i64 0, i32 1 +// SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOT_COUNTED_BY_GEP]], align 4 +// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = sext i32 [[DOT_COUNTED_BY_LOAD]] to i64 +// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = sext i32 [[INDEX]] to i64 +// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = sub nsw i64 [[TMP0]], [[TMP1]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = shl nsw i64 [[TMP2]], 2 +// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = icmp sgt i64 [[TMP2]], -1 +// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = icmp sgt i32 [[INDEX]], -1 +// SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = and i1 [[TMP5]], [[TMP4]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP7:%.*]] = select i1 [[TMP6]], i64 [[TMP3]], i64 0 +// SANITIZE-WITH-ATTR-NEXT: ret i64 [[TMP7]] +// +// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local i64 @test4_bdos( +// NO-SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef readonly [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR2]] { +// NO-SANITIZE-WITH-ATTR-NEXT: entry: +// NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED:%.*]], ptr [[P]], i64 0, i32 1 +// NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOT_COUNTED_BY_GEP]], align 4 +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = sext i32 [[DOT_COUNTED_BY_LOAD]] to i64 +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = sext i32 [[INDEX]] to i64 +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = sub nsw i64 [[TMP0]], [[TMP1]] +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = shl nsw i64 [[TMP2]], 2 +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = icmp sgt i64 [[TMP2]], -1 +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = icmp sgt i32 [[INDEX]], -1 +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = and i1 [[TMP5]], [[TMP4]] +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP7:%.*]] = select i1 [[TMP6]], i64 [[TMP3]], i64 0 +// NO-SANITIZE-WITH-ATTR-NEXT: ret i64 [[TMP7]] +// +// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i64 @test4_bdos( +// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] { +// SANITIZE-WITHOUT-ATTR-NEXT: entry: +// SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1 +// +// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i64 @test4_bdos( +// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr noundef readnone [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR1]] { +// NO-SANITIZE-WITHOUT-ATTR-NEXT: entry: +// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1 +// +size_t test4_bdos(struct annotated *p, int index) { + return __builtin_dynamic_object_size(&p->array[index], 1); +} + +// SANITIZE-WITH-ATTR-LABEL: define dso_local void @test5( +// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] { +// SANITIZE-WITH-ATTR-NEXT: entry: +// SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds [[STRUCT_ANON_STRUCT:%.*]], ptr [[P]], i64 0, i32 1 +// SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_LOAD:%.*]] = load i64, ptr [[DOT_COUNTED_BY_GEP]], align 4 +// SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 +// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = icmp ugt i64 [[DOT_COUNTED_BY_LOAD]], [[IDXPROM]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP0]], label [[CONT3:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF3]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR: handler.out_of_bounds: +// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB9:[0-9]+]], i64 [[IDXPROM]]) #[[ATTR10]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META2]] +// SANITIZE-WITH-ATTR: cont3: +// SANITIZE-WITH-ATTR-NEXT: [[ARRAY:%.*]] = getelementptr inbounds [[STRUCT_ANON_STRUCT]], ptr [[P]], i64 1 +// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i32], ptr [[ARRAY]], i64 0, i64 [[IDXPROM]] +// SANITIZE-WITH-ATTR-NEXT: [[DOTINV:%.*]] = icmp slt i64 [[DOT_COUNTED_BY_LOAD]], 0 +// SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_LOAD_TR:%.*]] = trunc i64 [[DOT_COUNTED_BY_LOAD]] to i32 +// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = shl i32 [[DOT_COUNTED_BY_LOAD_TR]], 2 +// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = add i32 [[TMP1]], 16 +// SANITIZE-WITH-ATTR-NEXT: [[CONV:%.*]] = select i1 [[DOTINV]], i32 0, i32 [[TMP2]] +// SANITIZE-WITH-ATTR-NEXT: store i32 [[CONV]], ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA4]] +// SANITIZE-WITH-ATTR-NEXT: ret void +// +// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local void @test5( +// NO-SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR1]] { +// NO-SANITIZE-WITH-ATTR-NEXT: entry: +// NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds [[STRUCT_ANON_STRUCT:%.*]], ptr [[P]], i64 0, i32 1 +// NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_LOAD:%.*]] = load i64, ptr [[DOT_COUNTED_BY_GEP]], align 4 +// NO-SANITIZE-WITH-ATTR-NEXT: [[DOTINV:%.*]] = icmp slt i64 [[DOT_COUNTED_BY_LOAD]], 0 +// NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_LOAD_TR:%.*]] = trunc i64 [[DOT_COUNTED_BY_LOAD]] to i32 +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = shl i32 [[DOT_COUNTED_BY_LOAD_TR]], 2 +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = add i32 [[TMP0]], 16 +// NO-SANITIZE-WITH-ATTR-NEXT: [[CONV:%.*]] = select i1 [[DOTINV]], i32 0, i32 [[TMP1]] +// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAY:%.*]] = getelementptr inbounds [[STRUCT_ANON_STRUCT]], ptr [[P]], i64 1 +// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 +// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i32], ptr [[ARRAY]], i64 0, i64 [[IDXPROM]] +// NO-SANITIZE-WITH-ATTR-NEXT: store i32 [[CONV]], ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] +// NO-SANITIZE-WITH-ATTR-NEXT: ret void +// +// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test5( +// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] { +// SANITIZE-WITHOUT-ATTR-NEXT: entry: +// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAY:%.*]] = getelementptr inbounds [[STRUCT_ANON_STRUCT:%.*]], ptr [[P]], i64 1 +// SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 +// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i32], ptr [[ARRAY]], i64 0, i64 [[IDXPROM]] +// SANITIZE-WITHOUT-ATTR-NEXT: store i32 -1, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] +// SANITIZE-WITHOUT-ATTR-NEXT: ret void +// +// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test5( +// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] { +// NO-SANITIZE-WITHOUT-ATTR-NEXT: entry: +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAY:%.*]] = getelementptr inbounds [[STRUCT_ANON_STRUCT:%.*]], ptr [[P]], i64 1 +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i32], ptr [[ARRAY]], i64 0, i64 [[IDXPROM]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: store i32 -1, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret void +// +void test5(struct anon_struct *p, int index) { + p->array[index] = __builtin_dynamic_object_size(p, 1); +} + +// SANITIZE-WITH-ATTR-LABEL: define dso_local i64 @test5_bdos( +// SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef readonly [[P:%.*]]) local_unnamed_addr #[[ATTR2]] { +// SANITIZE-WITH-ATTR-NEXT: entry: +// SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds [[STRUCT_ANON_STRUCT:%.*]], ptr [[P]], i64 0, i32 1 +// SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_LOAD:%.*]] = load i64, ptr [[DOT_COUNTED_BY_GEP]], align 4 +// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = shl nuw i64 [[DOT_COUNTED_BY_LOAD]], 2 +// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = add nuw i64 [[TMP0]], 16 +// SANITIZE-WITH-ATTR-NEXT: [[DOTINV:%.*]] = icmp slt i64 [[DOT_COUNTED_BY_LOAD]], 0 +// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = select i1 [[DOTINV]], i64 0, i64 [[TMP1]] +// SANITIZE-WITH-ATTR-NEXT: ret i64 [[TMP2]] +// +// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local i64 @test5_bdos( +// NO-SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef readonly [[P:%.*]]) local_unnamed_addr #[[ATTR2]] { +// NO-SANITIZE-WITH-ATTR-NEXT: entry: +// NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds [[STRUCT_ANON_STRUCT:%.*]], ptr [[P]], i64 0, i32 1 +// NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_LOAD:%.*]] = load i64, ptr [[DOT_COUNTED_BY_GEP]], align 4 +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = shl nuw i64 [[DOT_COUNTED_BY_LOAD]], 2 +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = add nuw i64 [[TMP0]], 16 +// NO-SANITIZE-WITH-ATTR-NEXT: [[DOTINV:%.*]] = icmp slt i64 [[DOT_COUNTED_BY_LOAD]], 0 +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = select i1 [[DOTINV]], i64 0, i64 [[TMP1]] +// NO-SANITIZE-WITH-ATTR-NEXT: ret i64 [[TMP2]] +// +// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i64 @test5_bdos( +// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef readnone [[P:%.*]]) local_unnamed_addr #[[ATTR2]] { +// SANITIZE-WITHOUT-ATTR-NEXT: entry: +// SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1 +// +// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i64 @test5_bdos( +// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr noundef readnone [[P:%.*]]) local_unnamed_addr #[[ATTR1]] { +// NO-SANITIZE-WITHOUT-ATTR-NEXT: entry: +// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1 +// +size_t test5_bdos(struct anon_struct *p) { + return __builtin_dynamic_object_size(p, 1); +} + +// SANITIZE-WITH-ATTR-LABEL: define dso_local void @test6( +// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] { +// SANITIZE-WITH-ATTR-NEXT: entry: +// SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds [[STRUCT_ANON_STRUCT:%.*]], ptr [[P]], i64 0, i32 1 +// SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_LOAD:%.*]] = load i64, ptr [[DOT_COUNTED_BY_GEP]], align 4 +// SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 +// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = icmp ugt i64 [[DOT_COUNTED_BY_LOAD]], [[IDXPROM]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP0]], label [[CONT3:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF3]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR: handler.out_of_bounds: +// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB10:[0-9]+]], i64 [[IDXPROM]]) #[[ATTR10]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META2]] +// SANITIZE-WITH-ATTR: cont3: +// SANITIZE-WITH-ATTR-NEXT: [[ARRAY:%.*]] = getelementptr inbounds [[STRUCT_ANON_STRUCT]], ptr [[P]], i64 1 +// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i32], ptr [[ARRAY]], i64 0, i64 [[IDXPROM]] +// SANITIZE-WITH-ATTR-NEXT: [[DOTINV:%.*]] = icmp slt i64 [[DOT_COUNTED_BY_LOAD]], 0 +// SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_LOAD_TR:%.*]] = trunc i64 [[DOT_COUNTED_BY_LOAD]] to i32 +// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = shl i32 [[DOT_COUNTED_BY_LOAD_TR]], 2 +// SANITIZE-WITH-ATTR-NEXT: [[CONV:%.*]] = select i1 [[DOTINV]], i32 0, i32 [[TMP1]] +// SANITIZE-WITH-ATTR-NEXT: store i32 [[CONV]], ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA4]] +// SANITIZE-WITH-ATTR-NEXT: ret void +// +// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local void @test6( +// NO-SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR1]] { +// NO-SANITIZE-WITH-ATTR-NEXT: entry: +// NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds [[STRUCT_ANON_STRUCT:%.*]], ptr [[P]], i64 0, i32 1 +// NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_LOAD:%.*]] = load i64, ptr [[DOT_COUNTED_BY_GEP]], align 4 +// NO-SANITIZE-WITH-ATTR-NEXT: [[DOTINV:%.*]] = icmp slt i64 [[DOT_COUNTED_BY_LOAD]], 0 +// NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_LOAD_TR:%.*]] = trunc i64 [[DOT_COUNTED_BY_LOAD]] to i32 +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = shl i32 [[DOT_COUNTED_BY_LOAD_TR]], 2 +// NO-SANITIZE-WITH-ATTR-NEXT: [[CONV:%.*]] = select i1 [[DOTINV]], i32 0, i32 [[TMP0]] +// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAY:%.*]] = getelementptr inbounds [[STRUCT_ANON_STRUCT]], ptr [[P]], i64 1 +// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 +// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i32], ptr [[ARRAY]], i64 0, i64 [[IDXPROM]] +// NO-SANITIZE-WITH-ATTR-NEXT: store i32 [[CONV]], ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] +// NO-SANITIZE-WITH-ATTR-NEXT: ret void +// +// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test6( +// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] { +// SANITIZE-WITHOUT-ATTR-NEXT: entry: +// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAY:%.*]] = getelementptr inbounds [[STRUCT_ANON_STRUCT:%.*]], ptr [[P]], i64 1 +// SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 +// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i32], ptr [[ARRAY]], i64 0, i64 [[IDXPROM]] +// SANITIZE-WITHOUT-ATTR-NEXT: store i32 -1, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] +// SANITIZE-WITHOUT-ATTR-NEXT: ret void +// +// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test6( +// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] { +// NO-SANITIZE-WITHOUT-ATTR-NEXT: entry: +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAY:%.*]] = getelementptr inbounds [[STRUCT_ANON_STRUCT:%.*]], ptr [[P]], i64 1 +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i32], ptr [[ARRAY]], i64 0, i64 [[IDXPROM]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: store i32 -1, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret void +// +void test6(struct anon_struct *p, int index) { + p->array[index] = __builtin_dynamic_object_size(p->array, 1); +} + +// SANITIZE-WITH-ATTR-LABEL: define dso_local i64 @test6_bdos( +// SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef readonly [[P:%.*]]) local_unnamed_addr #[[ATTR2]] { +// SANITIZE-WITH-ATTR-NEXT: entry: +// SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds [[STRUCT_ANON_STRUCT:%.*]], ptr [[P]], i64 0, i32 1 +// SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_LOAD:%.*]] = load i64, ptr [[DOT_COUNTED_BY_GEP]], align 4 +// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = shl nuw i64 [[DOT_COUNTED_BY_LOAD]], 2 +// SANITIZE-WITH-ATTR-NEXT: [[DOTINV:%.*]] = icmp slt i64 [[DOT_COUNTED_BY_LOAD]], 0 +// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = select i1 [[DOTINV]], i64 0, i64 [[TMP0]] +// SANITIZE-WITH-ATTR-NEXT: ret i64 [[TMP1]] +// +// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local i64 @test6_bdos( +// NO-SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef readonly [[P:%.*]]) local_unnamed_addr #[[ATTR2]] { +// NO-SANITIZE-WITH-ATTR-NEXT: entry: +// NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds [[STRUCT_ANON_STRUCT:%.*]], ptr [[P]], i64 0, i32 1 +// NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_LOAD:%.*]] = load i64, ptr [[DOT_COUNTED_BY_GEP]], align 4 +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = shl nuw i64 [[DOT_COUNTED_BY_LOAD]], 2 +// NO-SANITIZE-WITH-ATTR-NEXT: [[DOTINV:%.*]] = icmp slt i64 [[DOT_COUNTED_BY_LOAD]], 0 +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = select i1 [[DOTINV]], i64 0, i64 [[TMP0]] +// NO-SANITIZE-WITH-ATTR-NEXT: ret i64 [[TMP1]] +// +// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i64 @test6_bdos( +// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]]) local_unnamed_addr #[[ATTR0]] { +// SANITIZE-WITHOUT-ATTR-NEXT: entry: +// SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1 +// +// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i64 @test6_bdos( +// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr noundef readnone [[P:%.*]]) local_unnamed_addr #[[ATTR1]] { +// NO-SANITIZE-WITHOUT-ATTR-NEXT: entry: +// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1 +// +size_t test6_bdos(struct anon_struct *p) { + return __builtin_dynamic_object_size(p->array, 1); +} + +// SANITIZE-WITH-ATTR-LABEL: define dso_local void @test7( +// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] { +// SANITIZE-WITH-ATTR-NEXT: entry: +// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT_UNION_OF_FAMS:%.*]], ptr [[P]], i64 0, i32 1 +// SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 +// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_LOAD:%.*]] = load i8, ptr [[TMP0]], align 4 +// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = zext i8 [[DOTCOUNTED_BY_LOAD]] to i64, !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = icmp ult i64 [[IDXPROM]], [[TMP1]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP2]], label [[CONT7:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF3]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR: handler.out_of_bounds: +// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB12:[0-9]+]], i64 [[IDXPROM]]) #[[ATTR10]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META2]] +// SANITIZE-WITH-ATTR: cont7: +// SANITIZE-WITH-ATTR-NEXT: [[INTS:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 9 +// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i8], ptr [[INTS]], i64 0, i64 [[IDXPROM]] +// SANITIZE-WITH-ATTR-NEXT: store i8 -1, ptr [[ARRAYIDX]], align 1, !tbaa [[TBAA8:![0-9]+]] +// SANITIZE-WITH-ATTR-NEXT: ret void +// +// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local void @test7( +// NO-SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] { +// NO-SANITIZE-WITH-ATTR-NEXT: entry: +// NO-SANITIZE-WITH-ATTR-NEXT: [[INTS:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 9 +// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 +// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i8], ptr [[INTS]], i64 0, i64 [[IDXPROM]] +// NO-SANITIZE-WITH-ATTR-NEXT: store i8 -1, ptr [[ARRAYIDX]], align 1, !tbaa [[TBAA6:![0-9]+]] +// NO-SANITIZE-WITH-ATTR-NEXT: ret void +// +// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test7( +// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] { +// SANITIZE-WITHOUT-ATTR-NEXT: entry: +// SANITIZE-WITHOUT-ATTR-NEXT: [[INTS:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 9 +// SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 +// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i8], ptr [[INTS]], i64 0, i64 [[IDXPROM]] +// SANITIZE-WITHOUT-ATTR-NEXT: store i8 -1, ptr [[ARRAYIDX]], align 1, !tbaa [[TBAA6:![0-9]+]] +// SANITIZE-WITHOUT-ATTR-NEXT: ret void +// +// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test7( +// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] { +// NO-SANITIZE-WITHOUT-ATTR-NEXT: entry: +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[INTS:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 9 +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i8], ptr [[INTS]], i64 0, i64 [[IDXPROM]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: store i8 -1, ptr [[ARRAYIDX]], align 1, !tbaa [[TBAA6:![0-9]+]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret void +// +void test7(struct union_of_fams *p, int index) { + p->ints[index] = __builtin_dynamic_object_size(p, 1); +} + +// SANITIZE-WITH-ATTR-LABEL: define dso_local i64 @test7_bdos( +// SANITIZE-WITH-ATTR-SAME: ptr noundef readnone [[P:%.*]]) local_unnamed_addr #[[ATTR4:[0-9]+]] { +// SANITIZE-WITH-ATTR-NEXT: entry: +// SANITIZE-WITH-ATTR-NEXT: ret i64 -1 +// +// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local i64 @test7_bdos( +// NO-SANITIZE-WITH-ATTR-SAME: ptr noundef readnone [[P:%.*]]) local_unnamed_addr #[[ATTR4:[0-9]+]] { +// NO-SANITIZE-WITH-ATTR-NEXT: entry: +// NO-SANITIZE-WITH-ATTR-NEXT: ret i64 -1 +// +// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i64 @test7_bdos( +// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef readnone [[P:%.*]]) local_unnamed_addr #[[ATTR2]] { +// SANITIZE-WITHOUT-ATTR-NEXT: entry: +// SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1 +// +// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i64 @test7_bdos( +// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr noundef readnone [[P:%.*]]) local_unnamed_addr #[[ATTR1]] { +// NO-SANITIZE-WITHOUT-ATTR-NEXT: entry: +// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1 +// +size_t test7_bdos(struct union_of_fams *p) { + return __builtin_dynamic_object_size(p, 1); +} + +// SANITIZE-WITH-ATTR-LABEL: define dso_local void @test8( +// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] { +// SANITIZE-WITH-ATTR-NEXT: entry: +// SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds [[STRUCT_UNION_OF_FAMS:%.*]], ptr [[P]], i64 0, i32 1 +// SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_LOAD:%.*]] = load i8, ptr [[DOT_COUNTED_BY_GEP]], align 4 +// SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 +// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = zext i8 [[DOT_COUNTED_BY_LOAD]] to i64, !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp ult i64 [[IDXPROM]], [[TMP0]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP1]], label [[CONT9:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF3]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR: handler.out_of_bounds: +// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB13:[0-9]+]], i64 [[IDXPROM]]) #[[ATTR10]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META2]] +// SANITIZE-WITH-ATTR: cont9: +// SANITIZE-WITH-ATTR-NEXT: [[INTS:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 9 +// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i8], ptr [[INTS]], i64 0, i64 [[IDXPROM]] +// SANITIZE-WITH-ATTR-NEXT: store i8 [[DOT_COUNTED_BY_LOAD]], ptr [[ARRAYIDX]], align 1, !tbaa [[TBAA8]] +// SANITIZE-WITH-ATTR-NEXT: ret void +// +// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local void @test8( +// NO-SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR1]] { +// NO-SANITIZE-WITH-ATTR-NEXT: entry: +// NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds [[STRUCT_UNION_OF_FAMS:%.*]], ptr [[P]], i64 0, i32 1 +// NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_LOAD:%.*]] = load i8, ptr [[DOT_COUNTED_BY_GEP]], align 4 +// NO-SANITIZE-WITH-ATTR-NEXT: [[INTS:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 9 +// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 +// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i8], ptr [[INTS]], i64 0, i64 [[IDXPROM]] +// NO-SANITIZE-WITH-ATTR-NEXT: store i8 [[DOT_COUNTED_BY_LOAD]], ptr [[ARRAYIDX]], align 1, !tbaa [[TBAA6]] +// NO-SANITIZE-WITH-ATTR-NEXT: ret void +// +// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test8( +// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] { +// SANITIZE-WITHOUT-ATTR-NEXT: entry: +// SANITIZE-WITHOUT-ATTR-NEXT: [[INTS:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 9 +// SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 +// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i8], ptr [[INTS]], i64 0, i64 [[IDXPROM]] +// SANITIZE-WITHOUT-ATTR-NEXT: store i8 -1, ptr [[ARRAYIDX]], align 1, !tbaa [[TBAA6]] +// SANITIZE-WITHOUT-ATTR-NEXT: ret void +// +// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test8( +// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] { +// NO-SANITIZE-WITHOUT-ATTR-NEXT: entry: +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[INTS:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 9 +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i8], ptr [[INTS]], i64 0, i64 [[IDXPROM]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: store i8 -1, ptr [[ARRAYIDX]], align 1, !tbaa [[TBAA6]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret void +// +void test8(struct union_of_fams *p, int index) { + p->ints[index] = __builtin_dynamic_object_size(p->ints, 1); +} + +// SANITIZE-WITH-ATTR-LABEL: define dso_local i64 @test8_bdos( +// SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef readonly [[P:%.*]]) local_unnamed_addr #[[ATTR2]] { +// SANITIZE-WITH-ATTR-NEXT: entry: +// SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds [[STRUCT_UNION_OF_FAMS:%.*]], ptr [[P]], i64 0, i32 1 +// SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_LOAD:%.*]] = load i8, ptr [[DOT_COUNTED_BY_GEP]], align 4 +// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = zext i8 [[DOT_COUNTED_BY_LOAD]] to i64 +// SANITIZE-WITH-ATTR-NEXT: ret i64 [[TMP0]] +// +// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local i64 @test8_bdos( +// NO-SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef readonly [[P:%.*]]) local_unnamed_addr #[[ATTR2]] { +// NO-SANITIZE-WITH-ATTR-NEXT: entry: +// NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds [[STRUCT_UNION_OF_FAMS:%.*]], ptr [[P]], i64 0, i32 1 +// NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_LOAD:%.*]] = load i8, ptr [[DOT_COUNTED_BY_GEP]], align 4 +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = zext i8 [[DOT_COUNTED_BY_LOAD]] to i64 +// NO-SANITIZE-WITH-ATTR-NEXT: ret i64 [[TMP0]] +// +// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i64 @test8_bdos( +// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]]) local_unnamed_addr #[[ATTR0]] { +// SANITIZE-WITHOUT-ATTR-NEXT: entry: +// SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1 +// +// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i64 @test8_bdos( +// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr noundef readnone [[P:%.*]]) local_unnamed_addr #[[ATTR1]] { +// NO-SANITIZE-WITHOUT-ATTR-NEXT: entry: +// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1 +// +size_t test8_bdos(struct union_of_fams *p) { + return __builtin_dynamic_object_size(p->ints, 1); +} + +// SANITIZE-WITH-ATTR-LABEL: define dso_local void @test9( +// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] { +// SANITIZE-WITH-ATTR-NEXT: entry: +// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT_UNION_OF_FAMS:%.*]], ptr [[P]], i64 0, i32 1 +// SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 +// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_LOAD:%.*]] = load i32, ptr [[TMP0]], align 4 +// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = zext i32 [[DOTCOUNTED_BY_LOAD]] to i64, !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = icmp ult i64 [[IDXPROM]], [[TMP1]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP2]], label [[CONT7:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF3]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR: handler.out_of_bounds: +// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB14:[0-9]+]], i64 [[IDXPROM]]) #[[ATTR10]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META2]] +// SANITIZE-WITH-ATTR: cont7: +// SANITIZE-WITH-ATTR-NEXT: [[BYTES:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 12 +// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i8], ptr [[BYTES]], i64 0, i64 [[IDXPROM]] +// SANITIZE-WITH-ATTR-NEXT: store i8 -1, ptr [[ARRAYIDX]], align 1, !tbaa [[TBAA8]] +// SANITIZE-WITH-ATTR-NEXT: ret void +// +// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local void @test9( +// NO-SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] { +// NO-SANITIZE-WITH-ATTR-NEXT: entry: +// NO-SANITIZE-WITH-ATTR-NEXT: [[BYTES:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 12 +// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 +// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i8], ptr [[BYTES]], i64 0, i64 [[IDXPROM]] +// NO-SANITIZE-WITH-ATTR-NEXT: store i8 -1, ptr [[ARRAYIDX]], align 1, !tbaa [[TBAA6]] +// NO-SANITIZE-WITH-ATTR-NEXT: ret void +// +// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test9( +// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] { +// SANITIZE-WITHOUT-ATTR-NEXT: entry: +// SANITIZE-WITHOUT-ATTR-NEXT: [[BYTES:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 12 +// SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 +// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i8], ptr [[BYTES]], i64 0, i64 [[IDXPROM]] +// SANITIZE-WITHOUT-ATTR-NEXT: store i8 -1, ptr [[ARRAYIDX]], align 1, !tbaa [[TBAA6]] +// SANITIZE-WITHOUT-ATTR-NEXT: ret void +// +// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test9( +// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] { +// NO-SANITIZE-WITHOUT-ATTR-NEXT: entry: +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[BYTES:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 12 +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i8], ptr [[BYTES]], i64 0, i64 [[IDXPROM]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: store i8 -1, ptr [[ARRAYIDX]], align 1, !tbaa [[TBAA6]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret void +// +void test9(struct union_of_fams *p, int index) { + p->bytes[index] = (unsigned char)__builtin_dynamic_object_size(p, 1); +} + +// SANITIZE-WITH-ATTR-LABEL: define dso_local i64 @test9_bdos( +// SANITIZE-WITH-ATTR-SAME: ptr noundef readnone [[P:%.*]]) local_unnamed_addr #[[ATTR4]] { +// SANITIZE-WITH-ATTR-NEXT: entry: +// SANITIZE-WITH-ATTR-NEXT: ret i64 -1 +// +// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local i64 @test9_bdos( +// NO-SANITIZE-WITH-ATTR-SAME: ptr noundef readnone [[P:%.*]]) local_unnamed_addr #[[ATTR4]] { +// NO-SANITIZE-WITH-ATTR-NEXT: entry: +// NO-SANITIZE-WITH-ATTR-NEXT: ret i64 -1 +// +// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i64 @test9_bdos( +// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef readnone [[P:%.*]]) local_unnamed_addr #[[ATTR2]] { +// SANITIZE-WITHOUT-ATTR-NEXT: entry: +// SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1 +// +// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i64 @test9_bdos( +// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr noundef readnone [[P:%.*]]) local_unnamed_addr #[[ATTR1]] { +// NO-SANITIZE-WITHOUT-ATTR-NEXT: entry: +// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1 +// +size_t test9_bdos(struct union_of_fams *p) { + return __builtin_dynamic_object_size(p, 1); +} + +// SANITIZE-WITH-ATTR-LABEL: define dso_local void @test10( +// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] { +// SANITIZE-WITH-ATTR-NEXT: entry: +// SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds [[STRUCT_UNION_OF_FAMS:%.*]], ptr [[P]], i64 0, i32 1 +// SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOT_COUNTED_BY_GEP]], align 4 +// SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 +// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = zext i32 [[DOT_COUNTED_BY_LOAD]] to i64, !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp ult i64 [[IDXPROM]], [[TMP0]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP1]], label [[CONT9:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF3]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR: handler.out_of_bounds: +// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB15:[0-9]+]], i64 [[IDXPROM]]) #[[ATTR10]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META2]] +// SANITIZE-WITH-ATTR: cont9: +// SANITIZE-WITH-ATTR-NEXT: [[BYTES:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 12 +// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i8], ptr [[BYTES]], i64 0, i64 [[IDXPROM]] +// SANITIZE-WITH-ATTR-NEXT: [[NARROW:%.*]] = tail call i32 @llvm.smax.i32(i32 [[DOT_COUNTED_BY_LOAD]], i32 0) +// SANITIZE-WITH-ATTR-NEXT: [[CONV:%.*]] = trunc i32 [[NARROW]] to i8 +// SANITIZE-WITH-ATTR-NEXT: store i8 [[CONV]], ptr [[ARRAYIDX]], align 1, !tbaa [[TBAA8]] +// SANITIZE-WITH-ATTR-NEXT: ret void +// +// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local void @test10( +// NO-SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR1]] { +// NO-SANITIZE-WITH-ATTR-NEXT: entry: +// NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds [[STRUCT_UNION_OF_FAMS:%.*]], ptr [[P]], i64 0, i32 1 +// NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOT_COUNTED_BY_GEP]], align 4 +// NO-SANITIZE-WITH-ATTR-NEXT: [[NARROW:%.*]] = tail call i32 @llvm.smax.i32(i32 [[DOT_COUNTED_BY_LOAD]], i32 0) +// NO-SANITIZE-WITH-ATTR-NEXT: [[CONV:%.*]] = trunc i32 [[NARROW]] to i8 +// NO-SANITIZE-WITH-ATTR-NEXT: [[BYTES:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 12 +// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 +// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i8], ptr [[BYTES]], i64 0, i64 [[IDXPROM]] +// NO-SANITIZE-WITH-ATTR-NEXT: store i8 [[CONV]], ptr [[ARRAYIDX]], align 1, !tbaa [[TBAA6]] +// NO-SANITIZE-WITH-ATTR-NEXT: ret void +// +// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test10( +// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] { +// SANITIZE-WITHOUT-ATTR-NEXT: entry: +// SANITIZE-WITHOUT-ATTR-NEXT: [[BYTES:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 12 +// SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 +// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i8], ptr [[BYTES]], i64 0, i64 [[IDXPROM]] +// SANITIZE-WITHOUT-ATTR-NEXT: store i8 -1, ptr [[ARRAYIDX]], align 1, !tbaa [[TBAA6]] +// SANITIZE-WITHOUT-ATTR-NEXT: ret void +// +// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test10( +// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] { +// NO-SANITIZE-WITHOUT-ATTR-NEXT: entry: +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[BYTES:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 12 +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i8], ptr [[BYTES]], i64 0, i64 [[IDXPROM]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: store i8 -1, ptr [[ARRAYIDX]], align 1, !tbaa [[TBAA6]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret void +// +void test10(struct union_of_fams *p, int index) { + p->bytes[index] = (unsigned char)__builtin_dynamic_object_size(p->bytes, 1); +} + +// SANITIZE-WITH-ATTR-LABEL: define dso_local i64 @test10_bdos( +// SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef readonly [[P:%.*]]) local_unnamed_addr #[[ATTR2]] { +// SANITIZE-WITH-ATTR-NEXT: entry: +// SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds [[STRUCT_UNION_OF_FAMS:%.*]], ptr [[P]], i64 0, i32 1 +// SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOT_COUNTED_BY_GEP]], align 4 +// SANITIZE-WITH-ATTR-NEXT: [[NARROW:%.*]] = tail call i32 @llvm.smax.i32(i32 [[DOT_COUNTED_BY_LOAD]], i32 0) +// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = zext nneg i32 [[NARROW]] to i64 +// SANITIZE-WITH-ATTR-NEXT: ret i64 [[TMP0]] +// +// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local i64 @test10_bdos( +// NO-SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef readonly [[P:%.*]]) local_unnamed_addr #[[ATTR2]] { +// NO-SANITIZE-WITH-ATTR-NEXT: entry: +// NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds [[STRUCT_UNION_OF_FAMS:%.*]], ptr [[P]], i64 0, i32 1 +// NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOT_COUNTED_BY_GEP]], align 4 +// NO-SANITIZE-WITH-ATTR-NEXT: [[NARROW:%.*]] = tail call i32 @llvm.smax.i32(i32 [[DOT_COUNTED_BY_LOAD]], i32 0) +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = zext nneg i32 [[NARROW]] to i64 +// NO-SANITIZE-WITH-ATTR-NEXT: ret i64 [[TMP0]] +// +// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i64 @test10_bdos( +// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]]) local_unnamed_addr #[[ATTR0]] { +// SANITIZE-WITHOUT-ATTR-NEXT: entry: +// SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1 +// +// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i64 @test10_bdos( +// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr noundef readnone [[P:%.*]]) local_unnamed_addr #[[ATTR1]] { +// NO-SANITIZE-WITHOUT-ATTR-NEXT: entry: +// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1 +// +size_t test10_bdos(struct union_of_fams *p) { + return __builtin_dynamic_object_size(p->bytes, 1); +} + +// SANITIZE-WITH-ATTR-LABEL: define dso_local void @test11( +// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] { +// SANITIZE-WITH-ATTR-NEXT: entry: +// SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 +// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_GEP:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED:%.*]], ptr [[P]], i64 0, i32 1 +// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOTCOUNTED_BY_GEP]], align 4 +// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = zext i32 [[DOTCOUNTED_BY_LOAD]] to i64, !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp ult i64 [[IDXPROM]], [[TMP0]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP1]], label [[CONT3:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF3]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR: handler.out_of_bounds: +// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB16:[0-9]+]], i64 [[IDXPROM]]) #[[ATTR10]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META2]] +// SANITIZE-WITH-ATTR: cont3: +// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED]], ptr [[P]], i64 0, i32 2, i64 [[IDXPROM]] +// SANITIZE-WITH-ATTR-NEXT: store i32 4, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA4]] +// SANITIZE-WITH-ATTR-NEXT: ret void +// +// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local void @test11( +// NO-SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef writeonly [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] { +// NO-SANITIZE-WITH-ATTR-NEXT: entry: +// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 +// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED:%.*]], ptr [[P]], i64 0, i32 2, i64 [[IDXPROM]] +// NO-SANITIZE-WITH-ATTR-NEXT: store i32 4, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] +// NO-SANITIZE-WITH-ATTR-NEXT: ret void +// +// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test11( +// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] { +// SANITIZE-WITHOUT-ATTR-NEXT: entry: +// SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 +// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED:%.*]], ptr [[P]], i64 0, i32 2, i64 [[IDXPROM]] +// SANITIZE-WITHOUT-ATTR-NEXT: store i32 4, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] +// SANITIZE-WITHOUT-ATTR-NEXT: ret void +// +// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test11( +// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nocapture noundef writeonly [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] { +// NO-SANITIZE-WITHOUT-ATTR-NEXT: entry: +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED:%.*]], ptr [[P]], i64 0, i32 2, i64 [[IDXPROM]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: store i32 4, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret void +// +void test11(struct annotated *p, int index) { + p->array[index] = __builtin_dynamic_object_size(&p->count, 1); +} + +// SANITIZE-WITH-ATTR-LABEL: define dso_local noundef i64 @test11_bdos( +// SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef readnone [[P:%.*]]) local_unnamed_addr #[[ATTR4]] { +// SANITIZE-WITH-ATTR-NEXT: entry: +// SANITIZE-WITH-ATTR-NEXT: ret i64 4 +// +// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local noundef i64 @test11_bdos( +// NO-SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef readnone [[P:%.*]]) local_unnamed_addr #[[ATTR4]] { +// NO-SANITIZE-WITH-ATTR-NEXT: entry: +// NO-SANITIZE-WITH-ATTR-NEXT: ret i64 4 +// +// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local noundef i64 @test11_bdos( +// SANITIZE-WITHOUT-ATTR-SAME: ptr nocapture noundef readnone [[P:%.*]]) local_unnamed_addr #[[ATTR2]] { +// SANITIZE-WITHOUT-ATTR-NEXT: entry: +// SANITIZE-WITHOUT-ATTR-NEXT: ret i64 4 +// +// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local noundef i64 @test11_bdos( +// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nocapture noundef readnone [[P:%.*]]) local_unnamed_addr #[[ATTR1]] { +// NO-SANITIZE-WITHOUT-ATTR-NEXT: entry: +// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret i64 4 +// +size_t test11_bdos(struct annotated *p) { + return __builtin_dynamic_object_size(&p->count, 1); +} + +struct { + struct { + struct { + int num_entries; + }; + }; + int entries[] __attribute__((__counted_by__(num_entries))); +} test12_foo; + +struct hang { + int entries[6]; +} test12_bar; + +int test12_a, test12_b; + +// SANITIZE-WITH-ATTR-LABEL: define dso_local noundef i32 @test12( +// SANITIZE-WITH-ATTR-SAME: i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR5:[0-9]+]] { +// SANITIZE-WITH-ATTR-NEXT: entry: +// SANITIZE-WITH-ATTR-NEXT: [[BAZ:%.*]] = alloca [[STRUCT_HANG:%.*]], align 4 +// SANITIZE-WITH-ATTR-NEXT: call void @llvm.lifetime.start.p0(i64 24, ptr nonnull [[BAZ]]) #[[ATTR11:[0-9]+]] +// SANITIZE-WITH-ATTR-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 4 dereferenceable(24) [[BAZ]], ptr noundef nonnull align 4 dereferenceable(24) @test12_bar, i64 24, i1 false), !tbaa.struct [[TBAA_STRUCT9:![0-9]+]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = icmp ult i32 [[INDEX]], 6 +// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = zext i32 [[INDEX]] to i64 +// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP0]], label [[CONT:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF3]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR: handler.out_of_bounds: +// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB18:[0-9]+]], i64 [[TMP1]]) #[[ATTR10]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META2]] +// SANITIZE-WITH-ATTR: cont: +// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [6 x i32], ptr [[BAZ]], i64 0, i64 [[TMP1]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA4]] +// SANITIZE-WITH-ATTR-NEXT: store i32 [[TMP2]], ptr @test12_b, align 4, !tbaa [[TBAA4]] +// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_LOAD:%.*]] = load i32, ptr @test12_foo, align 4 +// SANITIZE-WITH-ATTR-NEXT: [[DOTNOT:%.*]] = icmp eq i32 [[DOTCOUNTED_BY_LOAD]], 0 +// SANITIZE-WITH-ATTR-NEXT: br i1 [[DOTNOT]], label [[HANDLER_OUT_OF_BOUNDS4:%.*]], label [[HANDLER_TYPE_MISMATCH6:%.*]], !prof [[PROF10:![0-9]+]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR: handler.out_of_bounds4: +// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB19:[0-9]+]], i64 0) #[[ATTR10]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META2]] +// SANITIZE-WITH-ATTR: handler.type_mismatch6: +// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_type_mismatch_v1_abort(ptr nonnull @[[GLOB20:[0-9]+]], i64 ptrtoint (ptr getelementptr inbounds ([[STRUCT_ANON_5:%.*]], ptr @test12_foo, i64 1, i32 0, i32 0, i32 0) to i64)) #[[ATTR10]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META2]] +// +// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local noundef i32 @test12( +// NO-SANITIZE-WITH-ATTR-SAME: i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR5:[0-9]+]] { +// NO-SANITIZE-WITH-ATTR-NEXT: entry: +// NO-SANITIZE-WITH-ATTR-NEXT: [[BAZ:%.*]] = alloca [[STRUCT_HANG:%.*]], align 4 +// NO-SANITIZE-WITH-ATTR-NEXT: call void @llvm.lifetime.start.p0(i64 24, ptr nonnull [[BAZ]]) #[[ATTR12:[0-9]+]] +// NO-SANITIZE-WITH-ATTR-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 4 dereferenceable(24) [[BAZ]], ptr noundef nonnull align 4 dereferenceable(24) @test12_bar, i64 24, i1 false), !tbaa.struct [[TBAA_STRUCT7:![0-9]+]] +// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 +// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [6 x i32], ptr [[BAZ]], i64 0, i64 [[IDXPROM]] +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] +// NO-SANITIZE-WITH-ATTR-NEXT: store i32 [[TMP0]], ptr @test12_b, align 4, !tbaa [[TBAA2]] +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = load i32, ptr getelementptr inbounds ([[STRUCT_ANON_5:%.*]], ptr @test12_foo, i64 1, i32 0, i32 0, i32 0), align 4, !tbaa [[TBAA2]] +// NO-SANITIZE-WITH-ATTR-NEXT: store i32 [[TMP1]], ptr @test12_a, align 4, !tbaa [[TBAA2]] +// NO-SANITIZE-WITH-ATTR-NEXT: br label [[FOR_COND:%.*]] +// NO-SANITIZE-WITH-ATTR: for.cond: +// NO-SANITIZE-WITH-ATTR-NEXT: br label [[FOR_COND]] +// +// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local noundef i32 @test12( +// SANITIZE-WITHOUT-ATTR-SAME: i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR3:[0-9]+]] { +// SANITIZE-WITHOUT-ATTR-NEXT: entry: +// SANITIZE-WITHOUT-ATTR-NEXT: [[BAZ:%.*]] = alloca [[STRUCT_HANG:%.*]], align 4 +// SANITIZE-WITHOUT-ATTR-NEXT: call void @llvm.lifetime.start.p0(i64 24, ptr nonnull [[BAZ]]) #[[ATTR7:[0-9]+]] +// SANITIZE-WITHOUT-ATTR-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 4 dereferenceable(24) [[BAZ]], ptr noundef nonnull align 4 dereferenceable(24) @test12_bar, i64 24, i1 false), !tbaa.struct [[TBAA_STRUCT7:![0-9]+]] +// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = icmp ult i32 [[INDEX]], 6 +// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP1:%.*]] = zext i32 [[INDEX]] to i64 +// SANITIZE-WITHOUT-ATTR-NEXT: br i1 [[TMP0]], label [[CONT:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF8:![0-9]+]], !nosanitize [[META9:![0-9]+]] +// SANITIZE-WITHOUT-ATTR: handler.out_of_bounds: +// SANITIZE-WITHOUT-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB2:[0-9]+]], i64 [[TMP1]]) #[[ATTR8:[0-9]+]], !nosanitize [[META9]] +// SANITIZE-WITHOUT-ATTR-NEXT: unreachable, !nosanitize [[META9]] +// SANITIZE-WITHOUT-ATTR: cont: +// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [6 x i32], ptr [[BAZ]], i64 0, i64 [[TMP1]] +// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] +// SANITIZE-WITHOUT-ATTR-NEXT: store i32 [[TMP2]], ptr @test12_b, align 4, !tbaa [[TBAA2]] +// SANITIZE-WITHOUT-ATTR-NEXT: [[DOTCOUNTED_BY_LOAD:%.*]] = load i32, ptr @test12_foo, align 4 +// SANITIZE-WITHOUT-ATTR-NEXT: [[DOTNOT:%.*]] = icmp eq i32 [[DOTCOUNTED_BY_LOAD]], 0 +// SANITIZE-WITHOUT-ATTR-NEXT: br i1 [[DOTNOT]], label [[HANDLER_OUT_OF_BOUNDS4:%.*]], label [[HANDLER_TYPE_MISMATCH6:%.*]], !prof [[PROF10:![0-9]+]], !nosanitize [[META9]] +// SANITIZE-WITHOUT-ATTR: handler.out_of_bounds4: +// SANITIZE-WITHOUT-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB4:[0-9]+]], i64 0) #[[ATTR8]], !nosanitize [[META9]] +// SANITIZE-WITHOUT-ATTR-NEXT: unreachable, !nosanitize [[META9]] +// SANITIZE-WITHOUT-ATTR: handler.type_mismatch6: +// SANITIZE-WITHOUT-ATTR-NEXT: tail call void @__ubsan_handle_type_mismatch_v1_abort(ptr nonnull @[[GLOB5:[0-9]+]], i64 ptrtoint (ptr getelementptr inbounds ([[STRUCT_ANON_5:%.*]], ptr @test12_foo, i64 1, i32 0, i32 0, i32 0) to i64)) #[[ATTR8]], !nosanitize [[META9]] +// SANITIZE-WITHOUT-ATTR-NEXT: unreachable, !nosanitize [[META9]] +// +// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local noundef i32 @test12( +// NO-SANITIZE-WITHOUT-ATTR-SAME: i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR2:[0-9]+]] { +// NO-SANITIZE-WITHOUT-ATTR-NEXT: entry: +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[BAZ:%.*]] = alloca [[STRUCT_HANG:%.*]], align 4 +// NO-SANITIZE-WITHOUT-ATTR-NEXT: call void @llvm.lifetime.start.p0(i64 24, ptr nonnull [[BAZ]]) #[[ATTR9:[0-9]+]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 4 dereferenceable(24) [[BAZ]], ptr noundef nonnull align 4 dereferenceable(24) @test12_bar, i64 24, i1 false), !tbaa.struct [[TBAA_STRUCT7:![0-9]+]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [6 x i32], ptr [[BAZ]], i64 0, i64 [[IDXPROM]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: store i32 [[TMP0]], ptr @test12_b, align 4, !tbaa [[TBAA2]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP1:%.*]] = load i32, ptr getelementptr inbounds ([[STRUCT_ANON_5:%.*]], ptr @test12_foo, i64 1, i32 0, i32 0, i32 0), align 4, !tbaa [[TBAA2]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: store i32 [[TMP1]], ptr @test12_a, align 4, !tbaa [[TBAA2]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: br label [[FOR_COND:%.*]] +// NO-SANITIZE-WITHOUT-ATTR: for.cond: +// NO-SANITIZE-WITHOUT-ATTR-NEXT: br label [[FOR_COND]] +// +int test12(int index) { + struct hang baz = test12_bar; + + for (;; test12_a = (&test12_foo)->entries[0]) + test12_b = baz.entries[index]; + + return test12_b; +} + +struct test13_foo { + struct test13_bar *domain; +} test13_f; + +struct test13_bar { + struct test13_bar *parent; + int revmap_size; + struct test13_foo *revmap[] __attribute__((__counted_by__(revmap_size))); +}; + +// SANITIZE-WITH-ATTR-LABEL: define dso_local noundef i32 @test13( +// SANITIZE-WITH-ATTR-SAME: i64 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] { +// SANITIZE-WITH-ATTR-NEXT: entry: +// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr @test13_f, align 8, !tbaa [[TBAA11:![0-9]+]] +// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_GEP:%.*]] = getelementptr inbounds [[STRUCT_TEST13_BAR:%.*]], ptr [[TMP0]], i64 0, i32 1 +// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOTCOUNTED_BY_GEP]], align 4 +// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = zext i32 [[DOTCOUNTED_BY_LOAD]] to i64, !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = icmp ugt i64 [[TMP1]], [[INDEX]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP2]], label [[CONT5:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF3]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR: handler.out_of_bounds: +// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB23:[0-9]+]], i64 [[INDEX]]) #[[ATTR10]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META2]] +// SANITIZE-WITH-ATTR: cont5: +// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_TEST13_BAR]], ptr [[TMP0]], i64 0, i32 2, i64 [[INDEX]] +// SANITIZE-WITH-ATTR-NEXT: store ptr null, ptr [[ARRAYIDX]], align 8, !tbaa [[TBAA14:![0-9]+]] +// SANITIZE-WITH-ATTR-NEXT: ret i32 0 +// +// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local noundef i32 @test13( +// NO-SANITIZE-WITH-ATTR-SAME: i64 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR8:[0-9]+]] { +// NO-SANITIZE-WITH-ATTR-NEXT: entry: +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr @test13_f, align 8, !tbaa [[TBAA8:![0-9]+]] +// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_TEST13_BAR:%.*]], ptr [[TMP0]], i64 0, i32 2, i64 [[INDEX]] +// NO-SANITIZE-WITH-ATTR-NEXT: store ptr null, ptr [[ARRAYIDX]], align 8, !tbaa [[TBAA11:![0-9]+]] +// NO-SANITIZE-WITH-ATTR-NEXT: ret i32 0 +// +// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local noundef i32 @test13( +// SANITIZE-WITHOUT-ATTR-SAME: i64 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] { +// SANITIZE-WITHOUT-ATTR-NEXT: entry: +// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr @test13_f, align 8, !tbaa [[TBAA11:![0-9]+]] +// SANITIZE-WITHOUT-ATTR-NEXT: [[DOTCOUNTED_BY_GEP:%.*]] = getelementptr inbounds [[STRUCT_TEST13_BAR:%.*]], ptr [[TMP0]], i64 0, i32 1 +// SANITIZE-WITHOUT-ATTR-NEXT: [[DOTCOUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOTCOUNTED_BY_GEP]], align 4 +// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP1:%.*]] = zext i32 [[DOTCOUNTED_BY_LOAD]] to i64, !nosanitize [[META9]] +// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP2:%.*]] = icmp ugt i64 [[TMP1]], [[INDEX]], !nosanitize [[META9]] +// SANITIZE-WITHOUT-ATTR-NEXT: br i1 [[TMP2]], label [[CONT5:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF8]], !nosanitize [[META9]] +// SANITIZE-WITHOUT-ATTR: handler.out_of_bounds: +// SANITIZE-WITHOUT-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB8:[0-9]+]], i64 [[INDEX]]) #[[ATTR8]], !nosanitize [[META9]] +// SANITIZE-WITHOUT-ATTR-NEXT: unreachable, !nosanitize [[META9]] +// SANITIZE-WITHOUT-ATTR: cont5: +// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_TEST13_BAR]], ptr [[TMP0]], i64 0, i32 2, i64 [[INDEX]] +// SANITIZE-WITHOUT-ATTR-NEXT: store ptr null, ptr [[ARRAYIDX]], align 8, !tbaa [[TBAA14:![0-9]+]] +// SANITIZE-WITHOUT-ATTR-NEXT: ret i32 0 +// +// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local noundef i32 @test13( +// NO-SANITIZE-WITHOUT-ATTR-SAME: i64 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR5:[0-9]+]] { +// NO-SANITIZE-WITHOUT-ATTR-NEXT: entry: +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr @test13_f, align 8, !tbaa [[TBAA8:![0-9]+]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_TEST13_BAR:%.*]], ptr [[TMP0]], i64 0, i32 2, i64 [[INDEX]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: store ptr null, ptr [[ARRAYIDX]], align 8, !tbaa [[TBAA11:![0-9]+]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret i32 0 +// +int test13(long index) { + test13_f.domain->revmap[index] = 0; + return 0; +} + +struct test14_foo { + int x, y; + int blah[] __attribute__((counted_by(x))); +}; + +// SANITIZE-WITH-ATTR-LABEL: define dso_local i32 @test14( +// SANITIZE-WITH-ATTR-SAME: i32 noundef [[IDX:%.*]]) local_unnamed_addr #[[ATTR0]] { +// SANITIZE-WITH-ATTR-NEXT: entry: +// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = icmp eq i32 [[IDX]], 0 +// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP0]], label [[TRAP:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF3]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR: handler.out_of_bounds: +// SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[IDX]] to i64 +// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB24:[0-9]+]], i64 [[IDXPROM]]) #[[ATTR10]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META2]] +// SANITIZE-WITH-ATTR: trap: +// SANITIZE-WITH-ATTR-NEXT: tail call void @llvm.trap() #[[ATTR10]] +// SANITIZE-WITH-ATTR-NEXT: unreachable +// +// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local i32 @test14( +// NO-SANITIZE-WITH-ATTR-SAME: i32 noundef [[IDX:%.*]]) local_unnamed_addr #[[ATTR4]] { +// NO-SANITIZE-WITH-ATTR-NEXT: entry: +// NO-SANITIZE-WITH-ATTR-NEXT: [[DOTCOMPOUNDLITERAL:%.*]] = alloca [[STRUCT_TEST14_FOO:%.*]], align 4 +// NO-SANITIZE-WITH-ATTR-NEXT: store i32 1, ptr [[DOTCOMPOUNDLITERAL]], align 4, !tbaa [[TBAA2]] +// NO-SANITIZE-WITH-ATTR-NEXT: [[Y:%.*]] = getelementptr inbounds [[STRUCT_TEST14_FOO]], ptr [[DOTCOMPOUNDLITERAL]], i64 0, i32 1 +// NO-SANITIZE-WITH-ATTR-NEXT: store i32 2, ptr [[Y]], align 4, !tbaa [[TBAA2]] +// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[IDX]] to i64 +// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_TEST14_FOO]], ptr [[DOTCOMPOUNDLITERAL]], i64 0, i32 2, i64 [[IDXPROM]] +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] +// NO-SANITIZE-WITH-ATTR-NEXT: ret i32 [[TMP0]] +// +// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i32 @test14( +// SANITIZE-WITHOUT-ATTR-SAME: i32 noundef [[IDX:%.*]]) local_unnamed_addr #[[ATTR0]] { +// SANITIZE-WITHOUT-ATTR-NEXT: entry: +// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = icmp eq i32 [[IDX]], 0 +// SANITIZE-WITHOUT-ATTR-NEXT: br i1 [[TMP0]], label [[TRAP:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF8]], !nosanitize [[META9]] +// SANITIZE-WITHOUT-ATTR: handler.out_of_bounds: +// SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[IDX]] to i64 +// SANITIZE-WITHOUT-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB9:[0-9]+]], i64 [[IDXPROM]]) #[[ATTR8]], !nosanitize [[META9]] +// SANITIZE-WITHOUT-ATTR-NEXT: unreachable, !nosanitize [[META9]] +// SANITIZE-WITHOUT-ATTR: trap: +// SANITIZE-WITHOUT-ATTR-NEXT: tail call void @llvm.trap() #[[ATTR8]] +// SANITIZE-WITHOUT-ATTR-NEXT: unreachable +// +// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i32 @test14( +// NO-SANITIZE-WITHOUT-ATTR-SAME: i32 noundef [[IDX:%.*]]) local_unnamed_addr #[[ATTR1]] { +// NO-SANITIZE-WITHOUT-ATTR-NEXT: entry: +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[DOTCOMPOUNDLITERAL:%.*]] = alloca [[STRUCT_TEST14_FOO:%.*]], align 4 +// NO-SANITIZE-WITHOUT-ATTR-NEXT: store i32 1, ptr [[DOTCOMPOUNDLITERAL]], align 4, !tbaa [[TBAA2]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[Y:%.*]] = getelementptr inbounds [[STRUCT_TEST14_FOO]], ptr [[DOTCOMPOUNDLITERAL]], i64 0, i32 1 +// NO-SANITIZE-WITHOUT-ATTR-NEXT: store i32 2, ptr [[Y]], align 4, !tbaa [[TBAA2]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[IDX]] to i64 +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_TEST14_FOO]], ptr [[DOTCOMPOUNDLITERAL]], i64 0, i32 2, i64 [[IDXPROM]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret i32 [[TMP0]] +// +int test14(int idx) { + return (struct test14_foo){ 1, 2 }.blah[idx]; +} + +// SANITIZE-WITH-ATTR-LABEL: define dso_local i32 @test15( +// SANITIZE-WITH-ATTR-SAME: i32 noundef [[IDX:%.*]]) local_unnamed_addr #[[ATTR0]] { +// SANITIZE-WITH-ATTR-NEXT: entry: +// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = icmp eq i32 [[IDX]], 0 +// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP0]], label [[TRAP:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF3]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR: handler.out_of_bounds: +// SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[IDX]] to i64 +// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB25:[0-9]+]], i64 [[IDXPROM]]) #[[ATTR10]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META2]] +// SANITIZE-WITH-ATTR: trap: +// SANITIZE-WITH-ATTR-NEXT: tail call void @llvm.trap() #[[ATTR10]] +// SANITIZE-WITH-ATTR-NEXT: unreachable +// +// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local i32 @test15( +// NO-SANITIZE-WITH-ATTR-SAME: i32 noundef [[IDX:%.*]]) local_unnamed_addr #[[ATTR4]] { +// NO-SANITIZE-WITH-ATTR-NEXT: entry: +// NO-SANITIZE-WITH-ATTR-NEXT: [[FOO:%.*]] = alloca [[STRUCT_ANON_8:%.*]], align 4 +// NO-SANITIZE-WITH-ATTR-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr nonnull [[FOO]]) #[[ATTR12]] +// NO-SANITIZE-WITH-ATTR-NEXT: store i32 1, ptr [[FOO]], align 4 +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[FOO]], i64 4 +// NO-SANITIZE-WITH-ATTR-NEXT: store i32 2, ptr [[TMP0]], align 4 +// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[IDX]] to i64 +// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_ANON_8]], ptr [[FOO]], i64 0, i32 2, i64 [[IDXPROM]] +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = load i32, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] +// NO-SANITIZE-WITH-ATTR-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr nonnull [[FOO]]) #[[ATTR12]] +// NO-SANITIZE-WITH-ATTR-NEXT: ret i32 [[TMP1]] +// +// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i32 @test15( +// SANITIZE-WITHOUT-ATTR-SAME: i32 noundef [[IDX:%.*]]) local_unnamed_addr #[[ATTR0]] { +// SANITIZE-WITHOUT-ATTR-NEXT: entry: +// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = icmp eq i32 [[IDX]], 0 +// SANITIZE-WITHOUT-ATTR-NEXT: br i1 [[TMP0]], label [[TRAP:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF8]], !nosanitize [[META9]] +// SANITIZE-WITHOUT-ATTR: handler.out_of_bounds: +// SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[IDX]] to i64 +// SANITIZE-WITHOUT-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB10:[0-9]+]], i64 [[IDXPROM]]) #[[ATTR8]], !nosanitize [[META9]] +// SANITIZE-WITHOUT-ATTR-NEXT: unreachable, !nosanitize [[META9]] +// SANITIZE-WITHOUT-ATTR: trap: +// SANITIZE-WITHOUT-ATTR-NEXT: tail call void @llvm.trap() #[[ATTR8]] +// SANITIZE-WITHOUT-ATTR-NEXT: unreachable +// +// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i32 @test15( +// NO-SANITIZE-WITHOUT-ATTR-SAME: i32 noundef [[IDX:%.*]]) local_unnamed_addr #[[ATTR1]] { +// NO-SANITIZE-WITHOUT-ATTR-NEXT: entry: +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[FOO:%.*]] = alloca [[STRUCT_ANON_8:%.*]], align 4 +// NO-SANITIZE-WITHOUT-ATTR-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr nonnull [[FOO]]) #[[ATTR9]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: store i32 1, ptr [[FOO]], align 4 +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[FOO]], i64 4 +// NO-SANITIZE-WITHOUT-ATTR-NEXT: store i32 2, ptr [[TMP0]], align 4 +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[IDX]] to i64 +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_ANON_8]], ptr [[FOO]], i64 0, i32 2, i64 [[IDXPROM]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP1:%.*]] = load i32, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr nonnull [[FOO]]) #[[ATTR9]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret i32 [[TMP1]] +// +int test15(int idx) { + struct { + int x, y; + int blah[] __attribute__((counted_by(x))); + } foo = { 1, 2 }; + + return foo.blah[idx]; +} + +// SANITIZE-WITH-ATTR-LABEL: define dso_local noundef i64 @test19( +// SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef readnone [[P:%.*]]) local_unnamed_addr #[[ATTR4]] { +// SANITIZE-WITH-ATTR-NEXT: entry: +// SANITIZE-WITH-ATTR-NEXT: ret i64 -1 +// +// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local noundef i64 @test19( +// NO-SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef readnone [[P:%.*]]) local_unnamed_addr #[[ATTR4]] { +// NO-SANITIZE-WITH-ATTR-NEXT: entry: +// NO-SANITIZE-WITH-ATTR-NEXT: ret i64 -1 +// +// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i64 @test19( +// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]]) local_unnamed_addr #[[ATTR0]] { +// SANITIZE-WITHOUT-ATTR-NEXT: entry: +// SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1 +// +// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i64 @test19( +// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr noundef readnone [[P:%.*]]) local_unnamed_addr #[[ATTR1]] { +// NO-SANITIZE-WITHOUT-ATTR-NEXT: entry: +// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1 +// +size_t test19(struct annotated *p) { + // Avoid pointer arithmetic. It could lead to security issues. + return __builtin_dynamic_object_size(&(p + 42)->array[2], 1); +} + +// SANITIZE-WITH-ATTR-LABEL: define dso_local noundef i64 @test20( +// SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef readnone [[P:%.*]]) local_unnamed_addr #[[ATTR4]] { +// SANITIZE-WITH-ATTR-NEXT: entry: +// SANITIZE-WITH-ATTR-NEXT: ret i64 -1 +// +// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local noundef i64 @test20( +// NO-SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef readnone [[P:%.*]]) local_unnamed_addr #[[ATTR4]] { +// NO-SANITIZE-WITH-ATTR-NEXT: entry: +// NO-SANITIZE-WITH-ATTR-NEXT: ret i64 -1 +// +// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local noundef i64 @test20( +// SANITIZE-WITHOUT-ATTR-SAME: ptr nocapture noundef readnone [[P:%.*]]) local_unnamed_addr #[[ATTR2]] { +// SANITIZE-WITHOUT-ATTR-NEXT: entry: +// SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1 +// +// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local noundef i64 @test20( +// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nocapture noundef readnone [[P:%.*]]) local_unnamed_addr #[[ATTR1]] { +// NO-SANITIZE-WITHOUT-ATTR-NEXT: entry: +// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1 +// +size_t test20(struct annotated *p) { + // Avoid side-effects. + return __builtin_dynamic_object_size(&(++p)->array[2], 1); +} + +// SANITIZE-WITH-ATTR-LABEL: define dso_local noundef i64 @test21( +// SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef readnone [[P:%.*]]) local_unnamed_addr #[[ATTR4]] { +// SANITIZE-WITH-ATTR-NEXT: entry: +// SANITIZE-WITH-ATTR-NEXT: ret i64 -1 +// +// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local noundef i64 @test21( +// NO-SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef readnone [[P:%.*]]) local_unnamed_addr #[[ATTR4]] { +// NO-SANITIZE-WITH-ATTR-NEXT: entry: +// NO-SANITIZE-WITH-ATTR-NEXT: ret i64 -1 +// +// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local noundef i64 @test21( +// SANITIZE-WITHOUT-ATTR-SAME: ptr nocapture noundef readnone [[P:%.*]]) local_unnamed_addr #[[ATTR2]] { +// SANITIZE-WITHOUT-ATTR-NEXT: entry: +// SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1 +// +// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local noundef i64 @test21( +// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nocapture noundef readnone [[P:%.*]]) local_unnamed_addr #[[ATTR1]] { +// NO-SANITIZE-WITHOUT-ATTR-NEXT: entry: +// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1 +// +size_t test21(struct annotated *p) { + // Avoid side-effects. + return __builtin_dynamic_object_size(&(p++)->array[2], 1); +} + +// SANITIZE-WITH-ATTR-LABEL: define dso_local noundef i64 @test22( +// SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef readnone [[P:%.*]]) local_unnamed_addr #[[ATTR4]] { +// SANITIZE-WITH-ATTR-NEXT: entry: +// SANITIZE-WITH-ATTR-NEXT: ret i64 -1 +// +// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local noundef i64 @test22( +// NO-SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef readnone [[P:%.*]]) local_unnamed_addr #[[ATTR4]] { +// NO-SANITIZE-WITH-ATTR-NEXT: entry: +// NO-SANITIZE-WITH-ATTR-NEXT: ret i64 -1 +// +// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local noundef i64 @test22( +// SANITIZE-WITHOUT-ATTR-SAME: ptr nocapture noundef readnone [[P:%.*]]) local_unnamed_addr #[[ATTR2]] { +// SANITIZE-WITHOUT-ATTR-NEXT: entry: +// SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1 +// +// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local noundef i64 @test22( +// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nocapture noundef readnone [[P:%.*]]) local_unnamed_addr #[[ATTR1]] { +// NO-SANITIZE-WITHOUT-ATTR-NEXT: entry: +// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1 +// +size_t test22(struct annotated *p) { + // Avoid side-effects. + return __builtin_dynamic_object_size(&(--p)->array[2], 1); +} + +// SANITIZE-WITH-ATTR-LABEL: define dso_local noundef i64 @test23( +// SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef readnone [[P:%.*]]) local_unnamed_addr #[[ATTR4]] { +// SANITIZE-WITH-ATTR-NEXT: entry: +// SANITIZE-WITH-ATTR-NEXT: ret i64 -1 +// +// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local noundef i64 @test23( +// NO-SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef readnone [[P:%.*]]) local_unnamed_addr #[[ATTR4]] { +// NO-SANITIZE-WITH-ATTR-NEXT: entry: +// NO-SANITIZE-WITH-ATTR-NEXT: ret i64 -1 +// +// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local noundef i64 @test23( +// SANITIZE-WITHOUT-ATTR-SAME: ptr nocapture noundef readnone [[P:%.*]]) local_unnamed_addr #[[ATTR2]] { +// SANITIZE-WITHOUT-ATTR-NEXT: entry: +// SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1 +// +// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local noundef i64 @test23( +// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nocapture noundef readnone [[P:%.*]]) local_unnamed_addr #[[ATTR1]] { +// NO-SANITIZE-WITHOUT-ATTR-NEXT: entry: +// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -1 +// +size_t test23(struct annotated *p) { + // Avoid side-effects. + return __builtin_dynamic_object_size(&(p--)->array[2], 1); +} + +struct tests_foo { + int count; + int arr[] __counted_by(count); +}; + +// SANITIZE-WITH-ATTR-LABEL: define dso_local i32 @test24( +// SANITIZE-WITH-ATTR-SAME: i32 noundef [[C:%.*]], ptr noundef [[VAR:%.*]]) local_unnamed_addr #[[ATTR0]] { +// SANITIZE-WITH-ATTR-NEXT: entry: +// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_TESTS_FOO:%.*]], ptr [[VAR]], i64 10 +// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_LOAD:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 +// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = icmp ugt i32 [[DOTCOUNTED_BY_LOAD]], 10 +// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP0]], label [[CONT4:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF3]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR: handler.out_of_bounds: +// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB26:[0-9]+]], i64 10) #[[ATTR10]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META2]] +// SANITIZE-WITH-ATTR: cont4: +// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds [[STRUCT_TESTS_FOO]], ptr [[VAR]], i64 21 +// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = load i32, ptr [[ARRAYIDX2]], align 4, !tbaa [[TBAA4]] +// SANITIZE-WITH-ATTR-NEXT: ret i32 [[TMP1]] +// +// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local i32 @test24( +// NO-SANITIZE-WITH-ATTR-SAME: i32 noundef [[C:%.*]], ptr nocapture noundef readonly [[VAR:%.*]]) local_unnamed_addr #[[ATTR2]] { +// NO-SANITIZE-WITH-ATTR-NEXT: entry: +// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds [[STRUCT_TESTS_FOO:%.*]], ptr [[VAR]], i64 21 +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX1]], align 4, !tbaa [[TBAA2]] +// NO-SANITIZE-WITH-ATTR-NEXT: ret i32 [[TMP0]] +// +// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i32 @test24( +// SANITIZE-WITHOUT-ATTR-SAME: i32 noundef [[C:%.*]], ptr noundef [[VAR:%.*]]) local_unnamed_addr #[[ATTR0]] { +// SANITIZE-WITHOUT-ATTR-NEXT: entry: +// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds [[STRUCT_TESTS_FOO:%.*]], ptr [[VAR]], i64 21 +// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX1]], align 4, !tbaa [[TBAA2]] +// SANITIZE-WITHOUT-ATTR-NEXT: ret i32 [[TMP0]] +// +// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i32 @test24( +// NO-SANITIZE-WITHOUT-ATTR-SAME: i32 noundef [[C:%.*]], ptr nocapture noundef readonly [[VAR:%.*]]) local_unnamed_addr #[[ATTR6:[0-9]+]] { +// NO-SANITIZE-WITHOUT-ATTR-NEXT: entry: +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds [[STRUCT_TESTS_FOO:%.*]], ptr [[VAR]], i64 21 +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX1]], align 4, !tbaa [[TBAA2]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret i32 [[TMP0]] +// +int test24(int c, struct tests_foo *var) { + // Invalid: there can't be an array of flexible arrays. + return var[10].arr[10]; +} + +// SANITIZE-WITH-ATTR-LABEL: define dso_local i32 @test25( +// SANITIZE-WITH-ATTR-SAME: i32 noundef [[C:%.*]], ptr noundef [[VAR:%.*]]) local_unnamed_addr #[[ATTR0]] { +// SANITIZE-WITH-ATTR-NEXT: entry: +// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VAR]], align 8, !tbaa [[TBAA14]] +// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_LOAD:%.*]] = load i32, ptr [[TMP0]], align 4 +// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp ugt i32 [[DOTCOUNTED_BY_LOAD]], 10 +// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP1]], label [[CONT5:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF3]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR: handler.out_of_bounds: +// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB27:[0-9]+]], i64 10) #[[ATTR10]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META2]] +// SANITIZE-WITH-ATTR: cont5: +// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_TESTS_FOO:%.*]], ptr [[TMP0]], i64 11 +// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA4]] +// SANITIZE-WITH-ATTR-NEXT: ret i32 [[TMP2]] +// +// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local i32 @test25( +// NO-SANITIZE-WITH-ATTR-SAME: i32 noundef [[C:%.*]], ptr nocapture noundef readonly [[VAR:%.*]]) local_unnamed_addr #[[ATTR9:[0-9]+]] { +// NO-SANITIZE-WITH-ATTR-NEXT: entry: +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VAR]], align 8, !tbaa [[TBAA11]] +// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_TESTS_FOO:%.*]], ptr [[TMP0]], i64 11 +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = load i32, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] +// NO-SANITIZE-WITH-ATTR-NEXT: ret i32 [[TMP1]] +// +// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i32 @test25( +// SANITIZE-WITHOUT-ATTR-SAME: i32 noundef [[C:%.*]], ptr noundef [[VAR:%.*]]) local_unnamed_addr #[[ATTR0]] { +// SANITIZE-WITHOUT-ATTR-NEXT: entry: +// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VAR]], align 8, !tbaa [[TBAA14]] +// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_TESTS_FOO:%.*]], ptr [[TMP0]], i64 11 +// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP1:%.*]] = load i32, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] +// SANITIZE-WITHOUT-ATTR-NEXT: ret i32 [[TMP1]] +// +// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i32 @test25( +// NO-SANITIZE-WITHOUT-ATTR-SAME: i32 noundef [[C:%.*]], ptr nocapture noundef readonly [[VAR:%.*]]) local_unnamed_addr #[[ATTR7:[0-9]+]] { +// NO-SANITIZE-WITHOUT-ATTR-NEXT: entry: +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VAR]], align 8, !tbaa [[TBAA11]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_TESTS_FOO:%.*]], ptr [[TMP0]], i64 11 +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP1:%.*]] = load i32, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret i32 [[TMP1]] +// +int test25(int c, struct tests_foo **var) { + // Double dereferenced variable. + return (**var).arr[10]; +} + +// Outer struct +struct test26_foo { + int a; + struct tests_foo s; +}; + +// SANITIZE-WITH-ATTR-LABEL: define dso_local i32 @test26( +// SANITIZE-WITH-ATTR-SAME: i32 noundef [[C:%.*]], ptr noundef [[FOO:%.*]]) local_unnamed_addr #[[ATTR0]] { +// SANITIZE-WITH-ATTR-NEXT: entry: +// SANITIZE-WITH-ATTR-NEXT: [[S:%.*]] = getelementptr inbounds [[STRUCT_TEST26_FOO:%.*]], ptr [[FOO]], i64 0, i32 1 +// SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[C]] to i64 +// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_LOAD:%.*]] = load i32, ptr [[S]], align 4 +// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = zext i32 [[DOTCOUNTED_BY_LOAD]] to i64, !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp ult i64 [[IDXPROM]], [[TMP0]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP1]], label [[CONT5:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF3]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR: handler.out_of_bounds: +// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB28:[0-9]+]], i64 [[IDXPROM]]) #[[ATTR10]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META2]] +// SANITIZE-WITH-ATTR: cont5: +// SANITIZE-WITH-ATTR-NEXT: [[ARR:%.*]] = getelementptr inbounds [[STRUCT_TEST26_FOO]], ptr [[FOO]], i64 1 +// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i32], ptr [[ARR]], i64 0, i64 [[IDXPROM]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA4]] +// SANITIZE-WITH-ATTR-NEXT: ret i32 [[TMP2]] +// +// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local i32 @test26( +// NO-SANITIZE-WITH-ATTR-SAME: i32 noundef [[C:%.*]], ptr nocapture noundef readonly [[FOO:%.*]]) local_unnamed_addr #[[ATTR2]] { +// NO-SANITIZE-WITH-ATTR-NEXT: entry: +// NO-SANITIZE-WITH-ATTR-NEXT: [[ARR:%.*]] = getelementptr inbounds [[STRUCT_TEST26_FOO:%.*]], ptr [[FOO]], i64 1 +// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[C]] to i64 +// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i32], ptr [[ARR]], i64 0, i64 [[IDXPROM]] +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] +// NO-SANITIZE-WITH-ATTR-NEXT: ret i32 [[TMP0]] +// +// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i32 @test26( +// SANITIZE-WITHOUT-ATTR-SAME: i32 noundef [[C:%.*]], ptr noundef [[FOO:%.*]]) local_unnamed_addr #[[ATTR0]] { +// SANITIZE-WITHOUT-ATTR-NEXT: entry: +// SANITIZE-WITHOUT-ATTR-NEXT: [[ARR:%.*]] = getelementptr inbounds [[STRUCT_TEST26_FOO:%.*]], ptr [[FOO]], i64 1 +// SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[C]] to i64 +// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i32], ptr [[ARR]], i64 0, i64 [[IDXPROM]] +// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] +// SANITIZE-WITHOUT-ATTR-NEXT: ret i32 [[TMP0]] +// +// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i32 @test26( +// NO-SANITIZE-WITHOUT-ATTR-SAME: i32 noundef [[C:%.*]], ptr nocapture noundef readonly [[FOO:%.*]]) local_unnamed_addr #[[ATTR6]] { +// NO-SANITIZE-WITHOUT-ATTR-NEXT: entry: +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARR:%.*]] = getelementptr inbounds [[STRUCT_TEST26_FOO:%.*]], ptr [[FOO]], i64 1 +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[C]] to i64 +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i32], ptr [[ARR]], i64 0, i64 [[IDXPROM]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret i32 [[TMP0]] +// +int test26(int c, struct test26_foo *foo) { + // Invalid: A structure with a flexible array must be a pointer. + return foo->s.arr[c]; +} + +struct test27_baz; + +struct test27_bar { + unsigned char type; + unsigned char flags; + unsigned short use_cnt; + unsigned char hw_priv; +}; + +struct test27_foo { + struct test27_baz *a; + + unsigned char bit1 : 1; + unsigned char bit2 : 1; + unsigned char bit3 : 1; + + unsigned int n_tables; + unsigned long missed; + struct test27_bar *entries[] __counted_by(n_tables); +}; + +// SANITIZE-WITH-ATTR-LABEL: define dso_local ptr @test27( +// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[I:%.*]], i32 noundef [[J:%.*]]) local_unnamed_addr #[[ATTR0]] { +// SANITIZE-WITH-ATTR-NEXT: entry: +// SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[I]] to i64 +// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_GEP:%.*]] = getelementptr inbounds [[STRUCT_TEST27_FOO:%.*]], ptr [[P]], i64 0, i32 2 +// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOTCOUNTED_BY_GEP]], align 4 +// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = zext i32 [[DOTCOUNTED_BY_LOAD]] to i64, !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp ult i64 [[IDXPROM]], [[TMP0]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP1]], label [[CONT3:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF3]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR: handler.out_of_bounds: +// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB30:[0-9]+]], i64 [[IDXPROM]]) #[[ATTR10]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META2]] +// SANITIZE-WITH-ATTR: cont3: +// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_TEST27_FOO]], ptr [[P]], i64 0, i32 4, i64 [[IDXPROM]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = load ptr, ptr [[ARRAYIDX]], align 8, !tbaa [[TBAA14]] +// SANITIZE-WITH-ATTR-NEXT: [[IDXPROM4:%.*]] = sext i32 [[J]] to i64 +// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX5:%.*]] = getelementptr inbounds [[STRUCT_TEST27_BAR:%.*]], ptr [[TMP2]], i64 [[IDXPROM4]] +// SANITIZE-WITH-ATTR-NEXT: ret ptr [[ARRAYIDX5]] +// +// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local ptr @test27( +// NO-SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef readonly [[P:%.*]], i32 noundef [[I:%.*]], i32 noundef [[J:%.*]]) local_unnamed_addr #[[ATTR2]] { +// NO-SANITIZE-WITH-ATTR-NEXT: entry: +// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[I]] to i64 +// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_TEST27_FOO:%.*]], ptr [[P]], i64 0, i32 4, i64 [[IDXPROM]] +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[ARRAYIDX]], align 8, !tbaa [[TBAA11]] +// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM1:%.*]] = sext i32 [[J]] to i64 +// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds [[STRUCT_TEST27_BAR:%.*]], ptr [[TMP0]], i64 [[IDXPROM1]] +// NO-SANITIZE-WITH-ATTR-NEXT: ret ptr [[ARRAYIDX2]] +// +// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local ptr @test27( +// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[I:%.*]], i32 noundef [[J:%.*]]) local_unnamed_addr #[[ATTR0]] { +// SANITIZE-WITHOUT-ATTR-NEXT: entry: +// SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[I]] to i64 +// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_TEST27_FOO:%.*]], ptr [[P]], i64 0, i32 4, i64 [[IDXPROM]] +// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[ARRAYIDX]], align 8, !tbaa [[TBAA14]] +// SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM3:%.*]] = sext i32 [[J]] to i64 +// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX4:%.*]] = getelementptr inbounds [[STRUCT_TEST27_BAR:%.*]], ptr [[TMP0]], i64 [[IDXPROM3]] +// SANITIZE-WITHOUT-ATTR-NEXT: ret ptr [[ARRAYIDX4]] +// +// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local ptr @test27( +// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nocapture noundef readonly [[P:%.*]], i32 noundef [[I:%.*]], i32 noundef [[J:%.*]]) local_unnamed_addr #[[ATTR6]] { +// NO-SANITIZE-WITHOUT-ATTR-NEXT: entry: +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[I]] to i64 +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_TEST27_FOO:%.*]], ptr [[P]], i64 0, i32 4, i64 [[IDXPROM]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[ARRAYIDX]], align 8, !tbaa [[TBAA11]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM1:%.*]] = sext i32 [[J]] to i64 +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds [[STRUCT_TEST27_BAR:%.*]], ptr [[TMP0]], i64 [[IDXPROM1]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret ptr [[ARRAYIDX2]] +// +struct test27_bar *test27(struct test27_foo *p, int i, int j) { + return &p->entries[i][j]; +} + +struct test28_foo { + struct test28_foo *s; + int count; + int arr[] __counted_by(count); +}; + +// SANITIZE-WITH-ATTR-LABEL: define dso_local i32 @test28( +// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[I:%.*]]) local_unnamed_addr #[[ATTR0]] { +// SANITIZE-WITH-ATTR-NEXT: entry: +// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P]], align 8, !tbaa [[TBAA14]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = load ptr, ptr [[TMP0]], align 8, !tbaa [[TBAA14]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = load ptr, ptr [[TMP1]], align 8, !tbaa [[TBAA14]] +// SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[I]] to i64 +// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_GEP:%.*]] = getelementptr inbounds [[STRUCT_TEST28_FOO:%.*]], ptr [[TMP2]], i64 0, i32 1 +// SANITIZE-WITH-ATTR-NEXT: [[DOTCOUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOTCOUNTED_BY_GEP]], align 4 +// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = zext i32 [[DOTCOUNTED_BY_LOAD]] to i64, !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = icmp ult i64 [[IDXPROM]], [[TMP3]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP4]], label [[CONT17:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF3]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR: handler.out_of_bounds: +// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB31:[0-9]+]], i64 [[IDXPROM]]) #[[ATTR10]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META2]] +// SANITIZE-WITH-ATTR: cont17: +// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_TEST28_FOO]], ptr [[TMP2]], i64 0, i32 2, i64 [[IDXPROM]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = load i32, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA4]] +// SANITIZE-WITH-ATTR-NEXT: ret i32 [[TMP5]] +// +// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local i32 @test28( +// NO-SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef readonly [[P:%.*]], i32 noundef [[I:%.*]]) local_unnamed_addr #[[ATTR9]] { +// NO-SANITIZE-WITH-ATTR-NEXT: entry: +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P]], align 8, !tbaa [[TBAA11]] +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = load ptr, ptr [[TMP0]], align 8, !tbaa [[TBAA11]] +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = load ptr, ptr [[TMP1]], align 8, !tbaa [[TBAA11]] +// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[I]] to i64 +// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_TEST28_FOO:%.*]], ptr [[TMP2]], i64 0, i32 2, i64 [[IDXPROM]] +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = load i32, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] +// NO-SANITIZE-WITH-ATTR-NEXT: ret i32 [[TMP3]] +// +// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i32 @test28( +// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[I:%.*]]) local_unnamed_addr #[[ATTR0]] { +// SANITIZE-WITHOUT-ATTR-NEXT: entry: +// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P]], align 8, !tbaa [[TBAA14]] +// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP1:%.*]] = load ptr, ptr [[TMP0]], align 8, !tbaa [[TBAA14]] +// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP2:%.*]] = load ptr, ptr [[TMP1]], align 8, !tbaa [[TBAA14]] +// SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[I]] to i64 +// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_TEST28_FOO:%.*]], ptr [[TMP2]], i64 0, i32 2, i64 [[IDXPROM]] +// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP3:%.*]] = load i32, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] +// SANITIZE-WITHOUT-ATTR-NEXT: ret i32 [[TMP3]] +// +// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i32 @test28( +// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nocapture noundef readonly [[P:%.*]], i32 noundef [[I:%.*]]) local_unnamed_addr #[[ATTR7]] { +// NO-SANITIZE-WITHOUT-ATTR-NEXT: entry: +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P]], align 8, !tbaa [[TBAA11]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP1:%.*]] = load ptr, ptr [[TMP0]], align 8, !tbaa [[TBAA11]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP2:%.*]] = load ptr, ptr [[TMP1]], align 8, !tbaa [[TBAA11]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[I]] to i64 +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_TEST28_FOO:%.*]], ptr [[TMP2]], i64 0, i32 2, i64 [[IDXPROM]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP3:%.*]] = load i32, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret i32 [[TMP3]] +// +int test28(struct test28_foo *p, int i) { + return p->s->s->s->arr[i]; +} + +struct annotated_struct_array { + struct annotated *ann_array[10]; + unsigned long flags; + int count; + int array[] __counted_by(count); +}; + +// SANITIZE-WITH-ATTR-LABEL: define dso_local void @test29( +// SANITIZE-WITH-ATTR-SAME: ptr noundef [[ANN:%.*]], i32 noundef [[IDX1:%.*]], i32 noundef [[IDX2:%.*]]) local_unnamed_addr #[[ATTR0]] { +// SANITIZE-WITH-ATTR-NEXT: entry: +// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = icmp ult i32 [[IDX1]], 10 +// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = zext i32 [[IDX1]] to i64 +// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP0]], label [[CONT3:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF3]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR: handler.out_of_bounds: +// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB33:[0-9]+]], i64 [[TMP1]]) #[[ATTR10]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META2]] +// SANITIZE-WITH-ATTR: cont3: +// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [10 x ptr], ptr [[ANN]], i64 0, i64 [[TMP1]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = load ptr, ptr [[ARRAYIDX]], align 8, !tbaa [[TBAA14]] +// SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED:%.*]], ptr [[TMP2]], i64 0, i32 1 +// SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOT_COUNTED_BY_GEP]], align 4 +// SANITIZE-WITH-ATTR-NEXT: [[IDXPROM15:%.*]] = sext i32 [[IDX2]] to i64 +// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = zext i32 [[DOT_COUNTED_BY_LOAD]] to i64, !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = icmp ult i64 [[IDXPROM15]], [[TMP3]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP4]], label [[CONT20:%.*]], label [[HANDLER_OUT_OF_BOUNDS16:%.*]], !prof [[PROF3]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR: handler.out_of_bounds16: +// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB34:[0-9]+]], i64 [[IDXPROM15]]) #[[ATTR10]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META2]] +// SANITIZE-WITH-ATTR: cont20: +// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX18:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED]], ptr [[TMP2]], i64 0, i32 2, i64 [[IDXPROM15]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = shl i32 [[DOT_COUNTED_BY_LOAD]], 2 +// SANITIZE-WITH-ATTR-NEXT: [[DOTINV:%.*]] = icmp slt i32 [[DOT_COUNTED_BY_LOAD]], 0 +// SANITIZE-WITH-ATTR-NEXT: [[CONV:%.*]] = select i1 [[DOTINV]], i32 0, i32 [[TMP5]] +// SANITIZE-WITH-ATTR-NEXT: store i32 [[CONV]], ptr [[ARRAYIDX18]], align 4, !tbaa [[TBAA4]] +// SANITIZE-WITH-ATTR-NEXT: ret void +// +// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local void @test29( +// NO-SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef readonly [[ANN:%.*]], i32 noundef [[IDX1:%.*]], i32 noundef [[IDX2:%.*]]) local_unnamed_addr #[[ATTR10:[0-9]+]] { +// NO-SANITIZE-WITH-ATTR-NEXT: entry: +// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[IDX1]] to i64 +// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [10 x ptr], ptr [[ANN]], i64 0, i64 [[IDXPROM]] +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[ARRAYIDX]], align 8, !tbaa [[TBAA11]] +// NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED:%.*]], ptr [[TMP0]], i64 0, i32 1 +// NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOT_COUNTED_BY_GEP]], align 4 +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = shl i32 [[DOT_COUNTED_BY_LOAD]], 2 +// NO-SANITIZE-WITH-ATTR-NEXT: [[DOTINV:%.*]] = icmp slt i32 [[DOT_COUNTED_BY_LOAD]], 0 +// NO-SANITIZE-WITH-ATTR-NEXT: [[CONV:%.*]] = select i1 [[DOTINV]], i32 0, i32 [[TMP1]] +// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM4:%.*]] = sext i32 [[IDX2]] to i64 +// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX5:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED]], ptr [[TMP0]], i64 0, i32 2, i64 [[IDXPROM4]] +// NO-SANITIZE-WITH-ATTR-NEXT: store i32 [[CONV]], ptr [[ARRAYIDX5]], align 4, !tbaa [[TBAA2]] +// NO-SANITIZE-WITH-ATTR-NEXT: ret void +// +// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test29( +// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[ANN:%.*]], i32 noundef [[IDX1:%.*]], i32 noundef [[IDX2:%.*]]) local_unnamed_addr #[[ATTR0]] { +// SANITIZE-WITHOUT-ATTR-NEXT: entry: +// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = icmp ult i32 [[IDX1]], 10 +// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP1:%.*]] = zext i32 [[IDX1]] to i64 +// SANITIZE-WITHOUT-ATTR-NEXT: br i1 [[TMP0]], label [[CONT21:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF8]], !nosanitize [[META9]] +// SANITIZE-WITHOUT-ATTR: handler.out_of_bounds: +// SANITIZE-WITHOUT-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB12:[0-9]+]], i64 [[TMP1]]) #[[ATTR8]], !nosanitize [[META9]] +// SANITIZE-WITHOUT-ATTR-NEXT: unreachable, !nosanitize [[META9]] +// SANITIZE-WITHOUT-ATTR: cont21: +// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [10 x ptr], ptr [[ANN]], i64 0, i64 [[TMP1]] +// SANITIZE-WITHOUT-ATTR-NEXT: [[TMP2:%.*]] = load ptr, ptr [[ARRAYIDX]], align 8, !tbaa [[TBAA14]] +// SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM18:%.*]] = sext i32 [[IDX2]] to i64 +// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX19:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED:%.*]], ptr [[TMP2]], i64 0, i32 2, i64 [[IDXPROM18]] +// SANITIZE-WITHOUT-ATTR-NEXT: store i32 -1, ptr [[ARRAYIDX19]], align 4, !tbaa [[TBAA2]] +// SANITIZE-WITHOUT-ATTR-NEXT: ret void +// +// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test29( +// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nocapture noundef readonly [[ANN:%.*]], i32 noundef [[IDX1:%.*]], i32 noundef [[IDX2:%.*]]) local_unnamed_addr #[[ATTR8:[0-9]+]] { +// NO-SANITIZE-WITHOUT-ATTR-NEXT: entry: +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[IDX1]] to i64 +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [10 x ptr], ptr [[ANN]], i64 0, i64 [[IDXPROM]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load ptr, ptr [[ARRAYIDX]], align 8, !tbaa [[TBAA11]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM5:%.*]] = sext i32 [[IDX2]] to i64 +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX6:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED:%.*]], ptr [[TMP0]], i64 0, i32 2, i64 [[IDXPROM5]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: store i32 -1, ptr [[ARRAYIDX6]], align 4, !tbaa [[TBAA2]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret void +// +void test29(struct annotated_struct_array *ann, int idx1, int idx2) { + ann->ann_array[idx1]->array[idx2] = __builtin_dynamic_object_size(ann->ann_array[idx1]->array, 1); +} diff --git a/clang/test/CodeGen/attr-noundef.cpp b/clang/test/CodeGen/attr-noundef.cpp index a2aa7e313f0e8064795c9830a410609d50e6b928..d236b35fdfd7daf3c37c823c18a384ef48c89bb7 100644 --- a/clang/test/CodeGen/attr-noundef.cpp +++ b/clang/test/CodeGen/attr-noundef.cpp @@ -26,7 +26,7 @@ struct NoCopy { }; NoCopy ret_nocopy() { return {}; } void pass_nocopy(NoCopy e) {} -// CHECK: [[DEF]] void @{{.*}}ret_nocopy{{.*}}(ptr noalias sret({{[^)]+}}) align 4 % +// CHECK: [[DEF]] void @{{.*}}ret_nocopy{{.*}}(ptr dead_on_unwind noalias writable sret({{[^)]+}}) align 4 % // CHECK: [[DEF]] void @{{.*}}pass_nocopy{{.*}}(ptr noundef % struct Huge { @@ -34,7 +34,7 @@ struct Huge { }; Huge ret_huge() { return {}; } void pass_huge(Huge h) {} -// CHECK: [[DEF]] void @{{.*}}ret_huge{{.*}}(ptr noalias sret({{[^)]+}}) align 4 % +// CHECK: [[DEF]] void @{{.*}}ret_huge{{.*}}(ptr dead_on_unwind noalias writable sret({{[^)]+}}) align 4 % // CHECK: [[DEF]] void @{{.*}}pass_huge{{.*}}(ptr noundef } // namespace check_structs @@ -58,7 +58,7 @@ union NoCopy { }; NoCopy ret_nocopy() { return {}; } void pass_nocopy(NoCopy e) {} -// CHECK: [[DEF]] void @{{.*}}ret_nocopy{{.*}}(ptr noalias sret({{[^)]+}}) align 4 % +// CHECK: [[DEF]] void @{{.*}}ret_nocopy{{.*}}(ptr dead_on_unwind noalias writable sret({{[^)]+}}) align 4 % // CHECK: [[DEF]] void @{{.*}}pass_nocopy{{.*}}(ptr noundef % } // namespace check_unions diff --git a/clang/test/CodeGen/blocks.c b/clang/test/CodeGen/blocks.c index 469cf7cb89a2c389a24b387cca3b59fabc5ce14c..8f947fcdfccb213dff1abc34c12d6bc40d0cc4bb 100644 --- a/clang/test/CodeGen/blocks.c +++ b/clang/test/CodeGen/blocks.c @@ -15,7 +15,7 @@ struct s0 { int a[64]; }; -// CHECK: define internal void @__f2_block_invoke(ptr noalias sret(%struct.s0) align 4 {{%.*}}, ptr noundef {{%.*}}, ptr noundef byval(%struct.s0) align 4 {{.*}}) +// CHECK: define internal void @__f2_block_invoke(ptr dead_on_unwind noalias writable sret(%struct.s0) align 4 {{%.*}}, ptr noundef {{%.*}}, ptr noundef byval(%struct.s0) align 4 {{.*}}) struct s0 f2(struct s0 a0) { return ^(struct s0 a1){ return a1; }(a0); } diff --git a/clang/test/CodeGen/bounds-checking.c b/clang/test/CodeGen/bounds-checking.c index 636d4f289e247863f1f312c57e03792f1d99f616..8100e30d0650adca140e08d8a262b45a32793128 100644 --- a/clang/test/CodeGen/bounds-checking.c +++ b/clang/test/CodeGen/bounds-checking.c @@ -69,7 +69,6 @@ int f7(union U *u, int i) { return u->c[i]; } - char B[10]; char B2[10]; // CHECK-LABEL: @f8 @@ -82,3 +81,12 @@ void f8(int i, int k) { // NOOPTARRAY: call void @llvm.ubsantrap(i8 4) B2[k] = '\0'; } + +// See commit 9a954c6 that caused a SEGFAULT in this code. +struct S { + __builtin_va_list ap; +} *s; +// CHECK-LABEL: @f9 +struct S *f9(int i) { + return &s[i]; +} diff --git a/clang/test/CodeGen/c11atomics-ios.c b/clang/test/CodeGen/c11atomics-ios.c index af489811edc58f8819b531e95f6683612a88a33b..bcb6519ab0dc818a622f710aa1ab8f213051d353 100644 --- a/clang/test/CodeGen/c11atomics-ios.c +++ b/clang/test/CodeGen/c11atomics-ios.c @@ -178,7 +178,7 @@ void testPromotedStruct(_Atomic(PS) *fp) { } PS test_promoted_load(_Atomic(PS) *addr) { - // CHECK-LABEL: @test_promoted_load(ptr noalias sret(%struct.PS) align 2 %agg.result, ptr noundef %addr) + // CHECK-LABEL: @test_promoted_load(ptr dead_on_unwind noalias writable sret(%struct.PS) align 2 %agg.result, ptr noundef %addr) // CHECK: [[ADDR_ARG:%.*]] = alloca ptr, align 4 // CHECK: [[ATOMIC_RES:%.*]] = alloca { %struct.PS, [2 x i8] }, align 8 // CHECK: store ptr %addr, ptr [[ADDR_ARG]], align 4 @@ -209,7 +209,7 @@ void test_promoted_store(_Atomic(PS) *addr, PS *val) { } PS test_promoted_exchange(_Atomic(PS) *addr, PS *val) { - // CHECK-LABEL: @test_promoted_exchange(ptr noalias sret(%struct.PS) align 2 %agg.result, ptr noundef %addr, ptr noundef %val) + // CHECK-LABEL: @test_promoted_exchange(ptr dead_on_unwind noalias writable sret(%struct.PS) align 2 %agg.result, ptr noundef %addr, ptr noundef %val) // CHECK: [[ADDR_ARG:%.*]] = alloca ptr, align 4 // CHECK: [[VAL_ARG:%.*]] = alloca ptr, align 4 // CHECK: [[NONATOMIC_TMP:%.*]] = alloca %struct.PS, align 2 diff --git a/clang/test/CodeGen/c11atomics.c b/clang/test/CodeGen/c11atomics.c index 773ed41991f78373fe41c4109e8361327ba30375..dd1f52f70ae09fd2c39a974390ab3e331363793d 100644 --- a/clang/test/CodeGen/c11atomics.c +++ b/clang/test/CodeGen/c11atomics.c @@ -338,7 +338,7 @@ void testPromotedStruct(_Atomic(PS) *fp) { } PS test_promoted_load(_Atomic(PS) *addr) { - // CHECK-LABEL: @test_promoted_load(ptr noalias sret(%struct.PS) align 2 %agg.result, ptr noundef %addr) + // CHECK-LABEL: @test_promoted_load(ptr dead_on_unwind noalias writable sret(%struct.PS) align 2 %agg.result, ptr noundef %addr) // CHECK: [[ADDR_ARG:%.*]] = alloca ptr, align 4 // CHECK: [[ATOMIC_RES:%.*]] = alloca { %struct.PS, [2 x i8] }, align 8 // CHECK: store ptr %addr, ptr [[ADDR_ARG]], align 4 @@ -368,7 +368,7 @@ void test_promoted_store(_Atomic(PS) *addr, PS *val) { } PS test_promoted_exchange(_Atomic(PS) *addr, PS *val) { - // CHECK-LABEL: @test_promoted_exchange(ptr noalias sret(%struct.PS) align 2 %agg.result, ptr noundef %addr, ptr noundef %val) + // CHECK-LABEL: @test_promoted_exchange(ptr dead_on_unwind noalias writable sret(%struct.PS) align 2 %agg.result, ptr noundef %addr, ptr noundef %val) // CHECK: [[ADDR_ARG:%.*]] = alloca ptr, align 4 // CHECK: [[VAL_ARG:%.*]] = alloca ptr, align 4 // CHECK: [[NONATOMIC_TMP:%.*]] = alloca %struct.PS, align 2 diff --git a/clang/test/CodeGen/debug-info-codeview-unnamed.c b/clang/test/CodeGen/debug-info-codeview-unnamed.c index bd2a7543e56b2ba10986826c0596dfc5fae0d33d..16ffb3682236f1856380ab63a05d53387f63f920 100644 --- a/clang/test/CodeGen/debug-info-codeview-unnamed.c +++ b/clang/test/CodeGen/debug-info-codeview-unnamed.c @@ -8,23 +8,23 @@ int main(int argc, char* argv[], char* arge[]) { // struct { int bar; } one = {42}; // - // LINUX: !{{[0-9]+}} = !DILocalVariable(name: "one" - // LINUX-SAME: type: [[TYPE_OF_ONE:![0-9]+]] - // LINUX-SAME: ) - // LINUX: [[TYPE_OF_ONE]] = distinct !DICompositeType( + // LINUX: [[TYPE_OF_ONE:![0-9]+]] = distinct !DICompositeType( // LINUX-SAME: tag: DW_TAG_structure_type // LINUX-NOT: name: // LINUX-NOT: identifier: // LINUX-SAME: ) + // LINUX: !{{[0-9]+}} = !DILocalVariable(name: "one" + // LINUX-SAME: type: [[TYPE_OF_ONE]] + // LINUX-SAME: ) // - // MSVC: !{{[0-9]+}} = !DILocalVariable(name: "one" - // MSVC-SAME: type: [[TYPE_OF_ONE:![0-9]+]] - // MSVC-SAME: ) - // MSVC: [[TYPE_OF_ONE]] = distinct !DICompositeType + // MSVC: [[TYPE_OF_ONE:![0-9]+]] = distinct !DICompositeType // MSVC-SAME: tag: DW_TAG_structure_type // MSVC-NOT: name: // MSVC-NOT: identifier: // MSVC-SAME: ) + // MSVC: !{{[0-9]+}} = !DILocalVariable(name: "one" + // MSVC-SAME: type: [[TYPE_OF_ONE]] + // MSVC-SAME: ) return 0; } diff --git a/clang/test/CodeGen/debug-info-unused-types.c b/clang/test/CodeGen/debug-info-unused-types.c index 3e9f7b07658e36e224b43cf4d03c679822d99f84..31d608d92a06b4150a5f806e8b47f19df89f00a8 100644 --- a/clang/test/CodeGen/debug-info-unused-types.c +++ b/clang/test/CodeGen/debug-info-unused-types.c @@ -18,13 +18,15 @@ void quux(void) { // CHECK: !DICompileUnit{{.+}}retainedTypes: [[RETTYPES:![0-9]+]] // CHECK: [[TYPE0:![0-9]+]] = !DICompositeType(tag: DW_TAG_enumeration_type, name: "bar" // CHECK: [[TYPE1:![0-9]+]] = !DIEnumerator(name: "BAR" -// CHECK: [[TYPE2:![0-9]+]] = !DICompositeType(tag: DW_TAG_enumeration_type, name: "z" -// CHECK: [[TYPE3:![0-9]+]] = !DIEnumerator(name: "Z" -// CHECK: [[RETTYPES]] = !{[[TYPE4:![0-9]+]], [[TYPE5:![0-9]+]], [[TYPE0]], [[TYPE6:![0-9]+]], {{![0-9]+}}, [[TYPE7:![0-9]+]], [[TYPE2]], [[TYPE8:![0-9]+]]} -// CHECK: [[TYPE4]] = !DIDerivedType(tag: DW_TAG_typedef, name: "my_int" -// CHECK: [[TYPE5]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "foo" -// CHECK: [[TYPE6]] = distinct !DICompositeType(tag: DW_TAG_union_type, name: "baz" -// CHECK: [[TYPE7]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "y" +// CHECK: [[RETTYPES]] = !{[[TYPE2:![0-9]+]], [[TYPE3:![0-9]+]], [[TYPE0]], [[TYPE4:![0-9]+]], {{![0-9]+}}} +// CHECK: [[TYPE2]] = !DIDerivedType(tag: DW_TAG_typedef, name: "my_int" +// CHECK: [[TYPE3]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "foo" +// CHECK: [[TYPE4]] = distinct !DICompositeType(tag: DW_TAG_union_type, name: "baz" +// CHECK: [[SP:![0-9]+]] = distinct !DISubprogram(name: "quux", {{.*}}, retainedNodes: [[SPRETNODES:![0-9]+]] +// CHECK: [[SPRETNODES]] = !{[[TYPE5:![0-9]+]], [[TYPE6:![0-9]+]], [[TYPE8:![0-9]+]]} +// CHECK: [[TYPE5]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "y" +// CHECK: [[TYPE6]] = !DICompositeType(tag: DW_TAG_enumeration_type, name: "z" +// CHECK: [[TYPE7:![0-9]+]] = !DIEnumerator(name: "Z" // CHECK: [[TYPE8]] = distinct !DICompositeType(tag: DW_TAG_union_type, name: "w" // Check that debug info is not emitted for the typedef, struct, enum, and diff --git a/clang/test/CodeGen/debug-info-unused-types.cpp b/clang/test/CodeGen/debug-info-unused-types.cpp index 023cac159faa4b4105e0bd94986bbafe8a0a1af0..5b01c6dbb394149654c30dfb0dc2caeacc5fcc50 100644 --- a/clang/test/CodeGen/debug-info-unused-types.cpp +++ b/clang/test/CodeGen/debug-info-unused-types.cpp @@ -13,12 +13,14 @@ void quux() { // CHECK: !DICompileUnit{{.+}}retainedTypes: [[RETTYPES:![0-9]+]] // CHECK: [[TYPE0:![0-9]+]] = !DICompositeType(tag: DW_TAG_enumeration_type, name: "baz" // CHECK: [[TYPE1:![0-9]+]] = !DIEnumerator(name: "BAZ" -// CHECK: [[TYPE2:![0-9]+]] = !DICompositeType(tag: DW_TAG_enumeration_type, name: "z" -// CHECK: [[TYPE3:![0-9]+]] = !DIEnumerator(name: "Z" -// CHECK: [[RETTYPES]] = !{[[TYPE4:![0-9]+]], [[TYPE5:![0-9]+]], [[TYPE0]], {{![0-9]+}}, [[TYPE6:![0-9]+]], [[TYPE2]]} -// CHECK: [[TYPE4]] = !DIDerivedType(tag: DW_TAG_typedef, name: "foo" -// CHECK: [[TYPE5]] = distinct !DICompositeType(tag: DW_TAG_class_type, name: "bar" -// CHECK: [[TYPE6]] = distinct !DICompositeType(tag: DW_TAG_class_type, name: "y" +// CHECK: [[RETTYPES]] = !{[[TYPE2:![0-9]+]], [[TYPE3:![0-9]+]], [[TYPE0]], {{![0-9]+}}} +// CHECK: [[TYPE2]] = !DIDerivedType(tag: DW_TAG_typedef, name: "foo" +// CHECK: [[TYPE3]] = distinct !DICompositeType(tag: DW_TAG_class_type, name: "bar" +// CHECK: [[SP:![0-9]+]] = distinct !DISubprogram(name: "quux", {{.*}}, retainedNodes: [[SPRETNODES:![0-9]+]] +// CHECK: [[SPRETNODES]] = !{[[TYPE4:![0-9]+]], [[TYPE5:![0-9]+]]} +// CHECK: [[TYPE4]] = distinct !DICompositeType(tag: DW_TAG_class_type, name: "y", scope: [[SP]] +// CHECK: [[TYPE5]] = !DICompositeType(tag: DW_TAG_enumeration_type, name: "z", scope: [[SP]] +// CHECK: [[TYPE6:![0-9]+]] = !DIEnumerator(name: "Z" // NODBG-NOT: !DI{{CompositeType|Enumerator|DerivedType}} diff --git a/clang/test/CodeGen/debug-names-compound-type-units.ll b/clang/test/CodeGen/debug-names-compound-type-units.ll new file mode 100644 index 0000000000000000000000000000000000000000..62cecfdeaf7f94bf58532158ec0703dd7ca5df8a --- /dev/null +++ b/clang/test/CodeGen/debug-names-compound-type-units.ll @@ -0,0 +1,74 @@ +; REQUIRES: asserts +; REQUIRES: x86-registered-target + +;; Tests that we use correct accelerator table when processing nested TUs. +;; Assert is not triggered. +;; File1 +;; struct Foo { +;; char f; +;; }; +;; struct Foo2 { +;; char f; +;; Foo f1; +;; }; +;; void fooFunc() { +;; Foo2 global2; +;; } +;; clang++ .cpp -O0 -g2 -fdebug-types-section -gpubnames -S -emit-llvm -o .ll + +; RUN: llc -O0 -dwarf-version=5 -generate-type-units -filetype=obj < %s -o %t.o +; RUN: llvm-readelf --sections %t.o | FileCheck --check-prefix=OBJ %s + +; OBJ: debug_names + +; ModuleID = 'main.cpp' +source_filename = "main.cpp" +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +%struct.Foo2 = type { i8, %struct.Foo } +%struct.Foo = type { i8 } + +; Function Attrs: mustprogress noinline nounwind optnone uwtable +define dso_local void @_Z7fooFuncv() #0 !dbg !10 { +entry: + %global2 = alloca %struct.Foo2, align 1 + call void @llvm.dbg.declare(metadata ptr %global2, metadata !14, metadata !DIExpression()), !dbg !23 + ret void, !dbg !24 +} + +; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none) +declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 + +attributes #0 = { mustprogress noinline nounwind optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +attributes #1 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!2, !3, !4, !5, !6, !7, !8} +!llvm.ident = !{!9} + +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 18.0.0git", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false) +!1 = !DIFile(filename: "main.cpp", directory: "/smallMultipleTUs", checksumkind: CSK_MD5, checksum: "70bff4d50322126f3d8ca4178afad376") +!2 = !{i32 7, !"Dwarf Version", i32 5} +!3 = !{i32 2, !"Debug Info Version", i32 3} +!4 = !{i32 1, !"wchar_size", i32 4} +!5 = !{i32 8, !"PIC Level", i32 2} +!6 = !{i32 7, !"PIE Level", i32 2} +!7 = !{i32 7, !"uwtable", i32 2} +!8 = !{i32 7, !"frame-pointer", i32 2} +!9 = !{!"clang version 18.0.0git"} +!10 = distinct !DISubprogram(name: "fooFunc", linkageName: "_Z7fooFuncv", scope: !1, file: !1, line: 9, type: !11, scopeLine: 9, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !13) +!11 = !DISubroutineType(types: !12) +!12 = !{null} +!13 = !{} +!14 = !DILocalVariable(name: "global2", scope: !10, file: !1, line: 10, type: !15) +!15 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Foo2", file: !1, line: 4, size: 16, flags: DIFlagTypePassByValue, elements: !16, identifier: "_ZTS4Foo2") +!16 = !{!17, !19} +!17 = !DIDerivedType(tag: DW_TAG_member, name: "f", scope: !15, file: !1, line: 5, baseType: !18, size: 8) +!18 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char) +!19 = !DIDerivedType(tag: DW_TAG_member, name: "f1", scope: !15, file: !1, line: 6, baseType: !20, size: 8, offset: 8) +!20 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Foo", file: !1, line: 1, size: 8, flags: DIFlagTypePassByValue, elements: !21, identifier: "_ZTS3Foo") +!21 = !{!22} +!22 = !DIDerivedType(tag: DW_TAG_member, name: "f", scope: !20, file: !1, line: 2, baseType: !18, size: 8) +!23 = !DILocation(line: 10, column: 6, scope: !10) +!24 = !DILocation(line: 11, column: 1, scope: !10) diff --git a/clang/test/CodeGen/ext-int-cc.c b/clang/test/CodeGen/ext-int-cc.c index bcf29fc1309deb7dc6febc51b2e6d69623f7f00a..001e866d34b45eeb54f636bda42ee86e39f46929 100644 --- a/clang/test/CodeGen/ext-int-cc.c +++ b/clang/test/CodeGen/ext-int-cc.c @@ -226,104 +226,104 @@ _BitInt(64) ReturnPassing2(void){} _BitInt(127) ReturnPassing3(void){} // LIN64: define{{.*}} { i64, i64 } @ReturnPassing3( -// WIN64: define dso_local void @ReturnPassing3(ptr noalias sret -// LIN32: define{{.*}} void @ReturnPassing3(ptr noalias sret -// WIN32: define dso_local void @ReturnPassing3(ptr noalias sret -// NACL: define{{.*}} void @ReturnPassing3(ptr noalias sret +// WIN64: define dso_local void @ReturnPassing3(ptr dead_on_unwind noalias writable sret +// LIN32: define{{.*}} void @ReturnPassing3(ptr dead_on_unwind noalias writable sret +// WIN32: define dso_local void @ReturnPassing3(ptr dead_on_unwind noalias writable sret +// NACL: define{{.*}} void @ReturnPassing3(ptr dead_on_unwind noalias writable sret // NVPTX/64 makes the intentional choice to put all return values direct, even // large structures, so we do the same here. // NVPTX64: define{{.*}} i127 @ReturnPassing3( // NVPTX: define{{.*}} i127 @ReturnPassing3( // SPARCV9: define{{.*}} i127 @ReturnPassing3( -// SPARC: define{{.*}} void @ReturnPassing3(ptr noalias sret +// SPARC: define{{.*}} void @ReturnPassing3(ptr dead_on_unwind noalias writable sret // MIPS64: define{{.*}} i127 @ReturnPassing3( -// MIPS: define{{.*}} void @ReturnPassing3(ptr noalias sret -// SPIR64: define{{.*}} spir_func void @ReturnPassing3(ptr noalias sret -// SPIR: define{{.*}} spir_func void @ReturnPassing3(ptr noalias sret -// HEX: define{{.*}} void @ReturnPassing3(ptr noalias sret -// LANAI: define{{.*}} void @ReturnPassing3(ptr noalias sret -// R600: define{{.*}} void @ReturnPassing3(ptr addrspace(5) noalias sret -// ARC: define{{.*}} void @ReturnPassing3(ptr noalias sret -// XCORE: define{{.*}} void @ReturnPassing3(ptr noalias sret +// MIPS: define{{.*}} void @ReturnPassing3(ptr dead_on_unwind noalias writable sret +// SPIR64: define{{.*}} spir_func void @ReturnPassing3(ptr dead_on_unwind noalias writable sret +// SPIR: define{{.*}} spir_func void @ReturnPassing3(ptr dead_on_unwind noalias writable sret +// HEX: define{{.*}} void @ReturnPassing3(ptr dead_on_unwind noalias writable sret +// LANAI: define{{.*}} void @ReturnPassing3(ptr dead_on_unwind noalias writable sret +// R600: define{{.*}} void @ReturnPassing3(ptr addrspace(5) dead_on_unwind noalias writable sret +// ARC: define{{.*}} void @ReturnPassing3(ptr dead_on_unwind noalias writable sret +// XCORE: define{{.*}} void @ReturnPassing3(ptr dead_on_unwind noalias writable sret // RISCV64: define{{.*}} i127 @ReturnPassing3( -// RISCV32: define{{.*}} void @ReturnPassing3(ptr noalias sret +// RISCV32: define{{.*}} void @ReturnPassing3(ptr dead_on_unwind noalias writable sret // WASM: define{{.*}} i127 @ReturnPassing3( -// SYSTEMZ: define{{.*}} void @ReturnPassing3(ptr noalias sret +// SYSTEMZ: define{{.*}} void @ReturnPassing3(ptr dead_on_unwind noalias writable sret // PPC64: define{{.*}} i127 @ReturnPassing3( -// PPC32: define{{.*}} void @ReturnPassing3(ptr noalias sret +// PPC32: define{{.*}} void @ReturnPassing3(ptr dead_on_unwind noalias writable sret // AARCH64: define{{.*}} i127 @ReturnPassing3( // AARCH64DARWIN: define{{.*}} i127 @ReturnPassing3( -// ARM: define{{.*}} arm_aapcscc void @ReturnPassing3(ptr noalias sret +// ARM: define{{.*}} arm_aapcscc void @ReturnPassing3(ptr dead_on_unwind noalias writable sret // LA64: define{{.*}} i127 @ReturnPassing3( -// LA32: define{{.*}} void @ReturnPassing3(ptr noalias sret +// LA32: define{{.*}} void @ReturnPassing3(ptr dead_on_unwind noalias writable sret _BitInt(128) ReturnPassing4(void){} // LIN64: define{{.*}} { i64, i64 } @ReturnPassing4( -// WIN64: define dso_local void @ReturnPassing4(ptr noalias sret -// LIN32: define{{.*}} void @ReturnPassing4(ptr noalias sret -// WIN32: define dso_local void @ReturnPassing4(ptr noalias sret -// NACL: define{{.*}} void @ReturnPassing4(ptr noalias sret +// WIN64: define dso_local void @ReturnPassing4(ptr dead_on_unwind noalias writable sret +// LIN32: define{{.*}} void @ReturnPassing4(ptr dead_on_unwind noalias writable sret +// WIN32: define dso_local void @ReturnPassing4(ptr dead_on_unwind noalias writable sret +// NACL: define{{.*}} void @ReturnPassing4(ptr dead_on_unwind noalias writable sret // NVPTX64: define{{.*}} i128 @ReturnPassing4( // NVPTX: define{{.*}} i128 @ReturnPassing4( // SPARCV9: define{{.*}} i128 @ReturnPassing4( -// SPARC: define{{.*}} void @ReturnPassing4(ptr noalias sret +// SPARC: define{{.*}} void @ReturnPassing4(ptr dead_on_unwind noalias writable sret // MIPS64: define{{.*}} i128 @ReturnPassing4( -// MIPS: define{{.*}} void @ReturnPassing4(ptr noalias sret -// SPIR64: define{{.*}} spir_func void @ReturnPassing4(ptr noalias sret -// SPIR: define{{.*}} spir_func void @ReturnPassing4(ptr noalias sret -// HEX: define{{.*}} void @ReturnPassing4(ptr noalias sret -// LANAI: define{{.*}} void @ReturnPassing4(ptr noalias sret -// R600: define{{.*}} void @ReturnPassing4(ptr addrspace(5) noalias sret -// ARC: define{{.*}} void @ReturnPassing4(ptr noalias sret -// XCORE: define{{.*}} void @ReturnPassing4(ptr noalias sret +// MIPS: define{{.*}} void @ReturnPassing4(ptr dead_on_unwind noalias writable sret +// SPIR64: define{{.*}} spir_func void @ReturnPassing4(ptr dead_on_unwind noalias writable sret +// SPIR: define{{.*}} spir_func void @ReturnPassing4(ptr dead_on_unwind noalias writable sret +// HEX: define{{.*}} void @ReturnPassing4(ptr dead_on_unwind noalias writable sret +// LANAI: define{{.*}} void @ReturnPassing4(ptr dead_on_unwind noalias writable sret +// R600: define{{.*}} void @ReturnPassing4(ptr addrspace(5) dead_on_unwind noalias writable sret +// ARC: define{{.*}} void @ReturnPassing4(ptr dead_on_unwind noalias writable sret +// XCORE: define{{.*}} void @ReturnPassing4(ptr dead_on_unwind noalias writable sret // RISCV64: define{{.*}} i128 @ReturnPassing4( -// RISCV32: define{{.*}} void @ReturnPassing4(ptr noalias sret +// RISCV32: define{{.*}} void @ReturnPassing4(ptr dead_on_unwind noalias writable sret // WASM: define{{.*}} i128 @ReturnPassing4( -// SYSTEMZ: define{{.*}} void @ReturnPassing4(ptr noalias sret +// SYSTEMZ: define{{.*}} void @ReturnPassing4(ptr dead_on_unwind noalias writable sret // PPC64: define{{.*}} i128 @ReturnPassing4( -// PPC32: define{{.*}} void @ReturnPassing4(ptr noalias sret +// PPC32: define{{.*}} void @ReturnPassing4(ptr dead_on_unwind noalias writable sret // AARCH64: define{{.*}} i128 @ReturnPassing4( // AARCH64DARWIN: define{{.*}} i128 @ReturnPassing4( -// ARM: define{{.*}} arm_aapcscc void @ReturnPassing4(ptr noalias sret +// ARM: define{{.*}} arm_aapcscc void @ReturnPassing4(ptr dead_on_unwind noalias writable sret // LA64: define{{.*}} i128 @ReturnPassing4( -// LA32: define{{.*}} void @ReturnPassing4(ptr noalias sret +// LA32: define{{.*}} void @ReturnPassing4(ptr dead_on_unwind noalias writable sret #if __BITINT_MAXWIDTH__ > 128 _BitInt(129) ReturnPassing5(void){} -// LIN64: define{{.*}} void @ReturnPassing5(ptr noalias sret -// WIN64: define dso_local void @ReturnPassing5(ptr noalias sret -// LIN32: define{{.*}} void @ReturnPassing5(ptr noalias sret -// WIN32: define dso_local void @ReturnPassing5(ptr noalias sret -// NACL-NOT: define{{.*}} void @ReturnPassing5(ptr noalias sret +// LIN64: define{{.*}} void @ReturnPassing5(ptr dead_on_unwind noalias writable sret +// WIN64: define dso_local void @ReturnPassing5(ptr dead_on_unwind noalias writable sret +// LIN32: define{{.*}} void @ReturnPassing5(ptr dead_on_unwind noalias writable sret +// WIN32: define dso_local void @ReturnPassing5(ptr dead_on_unwind noalias writable sret +// NACL-NOT: define{{.*}} void @ReturnPassing5(ptr dead_on_unwind noalias writable sret // NVPTX64-NOT: define{{.*}} i129 @ReturnPassing5( // NVPTX-NOT: define{{.*}} i129 @ReturnPassing5( // SPARCV9-NOT: define{{.*}} i129 @ReturnPassing5( -// SPARC-NOT: define{{.*}} void @ReturnPassing5(ptr noalias sret -// MIPS64-NOT: define{{.*}} void @ReturnPassing5(ptr noalias sret -// MIPS-NOT: define{{.*}} void @ReturnPassing5(ptr noalias sret -// SPIR64-NOT: define{{.*}} spir_func void @ReturnPassing5(ptr noalias sret -// SPIR-NOT: define{{.*}} spir_func void @ReturnPassing5(ptr noalias sret -// HEX-NOT: define{{.*}} void @ReturnPassing5(ptr noalias sret -// LANAI-NOT: define{{.*}} void @ReturnPassing5(ptr noalias sret +// SPARC-NOT: define{{.*}} void @ReturnPassing5(ptr dead_on_unwind noalias writable sret +// MIPS64-NOT: define{{.*}} void @ReturnPassing5(ptr dead_on_unwind noalias writable sret +// MIPS-NOT: define{{.*}} void @ReturnPassing5(ptr dead_on_unwind noalias writable sret +// SPIR64-NOT: define{{.*}} spir_func void @ReturnPassing5(ptr dead_on_unwind noalias writable sret +// SPIR-NOT: define{{.*}} spir_func void @ReturnPassing5(ptr dead_on_unwind noalias writable sret +// HEX-NOT: define{{.*}} void @ReturnPassing5(ptr dead_on_unwind noalias writable sret +// LANAI-NOT: define{{.*}} void @ReturnPassing5(ptr dead_on_unwind noalias writable sret // R600-NOT: define{{.*}} void @ReturnPassing5(ptr addrspace(5) noalias sret -// ARC-NOT: define{{.*}} void @ReturnPassing5(ptr inreg noalias sret -// XCORE-NOT: define{{.*}} void @ReturnPassing5(ptr noalias sret -// RISCV64-NOT: define{{.*}} void @ReturnPassing5(ptr noalias sret -// RISCV32-NOT: define{{.*}} void @ReturnPassing5(ptr noalias sret -// WASM-NOT: define{{.*}} void @ReturnPassing5(ptr noalias sret -// SYSTEMZ-NOT: define{{.*}} void @ReturnPassing5(ptr noalias sret -// PPC64-NOT: define{{.*}} void @ReturnPassing5(ptr noalias sret -// PPC32-NOT: define{{.*}} void @ReturnPassing5(ptr noalias sret -// AARCH64-NOT: define{{.*}} void @ReturnPassing5(ptr noalias sret -// AARCH64DARWIN-NOT: define{{.*}} void @ReturnPassing5(ptr noalias sret -// ARM-NOT: define{{.*}} arm_aapcscc void @ReturnPassing5(ptr noalias sret -// LA64-NOT: define{{.*}} void @ReturnPassing5(ptr noalias sret -// LA32-NOT: define{{.*}} void @ReturnPassing5(ptr noalias sret +// ARC-NOT: define{{.*}} void @ReturnPassing5(ptr dead_on_unwind inreg noalias writable sret +// XCORE-NOT: define{{.*}} void @ReturnPassing5(ptr dead_on_unwind noalias writable sret +// RISCV64-NOT: define{{.*}} void @ReturnPassing5(ptr dead_on_unwind noalias writable sret +// RISCV32-NOT: define{{.*}} void @ReturnPassing5(ptr dead_on_unwind noalias writable sret +// WASM-NOT: define{{.*}} void @ReturnPassing5(ptr dead_on_unwind noalias writable sret +// SYSTEMZ-NOT: define{{.*}} void @ReturnPassing5(ptr dead_on_unwind noalias writable sret +// PPC64-NOT: define{{.*}} void @ReturnPassing5(ptr dead_on_unwind noalias writable sret +// PPC32-NOT: define{{.*}} void @ReturnPassing5(ptr dead_on_unwind noalias writable sret +// AARCH64-NOT: define{{.*}} void @ReturnPassing5(ptr dead_on_unwind noalias writable sret +// AARCH64DARWIN-NOT: define{{.*}} void @ReturnPassing5(ptr dead_on_unwind noalias writable sret +// ARM-NOT: define{{.*}} arm_aapcscc void @ReturnPassing5(ptr dead_on_unwind noalias writable sret +// LA64-NOT: define{{.*}} void @ReturnPassing5(ptr dead_on_unwind noalias writable sret +// LA32-NOT: define{{.*}} void @ReturnPassing5(ptr dead_on_unwind noalias writable sret // SparcV9 is odd in that it has a return-size limit of 256, not 128 or 64 // like other platforms, so test to make sure this behavior will still work. _BitInt(256) ReturnPassing6(void) {} // SPARCV9-NOT: define{{.*}} i256 @ReturnPassing6( _BitInt(257) ReturnPassing7(void) {} -// SPARCV9-NOT: define{{.*}} void @ReturnPassing7(ptr noalias sret +// SPARCV9-NOT: define{{.*}} void @ReturnPassing7(ptr dead_on_unwind noalias writable sret #endif diff --git a/clang/test/CodeGen/flexible-array-init.c b/clang/test/CodeGen/flexible-array-init.c index b2cf959f7e1220ce30de70ac70631d4c939b6527..bae926da5feb0701a5a5f5ec0af2009ff6c65b32 100644 --- a/clang/test/CodeGen/flexible-array-init.c +++ b/clang/test/CodeGen/flexible-array-init.c @@ -20,3 +20,11 @@ struct __attribute((packed, aligned(4))) { char a; int x; char z[]; } e = { 1, 2 struct { int x; char y[]; } f = { 1, { 13, 15 } }; // CHECK: @f ={{.*}} global <{ i32, [2 x i8] }> <{ i32 1, [2 x i8] c"\0D\0F" }> + +union { + struct { + int a; + char b[]; + } x; +} in_union = {}; +// CHECK: @in_union ={{.*}} global %union.anon zeroinitializer diff --git a/clang/test/CodeGen/isfpclass.c b/clang/test/CodeGen/isfpclass.c index 430f5d94211f173e931802cb4282a9cb739c8087..6633db88f71a8199e21ac42253be8c7b84edabfe 100644 --- a/clang/test/CodeGen/isfpclass.c +++ b/clang/test/CodeGen/isfpclass.c @@ -160,7 +160,7 @@ int4 check_isfpclass_nan_strict_v4f32(float4 x) { } // CHECK-LABEL: define dso_local void @check_isfpclass_nan_v4f64 -// CHECK-SAME: (ptr noalias nocapture writeonly sret(<4 x i64>) align 16 [[AGG_RESULT:%.*]], ptr nocapture noundef readonly [[TMP0:%.*]]) local_unnamed_addr #[[ATTR3:[0-9]+]] { +// CHECK-SAME: (ptr dead_on_unwind noalias nocapture writable writeonly sret(<4 x i64>) align 16 [[AGG_RESULT:%.*]], ptr nocapture noundef readonly [[TMP0:%.*]]) local_unnamed_addr #[[ATTR3:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: [[X:%.*]] = load <4 x double>, ptr [[TMP0]], align 16, !tbaa [[TBAA2:![0-9]+]] // CHECK-NEXT: [[TMP1:%.*]] = fcmp uno <4 x double> [[X]], zeroinitializer diff --git a/clang/test/CodeGen/lanai-arguments.c b/clang/test/CodeGen/lanai-arguments.c index bc291faa867f511632d8afe896b7fb4018281998..bfd3b41a91eb28af198315cdc202e21cb643bae3 100644 --- a/clang/test/CodeGen/lanai-arguments.c +++ b/clang/test/CodeGen/lanai-arguments.c @@ -16,7 +16,7 @@ void f1(s1 i) {} typedef struct { int cc; } s2; -// CHECK: define{{.*}} void @f2(ptr noalias sret(%struct.s2) align 4 %agg.result) +// CHECK: define{{.*}} void @f2(ptr dead_on_unwind noalias writable sret(%struct.s2) align 4 %agg.result) s2 f2(void) { s2 foo; return foo; @@ -26,7 +26,7 @@ typedef struct { int cc; int dd; } s3; -// CHECK: define{{.*}} void @f3(ptr noalias sret(%struct.s3) align 4 %agg.result) +// CHECK: define{{.*}} void @f3(ptr dead_on_unwind noalias writable sret(%struct.s3) align 4 %agg.result) s3 f3(void) { s3 foo; return foo; diff --git a/clang/test/CodeGen/large-data-threshold.c b/clang/test/CodeGen/large-data-threshold.c index 29ae19e9b71899421af67c038ee2005067c2abd7..d110ad2125c7bc4c04cc8b2efa8dc162b694502c 100644 --- a/clang/test/CodeGen/large-data-threshold.c +++ b/clang/test/CodeGen/large-data-threshold.c @@ -2,11 +2,14 @@ // RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm %s -o - -mcmodel=medium | FileCheck %s --check-prefix=IR-DEFAULT // RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm %s -o - -mcmodel=medium -mlarge-data-threshold=200 | FileCheck %s --check-prefix=IR-CUSTOM +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm %s -o - -mcmodel=large -mlarge-data-threshold=200 | FileCheck %s --check-prefix=IR-CUSTOM +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm %s -o - -mcmodel=small -mlarge-data-threshold=200 | FileCheck %s --check-prefix=IR-SMALL // RUN: %clang_cc1 -triple x86_64-unknown-unknown -S %s -o - -mcmodel=medium -mlarge-data-threshold=200 | FileCheck %s --check-prefix=ASM-SMALL // RUN: %clang_cc1 -triple x86_64-unknown-unknown -S %s -o - -mcmodel=medium -mlarge-data-threshold=2 | FileCheck %s --check-prefix=ASM-LARGE -// IR-DEFAULT: !{i32 1, !"Large Data Threshold", i64 65535} +// IR-DEFAULT: !{i32 1, !"Large Data Threshold", i64 0} // IR-CUSTOM: !{i32 1, !"Large Data Threshold", i64 200} +// IR-SMALL-NOT: !"Large Data Threshold" // ASM-SMALL-NOT: movabsq // ASM-LARGE: movabsq diff --git a/clang/test/CodeGen/mcu-struct-return.c b/clang/test/CodeGen/mcu-struct-return.c index 218f9734c9c3261606a1078d1e7e5c6f817f9e4e..38a9bc2a36bfec4d7520181b39227920a6c30f5f 100644 --- a/clang/test/CodeGen/mcu-struct-return.c +++ b/clang/test/CodeGen/mcu-struct-return.c @@ -42,7 +42,7 @@ struct S1 bar1(void) { return s1; } struct S2 bar2(void) { return s2; } struct S1 bar3(union U1 u) { return s1; } // CHECK: define{{.*}} void @foo1() -// CHECK: define{{.*}} void @foo2(ptr noalias sret([[UNION2_TYPE]]) align 4 %{{.+}}) +// CHECK: define{{.*}} void @foo2(ptr dead_on_unwind noalias writable sret([[UNION2_TYPE]]) align 4 %{{.+}}) // CHECK: define{{.*}} i32 @foo3() // CHECK: define{{.*}} void @bar1() // CHECK: define{{.*}} i32 @bar2() @@ -62,7 +62,7 @@ void run(void) { // CHECK: [[Y1:%.+]] = alloca [[STRUCT1_TYPE]] // CHECK: [[Y2:%.+]] = alloca [[STRUCT2_TYPE]] // CHECK: call void @foo1() - // CHECK: call void @foo2(ptr sret([[UNION2_TYPE]]) align 4 [[X2]]) + // CHECK: call void @foo2(ptr dead_on_unwind writable sret([[UNION2_TYPE]]) align 4 [[X2]]) // CHECK: {{.+}} = call i32 @foo3() // CHECK: call void @bar1() // CHECK: {{.+}} = call i32 @bar2() diff --git a/clang/test/CodeGen/mingw-long-double.c b/clang/test/CodeGen/mingw-long-double.c index a50f8f0b3b633417eff3829e4a81044188d9dbaa..4be97526f963193d50d11e9a965aa2c2636acb20 100644 --- a/clang/test/CodeGen/mingw-long-double.c +++ b/clang/test/CodeGen/mingw-long-double.c @@ -32,15 +32,15 @@ long double TestLD(long double x) { return x * x; } // GNU32: define dso_local x86_fp80 @TestLD(x86_fp80 noundef %x) -// GNU64: define dso_local void @TestLD(ptr noalias sret(x86_fp80) align 16 %agg.result, ptr noundef %0) +// GNU64: define dso_local void @TestLD(ptr dead_on_unwind noalias writable sret(x86_fp80) align 16 %agg.result, ptr noundef %0) // MSC64: define dso_local double @TestLD(double noundef %x) long double _Complex TestLDC(long double _Complex x) { return x * x; } -// GNU32: define dso_local void @TestLDC(ptr noalias sret({ x86_fp80, x86_fp80 }) align 4 %agg.result, ptr noundef byval({ x86_fp80, x86_fp80 }) align 4 %x) -// GNU64: define dso_local void @TestLDC(ptr noalias sret({ x86_fp80, x86_fp80 }) align 16 %agg.result, ptr noundef %x) -// MSC64: define dso_local void @TestLDC(ptr noalias sret({ double, double }) align 8 %agg.result, ptr noundef %x) +// GNU32: define dso_local void @TestLDC(ptr dead_on_unwind noalias writable sret({ x86_fp80, x86_fp80 }) align 4 %agg.result, ptr noundef byval({ x86_fp80, x86_fp80 }) align 4 %x) +// GNU64: define dso_local void @TestLDC(ptr dead_on_unwind noalias writable sret({ x86_fp80, x86_fp80 }) align 16 %agg.result, ptr noundef %x) +// MSC64: define dso_local void @TestLDC(ptr dead_on_unwind noalias writable sret({ double, double }) align 8 %agg.result, ptr noundef %x) // GNU32: declare dso_local void @__mulxc3 // GNU64: declare dso_local void @__mulxc3 diff --git a/clang/test/CodeGen/mips-vector-return.c b/clang/test/CodeGen/mips-vector-return.c index b6da2af2ffd6678111f61cf03c780f734f109bdc..d2103d1def7456827cac079a4143281ce4c7e98e 100644 --- a/clang/test/CodeGen/mips-vector-return.c +++ b/clang/test/CodeGen/mips-vector-return.c @@ -8,14 +8,14 @@ typedef float v4sf __attribute__ ((__vector_size__ (16))); typedef double v4df __attribute__ ((__vector_size__ (32))); typedef int v4i32 __attribute__ ((__vector_size__ (16))); -// O32-LABEL: define{{.*}} void @test_v4sf(ptr noalias nocapture writeonly sret +// O32-LABEL: define{{.*}} void @test_v4sf(ptr dead_on_unwind noalias nocapture writable writeonly sret // N64: define{{.*}} inreg { i64, i64 } @test_v4sf v4sf test_v4sf(float a) { return (v4sf){0.0f, a, 0.0f, 0.0f}; } -// O32-LABEL: define{{.*}} void @test_v4df(ptr noalias nocapture writeonly sret -// N64-LABEL: define{{.*}} void @test_v4df(ptr noalias nocapture writeonly sret +// O32-LABEL: define{{.*}} void @test_v4df(ptr dead_on_unwind noalias nocapture writable writeonly sret +// N64-LABEL: define{{.*}} void @test_v4df(ptr dead_on_unwind noalias nocapture writable writeonly sret v4df test_v4df(double a) { return (v4df){0.0, a, 0.0, 0.0}; } diff --git a/clang/test/CodeGen/mips-zero-sized-struct.c b/clang/test/CodeGen/mips-zero-sized-struct.c index 12bd9abf6cf4ca1868bd4001687a84b23f043b8a..b40ff59f73fb2c50735adcc64432d8d34e9ce878 100644 --- a/clang/test/CodeGen/mips-zero-sized-struct.c +++ b/clang/test/CodeGen/mips-zero-sized-struct.c @@ -19,7 +19,7 @@ // RUN: %clang_cc1 -triple mipsisa64r6-unknown-linux-gnuabi64 -S -emit-llvm -o - %s | FileCheck -check-prefix=N64 %s // RUN: %clang_cc1 -triple mipsisa64r6el-unknown-linux-gnuabi64 -S -emit-llvm -o - %s | FileCheck -check-prefix=N64 %s -// O32: define{{.*}} void @fn28(ptr noalias sret(%struct.T2) align 1 %agg.result, i8 noundef signext %arg0) +// O32: define{{.*}} void @fn28(ptr dead_on_unwind noalias writable sret(%struct.T2) align 1 %agg.result, i8 noundef signext %arg0) // N32: define{{.*}} void @fn28(i8 noundef signext %arg0) // N64: define{{.*}} void @fn28(i8 noundef signext %arg0) diff --git a/clang/test/CodeGen/mips64-nontrivial-return.cpp b/clang/test/CodeGen/mips64-nontrivial-return.cpp index 0987dcaf355dd27863d9fcee369c0074ad500c16..a8fbf4622f80360c16942aa7c4c1e353a00405ee 100644 --- a/clang/test/CodeGen/mips64-nontrivial-return.cpp +++ b/clang/test/CodeGen/mips64-nontrivial-return.cpp @@ -10,7 +10,7 @@ class D : public B { extern D gd0; -// CHECK: _Z4foo1v(ptr noalias nocapture writeonly sret +// CHECK: _Z4foo1v(ptr dead_on_unwind noalias nocapture writable writeonly sret D foo1(void) { return gd0; diff --git a/clang/test/CodeGen/mips64-padding-arg.c b/clang/test/CodeGen/mips64-padding-arg.c index 7fda45f75098f972275c8c336b4494ed26229f5a..038103b1df3aaf7a62284d8478dd9f4ec0dc45da 100644 --- a/clang/test/CodeGen/mips64-padding-arg.c +++ b/clang/test/CodeGen/mips64-padding-arg.c @@ -33,9 +33,9 @@ void foo3(int a0, long double a1) { // Insert padding after hidden argument. // -// N64-LABEL: define{{.*}} void @foo5(ptr noalias sret(%struct.S0) align 16 %agg.result, i64 %0, fp128 noundef %a0) -// N64: call void @foo6(ptr sret(%struct.S0) align 16 %agg.result, i32 noundef signext 1, i32 noundef signext 2, i64 undef, fp128 noundef %a0) -// N64: declare void @foo6(ptr sret(%struct.S0) align 16, i32 noundef signext, i32 noundef signext, i64, fp128 noundef) +// N64-LABEL: define{{.*}} void @foo5(ptr dead_on_unwind noalias writable sret(%struct.S0) align 16 %agg.result, i64 %0, fp128 noundef %a0) +// N64: call void @foo6(ptr dead_on_unwind writable sret(%struct.S0) align 16 %agg.result, i32 noundef signext 1, i32 noundef signext 2, i64 undef, fp128 noundef %a0) +// N64: declare void @foo6(ptr dead_on_unwind writable sret(%struct.S0) align 16, i32 noundef signext, i32 noundef signext, i64, fp128 noundef) extern S0 foo6(int, int, long double); diff --git a/clang/test/CodeGen/ms_abi.c b/clang/test/CodeGen/ms_abi.c index adc5094267cbdbb29e264f00f7a884403f9799a3..0fe1741cf9a0a167b4b1c434375c28e745406d2d 100644 --- a/clang/test/CodeGen/ms_abi.c +++ b/clang/test/CodeGen/ms_abi.c @@ -141,7 +141,7 @@ struct i128 { }; __attribute__((ms_abi)) struct i128 f7(struct i128 a) { - // WIN64: define dso_local void @f7(ptr noalias sret(%struct.i128) align 8 %agg.result, ptr noundef %a) - // FREEBSD: define{{.*}} win64cc void @f7(ptr noalias sret(%struct.i128) align 8 %agg.result, ptr noundef %a) + // WIN64: define dso_local void @f7(ptr dead_on_unwind noalias writable sret(%struct.i128) align 8 %agg.result, ptr noundef %a) + // FREEBSD: define{{.*}} win64cc void @f7(ptr dead_on_unwind noalias writable sret(%struct.i128) align 8 %agg.result, ptr noundef %a) return a; } diff --git a/clang/test/CodeGen/paren-list-agg-init.cpp b/clang/test/CodeGen/paren-list-agg-init.cpp index 0e68beb5c37066bc0fe0528c001d4785d675d76a..eb8d91a7f97f62f76606b9974dd6339829fd761e 100644 --- a/clang/test/CodeGen/paren-list-agg-init.cpp +++ b/clang/test/CodeGen/paren-list-agg-init.cpp @@ -136,7 +136,7 @@ A foo1() { return a1; } -// CHECK: define dso_local void @{{.*foo2.*}}(ptr noalias sret([[STRUCT_B]]) align 8 [[AGG_RESULT:%.*]]) +// CHECK: define dso_local void @{{.*foo2.*}}(ptr dead_on_unwind noalias writable sret([[STRUCT_B]]) align 8 [[AGG_RESULT:%.*]]) // CHECK-NEXT: entry: // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_RESULT]], ptr align 8 [[B1]], i64 24, i1 false) // CHECK-NEXT: ret void @@ -144,7 +144,7 @@ B foo2() { return b1; } -// CHECK: define dso_local void @{{.*foo3.*}}(ptr noalias sret([[STRUCT_C]]) align 8 [[AGG_RESULT:%.*]]) +// CHECK: define dso_local void @{{.*foo3.*}}(ptr dead_on_unwind noalias writable sret([[STRUCT_C]]) align 8 [[AGG_RESULT:%.*]]) // CHECK-NEXT: entry: // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_RESULT]], ptr align 8 [[C1]], i64 48, i1 false) // CHECK-NEXT: ret void @@ -229,7 +229,7 @@ void foo7() { D d(A(1, 1), A(11, 11), A(111, 111)); } -// CHECK: dso_local void @{{.*foo8.*}}(ptr noalias sret([[STRUCT_D]]) align 8 [[AGG_RESULT:%.*]]) +// CHECK: dso_local void @{{.*foo8.*}}(ptr dead_on_unwind noalias writable sret([[STRUCT_D]]) align 8 [[AGG_RESULT:%.*]]) // CHECK-NEXT: entry: // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_RESULT]], ptr align 8 [[D1]], i64 56, i1 false) // CHECK-NEXT: ret void diff --git a/clang/test/CodeGen/regcall2.c b/clang/test/CodeGen/regcall2.c index 96bc6615012af340d12b447242159d51e790fcd9..c88d4e485b1049b9ff5ac6f1b9ed5c6e749c815d 100644 --- a/clang/test/CodeGen/regcall2.c +++ b/clang/test/CodeGen/regcall2.c @@ -19,7 +19,7 @@ double __regcall bar(__sVector a) { } // FIXME: Do we need to change for Windows? -// Win: define dso_local x86_regcallcc void @__regcall3__foo(ptr noalias sret(%struct.__sVector) align 64 %agg.result, i32 noundef %a) #0 +// Win: define dso_local x86_regcallcc void @__regcall3__foo(ptr dead_on_unwind noalias writable sret(%struct.__sVector) align 64 %agg.result, i32 noundef %a) #0 // Win: define dso_local x86_regcallcc double @__regcall3__bar(ptr noundef %a) #0 // Win: attributes #0 = { noinline nounwind optnone "min-legal-vector-width"="0" "no-builtins" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+avx,+avx2,+avx512f,+avx512vl,+crc32,+cx8,+evex512,+f16c,+fma,+mmx,+popcnt,+sse,+sse2,+sse3,+sse4.1,+sse4.2,+ssse3,+x87,+xsave" } diff --git a/clang/test/CodeGen/regparm-struct.c b/clang/test/CodeGen/regparm-struct.c index 70901ca364d05e60a59436049a4580ec96e17002..a533f6cedbba2432550bfa1852542ba5040dfe4b 100644 --- a/clang/test/CodeGen/regparm-struct.c +++ b/clang/test/CodeGen/regparm-struct.c @@ -159,7 +159,7 @@ void g16(void) { } __attribute__((regparm(3))) struct s12 f17(int a, int b, int c); -// CHECK: declare void @f17(ptr inreg sret(%struct.s12) align 4, i32 inreg noundef, i32 inreg noundef, i32 noundef) +// CHECK: declare void @f17(ptr dead_on_unwind inreg writable sret(%struct.s12) align 4, i32 inreg noundef, i32 inreg noundef, i32 noundef) void g17(void) { f17(41, 42, 43); } diff --git a/clang/test/CodeGen/renderscript.c b/clang/test/CodeGen/renderscript.c index 8acf16566454c9dbe1ca6bbbcaaacae6248032e6..1629665c1ffb8746ead76e28267df186be890acb 100644 --- a/clang/test/CodeGen/renderscript.c +++ b/clang/test/CodeGen/renderscript.c @@ -83,15 +83,15 @@ void argLongInt(sLongInt s) {} // and coerced to [a x iNN] for 64-bit RenderScript // ============================================================================= -// CHECK-RS32: void @retShortCharShort(ptr noalias sret(%struct.sShortCharShort) align 2 %agg.result) +// CHECK-RS32: void @retShortCharShort(ptr dead_on_unwind noalias writable sret(%struct.sShortCharShort) align 2 %agg.result) // CHECK-RS64: [3 x i16] @retShortCharShort() sShortCharShort retShortCharShort(void) { sShortCharShort r; return r; } -// CHECK-RS32: void @retIntShortChar(ptr noalias sret(%struct.sIntShortChar) align 4 %agg.result) +// CHECK-RS32: void @retIntShortChar(ptr dead_on_unwind noalias writable sret(%struct.sIntShortChar) align 4 %agg.result) // CHECK-RS64: [2 x i32] @retIntShortChar() sIntShortChar retIntShortChar(void) { sIntShortChar r; return r; } -// CHECK-RS32: void @retLongInt(ptr noalias sret(%struct.sLongInt) align 8 %agg.result) +// CHECK-RS32: void @retLongInt(ptr dead_on_unwind noalias writable sret(%struct.sLongInt) align 8 %agg.result) // CHECK-RS64: [2 x i64] @retLongInt() sLongInt retLongInt(void) { sLongInt r; return r; } @@ -116,12 +116,12 @@ void argLong2Char(sLong2Char s) {} // 64-bit RenderScript // ============================================================================= -// CHECK-RS32: void @retInt5(ptr noalias sret(%struct.sInt5) align 4 %agg.result) -// CHECK-RS64: void @retInt5(ptr noalias sret(%struct.sInt5) align 4 %agg.result) +// CHECK-RS32: void @retInt5(ptr dead_on_unwind noalias writable sret(%struct.sInt5) align 4 %agg.result) +// CHECK-RS64: void @retInt5(ptr dead_on_unwind noalias writable sret(%struct.sInt5) align 4 %agg.result) sInt5 retInt5(void) { sInt5 r; return r;} -// CHECK-RS32: void @retLong2Char(ptr noalias sret(%struct.sLong2Char) align 8 %agg.result) -// CHECK-RS64: void @retLong2Char(ptr noalias sret(%struct.sLong2Char) align 8 %agg.result) +// CHECK-RS32: void @retLong2Char(ptr dead_on_unwind noalias writable sret(%struct.sLong2Char) align 8 %agg.result) +// CHECK-RS64: void @retLong2Char(ptr dead_on_unwind noalias writable sret(%struct.sLong2Char) align 8 %agg.result) sLong2Char retLong2Char(void) { sLong2Char r; return r;} // ============================================================================= @@ -135,6 +135,6 @@ typedef struct {long l1, l2, l3, l4, l5, l6, l7, l8, l9; } sLong9; // CHECK-RS64: void @argLong9(ptr noundef %s) void argLong9(sLong9 s) {} -// CHECK-RS32: void @retLong9(ptr noalias sret(%struct.sLong9) align 8 %agg.result) -// CHECK-RS64: void @retLong9(ptr noalias sret(%struct.sLong9) align 8 %agg.result) +// CHECK-RS32: void @retLong9(ptr dead_on_unwind noalias writable sret(%struct.sLong9) align 8 %agg.result) +// CHECK-RS64: void @retLong9(ptr dead_on_unwind noalias writable sret(%struct.sLong9) align 8 %agg.result) sLong9 retLong9(void) { sLong9 r; return r; } diff --git a/clang/test/CodeGen/sparcv9-abi.c b/clang/test/CodeGen/sparcv9-abi.c index 2d39c64c1c2ce6c76a974907349a59c02fbafd0e..5e74a9a883cefaee3aada9cf3d4c0e6da6ea5478 100644 --- a/clang/test/CodeGen/sparcv9-abi.c +++ b/clang/test/CodeGen/sparcv9-abi.c @@ -53,7 +53,7 @@ struct large { int x; }; -// CHECK-LABEL: define{{.*}} void @f_large(ptr noalias sret(%struct.large) align 8 %agg.result, ptr noundef %x) +// CHECK-LABEL: define{{.*}} void @f_large(ptr dead_on_unwind noalias writable sret(%struct.large) align 8 %agg.result, ptr noundef %x) struct large f_large(struct large x) { x.a += *x.b; x.b = 0; diff --git a/clang/test/CodeGen/sret.c b/clang/test/CodeGen/sret.c index 548581d3e3dc661907057018caa12b526c9756d3..6d905e89b2c6fdb45d767f0b3d9c260ebb246176 100644 --- a/clang/test/CodeGen/sret.c +++ b/clang/test/CodeGen/sret.c @@ -9,15 +9,15 @@ struct abc { }; struct abc foo1(void); -// CHECK-DAG: declare {{.*}} @foo1(ptr sret(%struct.abc) +// CHECK-DAG: declare {{.*}} @foo1(ptr dead_on_unwind writable sret(%struct.abc) struct abc foo2(); -// CHECK-DAG: declare {{.*}} @foo2(ptr sret(%struct.abc) +// CHECK-DAG: declare {{.*}} @foo2(ptr dead_on_unwind writable sret(%struct.abc) struct abc foo3(void){} -// CHECK-DAG: define {{.*}} @foo3(ptr noalias sret(%struct.abc) +// CHECK-DAG: define {{.*}} @foo3(ptr dead_on_unwind noalias writable sret(%struct.abc) void bar(void) { struct abc dummy1 = foo1(); - // CHECK-DAG: call {{.*}} @foo1(ptr sret(%struct.abc) + // CHECK-DAG: call {{.*}} @foo1(ptr dead_on_unwind writable sret(%struct.abc) struct abc dummy2 = foo2(); - // CHECK-DAG: call {{.*}} @foo2(ptr sret(%struct.abc) + // CHECK-DAG: call {{.*}} @foo2(ptr dead_on_unwind writable sret(%struct.abc) } diff --git a/clang/test/CodeGen/thinlto-debug-names-tu-reuse.ll b/clang/test/CodeGen/thinlto-debug-names-tu-reuse.ll new file mode 100644 index 0000000000000000000000000000000000000000..8719473820053e42d8ed28110863d41531721b96 --- /dev/null +++ b/clang/test/CodeGen/thinlto-debug-names-tu-reuse.ll @@ -0,0 +1,59 @@ +; REQUIRES: asserts +; REQUIRES: x86-registered-target + +;; Tests that accelerator table switches correctly from TU to CU when a top level TU is re-used. +;; Assert is not triggered. +;; File1 +;; struct Foo { +;; char fChar; +;; }; +;; Foo fGlobal; +;; FIle2 +;; struct Foo { +;; char fChar; +;; }; +;; Foo fGlobal2; +;; clang++ .cpp -O0 -g2 -fdebug-types-section -gpubnames -S -emit-llvm -o .ll +;; llvm-link file1.ll file2.ll -S -o thinlto-debug-names-tu-reuse.ll + +; RUN: llc -O0 -dwarf-version=5 -generate-type-units -filetype=obj < %s -o %t.o +; RUN: llvm-readelf --sections %t.o | FileCheck --check-prefix=OBJ %s + +; OBJ: debug_names + +; ModuleID = 'llvm-link' +source_filename = "llvm-link" +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +%struct.Foo = type { i8 } + +@fGlobal = dso_local global %struct.Foo zeroinitializer, align 1, !dbg !0 +@fGlobal2 = dso_local global %struct.Foo zeroinitializer, align 1, !dbg !9 + +!llvm.dbg.cu = !{!2, !11} +!llvm.ident = !{!14, !14} +!llvm.module.flags = !{!15, !16, !17, !18, !19, !20, !21} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "fGlobal", scope: !2, file: !3, line: 5, type: !5, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !3, producer: "clang version 18.0.0git", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, globals: !4, splitDebugInlining: false) +!3 = !DIFile(filename: "main.cpp", directory: "/smallTUReuse", checksumkind: CSK_MD5, checksum: "4f1831504f0948b03880356fae49cb58") +!4 = !{!0} +!5 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Foo", file: !3, line: 2, size: 8, flags: DIFlagTypePassByValue, elements: !6, identifier: "_ZTS3Foo") +!6 = !{!7} +!7 = !DIDerivedType(tag: DW_TAG_member, name: "fChar", scope: !5, file: !3, line: 3, baseType: !8, size: 8) +!8 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char) +!9 = !DIGlobalVariableExpression(var: !10, expr: !DIExpression()) +!10 = distinct !DIGlobalVariable(name: "fGlobal2", scope: !11, file: !12, line: 5, type: !5, isLocal: false, isDefinition: true) +!11 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !12, producer: "clang version 18.0.0git", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, globals: !13, splitDebugInlining: false) +!12 = !DIFile(filename: "helper.cpp", directory: "/smallTUReuse", checksumkind: CSK_MD5, checksum: "014145d46991fd1eb6a2192d382feb75") +!13 = !{!9} +!14 = !{!"clang version 18.0.0git"} +!15 = !{i32 7, !"Dwarf Version", i32 5} +!16 = !{i32 2, !"Debug Info Version", i32 3} +!17 = !{i32 1, !"wchar_size", i32 4} +!18 = !{i32 8, !"PIC Level", i32 2} +!19 = !{i32 7, !"PIE Level", i32 2} +!20 = !{i32 7, !"uwtable", i32 2} +!21 = !{i32 7, !"frame-pointer", i32 2} diff --git a/clang/test/CodeGen/vectorcall.c b/clang/test/CodeGen/vectorcall.c index b5f7efec67511887fd097474b4f36cc16def53ea..cb53ecc70351d627515c9c6fdb4009fc810a2ffd 100644 --- a/clang/test/CodeGen/vectorcall.c +++ b/clang/test/CodeGen/vectorcall.c @@ -90,8 +90,8 @@ struct HVA4 __vectorcall hva6(struct HVA4 a, struct HVA4 b) { return b;} // X64: define dso_local x86_vectorcallcc %struct.HVA4 @"\01hva6@@128"(%struct.HVA4 inreg %a.coerce, ptr noundef %b) struct HVA5 __vectorcall hva7(void) {struct HVA5 a = {}; return a;} -// X86: define dso_local x86_vectorcallcc void @"\01hva7@@0"(ptr inreg noalias sret(%struct.HVA5) align 16 %agg.result) -// X64: define dso_local x86_vectorcallcc void @"\01hva7@@0"(ptr noalias sret(%struct.HVA5) align 16 %agg.result) +// X86: define dso_local x86_vectorcallcc void @"\01hva7@@0"(ptr dead_on_unwind inreg noalias writable sret(%struct.HVA5) align 16 %agg.result) +// X64: define dso_local x86_vectorcallcc void @"\01hva7@@0"(ptr dead_on_unwind noalias writable sret(%struct.HVA5) align 16 %agg.result) v4f32 __vectorcall hva8(v4f32 a, v4f32 b, v4f32 c, v4f32 d, int e, v4f32 f) {return f;} // X86: define dso_local x86_vectorcallcc <4 x float> @"\01hva8@@84"(<4 x float> inreg noundef %a, <4 x float> inreg noundef %b, <4 x float> inreg noundef %c, <4 x float> inreg noundef %d, i32 inreg noundef %e, <4 x float> inreg noundef %f) diff --git a/clang/test/CodeGen/windows-struct-abi.c b/clang/test/CodeGen/windows-struct-abi.c index 4431d91b63ca5921b222214221d57c2562fe5795..5e63c5b3344dd474a726ad14e7db1bda2cf421d7 100644 --- a/clang/test/CodeGen/windows-struct-abi.c +++ b/clang/test/CodeGen/windows-struct-abi.c @@ -34,7 +34,7 @@ struct f4 { struct f4 return_f4(void) { while (1); } -// CHECK: define dso_local void @return_f4(ptr noalias sret(%struct.f4) align 4 %agg.result) +// CHECK: define dso_local void @return_f4(ptr dead_on_unwind noalias writable sret(%struct.f4) align 4 %agg.result) void receive_f4(struct f4 a0) { } diff --git a/clang/test/CodeGen/windows-swiftcall.c b/clang/test/CodeGen/windows-swiftcall.c index 3e5c8a4d4b9d74efbd915c7dbc8aca018af0135f..6c138a341835d67724b70efaac5e28d44dadaf81 100644 --- a/clang/test/CodeGen/windows-swiftcall.c +++ b/clang/test/CodeGen/windows-swiftcall.c @@ -20,7 +20,7 @@ SWIFTCALL int indirect_result_2(OUT int *arg0, OUT float *arg1) { __builtin_unr typedef struct { char array[1024]; } struct_reallybig; SWIFTCALL struct_reallybig indirect_result_3(OUT int *arg0, OUT float *arg1) { __builtin_unreachable(); } -// CHECK-LABEL: define {{.*}} void @indirect_result_3(ptr noalias sret({{.*}}) {{.*}}, ptr noalias noundef align 4 dereferenceable(4){{.*}}, ptr noalias noundef align 4 dereferenceable(4){{.*}}) +// CHECK-LABEL: define {{.*}} void @indirect_result_3(ptr dead_on_unwind noalias writable sret({{.*}}) {{.*}}, ptr noalias noundef align 4 dereferenceable(4){{.*}}, ptr noalias noundef align 4 dereferenceable(4){{.*}}) SWIFTCALL void context_1(CONTEXT void *self) {} // CHECK-LABEL: define {{.*}} void @context_1(ptr noundef swiftself @@ -218,7 +218,7 @@ typedef struct { } struct_big_1; TEST(struct_big_1) -// CHECK-LABEL: define {{.*}} void @return_struct_big_1({{.*}} noalias sret +// CHECK-LABEL: define {{.*}} void @return_struct_big_1({{.*}} dead_on_unwind noalias writable sret // Should not be byval. // CHECK-LABEL: define {{.*}} void @take_struct_big_1(ptr noundef{{( %.*)?}}) diff --git a/clang/test/CodeGenCXX/aix-alignment.cpp b/clang/test/CodeGenCXX/aix-alignment.cpp index a8bb95814b1a4dd76b037b21ad4a2de03b3da8a9..d4397f3120ec5e86f2f3d28bb2bc6afddf8fbdc4 100644 --- a/clang/test/CodeGenCXX/aix-alignment.cpp +++ b/clang/test/CodeGenCXX/aix-alignment.cpp @@ -29,7 +29,7 @@ typedef struct D { ~D(){}; } D; -// AIX: define void @_Z3foo1D(ptr noalias sret(%struct.D) align 4 %agg.result, ptr noundef %x) +// AIX: define void @_Z3foo1D(ptr dead_on_unwind noalias writable sret(%struct.D) align 4 %agg.result, ptr noundef %x) // AIX32 call void @llvm.memcpy.p0.p0.i32(ptr align 4 %agg.result, ptr align 4 %x, i32 16, i1 false) // AIX64: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %agg.result, ptr align 4 %x, i64 16, i1 false) D foo(D x) { return x; } diff --git a/clang/test/CodeGenCXX/arm-cc.cpp b/clang/test/CodeGenCXX/arm-cc.cpp index 967d10096f72b27e444596bb9f2abec874db07d3..68e1b7e4e1e4665a4766ba811e6e551644dd327b 100644 --- a/clang/test/CodeGenCXX/arm-cc.cpp +++ b/clang/test/CodeGenCXX/arm-cc.cpp @@ -16,5 +16,5 @@ void baz() { zed(a); } -// CHECK: declare void @_Z3fooPv(ptr sret(%class.SMLoc) align 4, ptr noundef) +// CHECK: declare void @_Z3fooPv(ptr dead_on_unwind writable sret(%class.SMLoc) align 4, ptr noundef) // CHECK: declare void @_Z3zed5SMLoc(ptr noundef) diff --git a/clang/test/CodeGenCXX/arm-swiftcall.cpp b/clang/test/CodeGenCXX/arm-swiftcall.cpp index 687e4c8b4dcbeec7af53a97285ed76070bd28ddc..e60c1482700a4b9ffcf80b5043be71d7eb8ae6ae 100644 --- a/clang/test/CodeGenCXX/arm-swiftcall.cpp +++ b/clang/test/CodeGenCXX/arm-swiftcall.cpp @@ -105,7 +105,7 @@ struct struct_indirect_1 { }; TEST(struct_indirect_1) -// CHECK-LABEL: define {{.*}} void @return_struct_indirect_1({{.*}} noalias sret +// CHECK-LABEL: define {{.*}} void @return_struct_indirect_1({{.*}} dead_on_unwind noalias writable sret // Should not be byval. // CHECK-LABEL: define {{.*}} void @take_struct_indirect_1(ptr noundef{{( %.*)?}}) diff --git a/clang/test/CodeGenCXX/attr-musttail.cpp b/clang/test/CodeGenCXX/attr-musttail.cpp index b8a1961d5eb7778cd2ae36c6342a1266f9ba4d0f..720e50c5a240f815d2fdfe62d53c55b3af22aee8 100644 --- a/clang/test/CodeGenCXX/attr-musttail.cpp +++ b/clang/test/CodeGenCXX/attr-musttail.cpp @@ -162,7 +162,7 @@ HasNonTrivialCopyConstructor TestNonElidableCopyConstructor() { [[clang::musttail]] return (((ReturnsClassByValue()))); } -// CHECK: musttail call void @_Z19ReturnsClassByValuev(ptr sret(%struct.HasNonTrivialCopyConstructor) align 1 %agg.result) +// CHECK: musttail call void @_Z19ReturnsClassByValuev(ptr dead_on_unwind writable sret(%struct.HasNonTrivialCopyConstructor) align 1 %agg.result) struct HasNonTrivialCopyConstructor2 { // Copy constructor works even if it has extra default params. @@ -191,8 +191,8 @@ LargeWithCopyConstructor TestLargeWithCopyConstructor() { [[clang::musttail]] return ReturnsLarge(); } -// CHECK: define dso_local void @_Z28TestLargeWithCopyConstructorv(ptr noalias sret(%struct.LargeWithCopyConstructor) align 1 %agg.result) -// CHECK: musttail call void @_Z12ReturnsLargev(ptr sret(%struct.LargeWithCopyConstructor) align 1 %agg.result) +// CHECK: define dso_local void @_Z28TestLargeWithCopyConstructorv(ptr dead_on_unwind noalias writable sret(%struct.LargeWithCopyConstructor) align 1 %agg.result) +// CHECK: musttail call void @_Z12ReturnsLargev(ptr dead_on_unwind writable sret(%struct.LargeWithCopyConstructor) align 1 %agg.result) using IntFunctionType = int(); IntFunctionType *ReturnsIntFunction(); diff --git a/clang/test/CodeGenCXX/call-with-static-chain.cpp b/clang/test/CodeGenCXX/call-with-static-chain.cpp index 06c3f15396a86f7533c77922794c3fd7bcd974e0..61011a65e4a2cedd5443b1b9dcb876492aa0231a 100644 --- a/clang/test/CodeGenCXX/call-with-static-chain.cpp +++ b/clang/test/CodeGenCXX/call-with-static-chain.cpp @@ -25,8 +25,8 @@ void test() { // CHECK64: call i32 @f1(ptr nest noundef @f1 __builtin_call_with_static_chain(f1(a, a, a, a), f1); - // CHECK32: call void @f2(ptr sret(%struct.B) align 4 %{{[0-9a-z]+}}, ptr nest noundef @f2) - // CHECK64: call void @f2(ptr sret(%struct.B) align 8 %{{[0-9a-z]+}}, ptr nest noundef @f2) + // CHECK32: call void @f2(ptr dead_on_unwind writable sret(%struct.B) align 4 %{{[0-9a-z]+}}, ptr nest noundef @f2) + // CHECK64: call void @f2(ptr dead_on_unwind writable sret(%struct.B) align 8 %{{[0-9a-z]+}}, ptr nest noundef @f2) __builtin_call_with_static_chain(f2(), f2); // CHECK32: call i64 @f3(ptr nest noundef @f3) diff --git a/clang/test/CodeGenCXX/conditional-gnu-ext.cpp b/clang/test/CodeGenCXX/conditional-gnu-ext.cpp index b17e0f7bb9a222f6e9241206e534b3b2c99774a4..3d3d210f22f6935ea312c1a6f8c70a89701edfa2 100644 --- a/clang/test/CodeGenCXX/conditional-gnu-ext.cpp +++ b/clang/test/CodeGenCXX/conditional-gnu-ext.cpp @@ -94,7 +94,7 @@ namespace test3 { B test1() { // CHECK-LABEL: define{{.*}} void @_ZN5test35test1Ev( // CHECK: [[TEMP:%.*]] = alloca [[B:%.*]], - // CHECK: call void @_ZN5test312test1_helperEv(ptr sret([[B]]) align 1 [[TEMP]]) + // CHECK: call void @_ZN5test312test1_helperEv(ptr dead_on_unwind writable sret([[B]]) align 1 [[TEMP]]) // CHECK-NEXT: [[BOOL:%.*]] = call noundef zeroext i1 @_ZN5test31BcvbEv(ptr {{[^,]*}} [[TEMP]]) // CHECK-NEXT: br i1 [[BOOL]] // CHECK: call void @_ZN5test31BC1ERKS0_(ptr {{[^,]*}} [[RESULT:%.*]], ptr noundef nonnull align {{[0-9]+}} dereferenceable({{[0-9]+}}) [[TEMP]]) @@ -117,7 +117,7 @@ namespace test3 { // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[X]] // CHECK-NEXT: [[BOOL:%.*]] = call noundef zeroext i1 @_ZN5test31BcvbEv(ptr {{[^,]*}} [[T0]]) // CHECK-NEXT: br i1 [[BOOL]] - // CHECK: call void @_ZN5test31BcvNS_1AEEv(ptr sret([[A:%.*]]) align 1 [[RESULT:%.*]], ptr {{[^,]*}} [[T0]]) + // CHECK: call void @_ZN5test31BcvNS_1AEEv(ptr dead_on_unwind writable sret([[A:%.*]]) align 1 [[RESULT:%.*]], ptr {{[^,]*}} [[T0]]) // CHECK-NEXT: br label // CHECK: call void @_ZN5test31AC1Ev(ptr {{[^,]*}} [[RESULT]]) // CHECK-NEXT: br label @@ -128,10 +128,10 @@ namespace test3 { A test3() { // CHECK-LABEL: define{{.*}} void @_ZN5test35test3Ev( // CHECK: [[TEMP:%.*]] = alloca [[B]], - // CHECK: call void @_ZN5test312test3_helperEv(ptr sret([[B]]) align 1 [[TEMP]]) + // CHECK: call void @_ZN5test312test3_helperEv(ptr dead_on_unwind writable sret([[B]]) align 1 [[TEMP]]) // CHECK-NEXT: [[BOOL:%.*]] = call noundef zeroext i1 @_ZN5test31BcvbEv(ptr {{[^,]*}} [[TEMP]]) // CHECK-NEXT: br i1 [[BOOL]] - // CHECK: call void @_ZN5test31BcvNS_1AEEv(ptr sret([[A]]) align 1 [[RESULT:%.*]], ptr {{[^,]*}} [[TEMP]]) + // CHECK: call void @_ZN5test31BcvNS_1AEEv(ptr dead_on_unwind writable sret([[A]]) align 1 [[RESULT:%.*]], ptr {{[^,]*}} [[TEMP]]) // CHECK-NEXT: br label // CHECK: call void @_ZN5test31AC1Ev(ptr {{[^,]*}} [[RESULT]]) // CHECK-NEXT: br label diff --git a/clang/test/CodeGenCXX/cxx1z-copy-omission.cpp b/clang/test/CodeGenCXX/cxx1z-copy-omission.cpp index db6671bcd301b84484dd92265d186d13d96f2c16..e64d163fd3d6c80df0252be8a6bf5b99e3b89ae7 100644 --- a/clang/test/CodeGenCXX/cxx1z-copy-omission.cpp +++ b/clang/test/CodeGenCXX/cxx1z-copy-omission.cpp @@ -19,7 +19,7 @@ void g() { // CHECK: %[[A:.*]] = alloca // CHECK-NOT: alloca // CHECK-NOT: call - // CHECK: call {{.*}} @_Z1fv(ptr sret({{.*}}) align 4 %[[A]]) + // CHECK: call {{.*}} @_Z1fv(ptr dead_on_unwind writable sret({{.*}}) align 4 %[[A]]) A a = A( A{ f() } ); // CHECK-NOT: call @@ -40,7 +40,7 @@ void h() { // CHECK-NOT: alloca // CHECK-NOT: call - // CHECK: call {{.*}} @_Z1fv(ptr sret({{.*}}) align 4 %[[A]]) + // CHECK: call {{.*}} @_Z1fv(ptr dead_on_unwind writable sret({{.*}}) align 4 %[[A]]) // CHECK-NOT: call // CHECK: call {{.*}} @_Z1f1A(ptr noundef %[[A]]) f(f()); diff --git a/clang/test/CodeGenCXX/cxx1z-lambda-star-this.cpp b/clang/test/CodeGenCXX/cxx1z-lambda-star-this.cpp index 63bfe5603b694c15366f46373c9fef5bee476edd..1388f1b87889a70028522ac43d1064f3e72a0142 100644 --- a/clang/test/CodeGenCXX/cxx1z-lambda-star-this.cpp +++ b/clang/test/CodeGenCXX/cxx1z-lambda-star-this.cpp @@ -10,7 +10,7 @@ namespace ns1 { int X = A{}.foo()(); } //end ns1 -//CHECK: @"?foo@A@@QAE?A?@@XZ"(ptr {{[^,]*}} %this, ptr noalias sret(%class.anon) align 8 %[[A_LAMBDA_RETVAL:.*]]) +//CHECK: @"?foo@A@@QAE?A?@@XZ"(ptr {{[^,]*}} %this, ptr dead_on_unwind noalias writable sret(%class.anon) align 8 %[[A_LAMBDA_RETVAL:.*]]) // get the first object with the closure type, which is of type 'struct.A' //CHECK: %[[I0:.+]] = getelementptr inbounds %[[A_LAMBDA]], ptr %[[A_LAMBDA_RETVAL]], i32 0, i32 0 // copy the contents ... @@ -24,6 +24,6 @@ struct B { namespace ns2 { int X = B{}.bar()(); } -//CHECK: @"?bar@B@@QAE?A?@@XZ"(ptr {{[^,]*}} %this, ptr noalias sret(%class.anon.0) align 4 %agg.result) +//CHECK: @"?bar@B@@QAE?A?@@XZ"(ptr {{[^,]*}} %this, ptr dead_on_unwind noalias writable sret(%class.anon.0) align 4 %agg.result) //CHECK: %[[I20:.+]] = getelementptr inbounds %class.anon.0, ptr %agg.result, i32 0, i32 0 //CHECK: store ptr %this1, ptr %[[I20]], align 4 diff --git a/clang/test/CodeGenCXX/debug-info-access.cpp b/clang/test/CodeGenCXX/debug-info-access.cpp index 9f2c044843d0f0f4e98a885de30bad50226a7240..7c0bf8ccb038428f37e20254d5dcb43a77ee0742 100644 --- a/clang/test/CodeGenCXX/debug-info-access.cpp +++ b/clang/test/CodeGenCXX/debug-info-access.cpp @@ -18,9 +18,9 @@ public: static int public_static; protected: + // CHECK-DAG: !DIDerivedType(tag: DW_TAG_typedef, name: "prot_using",{{.*}} line: [[@LINE+3]],{{.*}} flags: DIFlagProtected) // CHECK-DAG: !DIDerivedType(tag: DW_TAG_typedef, name: "prot_typedef",{{.*}} line: [[@LINE+1]],{{.*}} flags: DIFlagProtected) typedef int prot_typedef; - // CHECK-DAG: !DIDerivedType(tag: DW_TAG_typedef, name: "prot_using",{{.*}} line: [[@LINE+1]],{{.*}} flags: DIFlagProtected) using prot_using = prot_typedef; prot_using prot_member; diff --git a/clang/test/CodeGenCXX/debug-info-anon-union-vars.cpp b/clang/test/CodeGenCXX/debug-info-anon-union-vars.cpp index 61b3c7c0526c8ef2da867889c734c543aeb17554..c91cf83c0405fecf31a4e0ef886ac3f745642e7a 100644 --- a/clang/test/CodeGenCXX/debug-info-anon-union-vars.cpp +++ b/clang/test/CodeGenCXX/debug-info-anon-union-vars.cpp @@ -51,13 +51,13 @@ void instantiate(int x) { // CHECK: !DIGlobalVariable(name: "b",{{.*}} file: [[FILE]], line: 6,{{.*}} isLocal: true, isDefinition: true // CHECK: !DIGlobalVariable(name: "result", {{.*}} isLocal: false, isDefinition: true // CHECK: !DIGlobalVariable(name: "value", {{.*}} isLocal: false, isDefinition: true -// CHECK: !DILocalVariable(name: "i", {{.*}}, flags: DIFlagArtificial -// CHECK: !DILocalVariable(name: "c", {{.*}}, flags: DIFlagArtificial -// CHECK: !DILocalVariable( -// CHECK-NOT: name: -// CHECK: type: ![[UNION:[0-9]+]] -// CHECK: ![[UNION]] = distinct !DICompositeType(tag: DW_TAG_union_type, +// CHECK: ![[UNION:[0-9]+]] = distinct !DICompositeType(tag: DW_TAG_union_type, // CHECK-NOT: name: // CHECK: elements // CHECK: !DIDerivedType(tag: DW_TAG_member, name: "i", scope: ![[UNION]], // CHECK: !DIDerivedType(tag: DW_TAG_member, name: "c", scope: ![[UNION]], +// CHECK: !DILocalVariable(name: "i", {{.*}}, flags: DIFlagArtificial +// CHECK: !DILocalVariable(name: "c", {{.*}}, flags: DIFlagArtificial +// CHECK: !DILocalVariable( +// CHECK-NOT: name: +// CHECK: type: ![[UNION]] diff --git a/clang/test/CodeGenCXX/debug-info-codeview-unnamed.cpp b/clang/test/CodeGenCXX/debug-info-codeview-unnamed.cpp index b4c79936ab33e64216d7b977174ef01d93754c35..9602ac1b024973012c29d2783bab94b277a3fd7a 100644 --- a/clang/test/CodeGenCXX/debug-info-codeview-unnamed.cpp +++ b/clang/test/CodeGenCXX/debug-info-codeview-unnamed.cpp @@ -3,6 +3,60 @@ int main(int argc, char* argv[], char* arge[]) { // + // LINUX: [[TYPE_OF_ONE:![0-9]+]] = distinct !DICompositeType( + // LINUX-SAME: tag: DW_TAG_structure_type + // LINUX-NOT: name: + // LINUX-NOT: identifier: + // LINUX-SAME: ) + // + // MSVC: [[TYPE_OF_ONE:![0-9]+]] = distinct !DICompositeType + // MSVC-SAME: tag: DW_TAG_structure_type + // MSVC-SAME: name: "" + // MSVC-SAME: identifier: ".?AU@?1??main@@9@" + // MSVC-SAME: ) + + + // + // LINUX: [[TYPE_OF_TWO:![0-9]+]] = distinct !DICompositeType( + // LINUX-SAME: tag: DW_TAG_structure_type + // LINUX-NOT: name: + // LINUX-NOT: identifier: + // LINUX-SAME: ) + // + // MSVC: [[TYPE_OF_TWO:![0-9]+]] = distinct !DICompositeType + // MSVC-SAME: tag: DW_TAG_structure_type + // MSVC-SAME: name: "" + // MSVC-SAME: identifier: ".?AU@?2??main@@9@" + // MSVC-SAME: ) + + + // + // LINUX: [[TYPE_OF_THREE:![0-9]+]] = distinct !DICompositeType( + // LINUX-SAME: tag: DW_TAG_structure_type + // LINUX-SAME: name: "named" + // LINUX-NOT: identifier: + // LINUX-SAME: ) + // + // MSVC: [[TYPE_OF_THREE:![0-9]+]] = distinct !DICompositeType + // MSVC-SAME: tag: DW_TAG_structure_type + // MSVC-SAME: name: "named" + // MSVC-SAME: identifier: ".?AUnamed@?1??main@@9@" + // MSVC-SAME: ) + + // + // LINUX: [[TYPE_OF_FOUR:![0-9]+]] = distinct !DICompositeType( + // LINUX-SAME: tag: DW_TAG_class_type + // LINUX-NOT: name: + // LINUX-NOT: identifier: + // LINUX-SAME: ) + // + // MSVC: [[TYPE_OF_FOUR:![0-9]+]] = distinct !DICompositeType + // MSVC-SAME: tag: DW_TAG_class_type + // MSVC-SAME: name: "" + // MSVC-SAME: identifier: ".?AV@?0??main@@9@" + // MSVC-SAME: ) + + // In CodeView, the LF_MFUNCTION entry for "bar()" refers to the forward // reference of the unnamed struct. Visual Studio requires a unique // identifier to match the LF_STRUCTURE forward reference to the definition. @@ -10,21 +64,11 @@ int main(int argc, char* argv[], char* arge[]) { struct { void bar() {} } one; // // LINUX: !{{[0-9]+}} = !DILocalVariable(name: "one" - // LINUX-SAME: type: [[TYPE_OF_ONE:![0-9]+]] - // LINUX-SAME: ) - // LINUX: [[TYPE_OF_ONE]] = distinct !DICompositeType( - // LINUX-SAME: tag: DW_TAG_structure_type - // LINUX-NOT: name: - // LINUX-NOT: identifier: + // LINUX-SAME: type: [[TYPE_OF_ONE]] // LINUX-SAME: ) // // MSVC: !{{[0-9]+}} = !DILocalVariable(name: "one" - // MSVC-SAME: type: [[TYPE_OF_ONE:![0-9]+]] - // MSVC-SAME: ) - // MSVC: [[TYPE_OF_ONE]] = distinct !DICompositeType - // MSVC-SAME: tag: DW_TAG_structure_type - // MSVC-SAME: name: "" - // MSVC-SAME: identifier: ".?AU@?1??main@@9@" + // MSVC-SAME: type: [[TYPE_OF_ONE]] // MSVC-SAME: ) @@ -36,21 +80,11 @@ int main(int argc, char* argv[], char* arge[]) { int decltype(two)::*ptr2unnamed = &decltype(two)::bar; // // LINUX: !{{[0-9]+}} = !DILocalVariable(name: "two" - // LINUX-SAME: type: [[TYPE_OF_TWO:![0-9]+]] - // LINUX-SAME: ) - // LINUX: [[TYPE_OF_TWO]] = distinct !DICompositeType( - // LINUX-SAME: tag: DW_TAG_structure_type - // LINUX-NOT: name: - // LINUX-NOT: identifier: + // LINUX-SAME: type: [[TYPE_OF_TWO]] // LINUX-SAME: ) // // MSVC: !{{[0-9]+}} = !DILocalVariable(name: "two" - // MSVC-SAME: type: [[TYPE_OF_TWO:![0-9]+]] - // MSVC-SAME: ) - // MSVC: [[TYPE_OF_TWO]] = distinct !DICompositeType - // MSVC-SAME: tag: DW_TAG_structure_type - // MSVC-SAME: name: "" - // MSVC-SAME: identifier: ".?AU@?2??main@@9@" + // MSVC-SAME: type: [[TYPE_OF_TWO]] // MSVC-SAME: ) @@ -61,21 +95,11 @@ int main(int argc, char* argv[], char* arge[]) { struct named { int bar; int named::* p2mem; } three = { 42, &named::bar }; // // LINUX: !{{[0-9]+}} = !DILocalVariable(name: "three" - // LINUX-SAME: type: [[TYPE_OF_THREE:![0-9]+]] - // LINUX-SAME: ) - // LINUX: [[TYPE_OF_THREE]] = distinct !DICompositeType( - // LINUX-SAME: tag: DW_TAG_structure_type - // LINUX-SAME: name: "named" - // LINUX-NOT: identifier: + // LINUX-SAME: type: [[TYPE_OF_THREE]] // LINUX-SAME: ) // // MSVC: !{{[0-9]+}} = !DILocalVariable(name: "three" - // MSVC-SAME: type: [[TYPE_OF_THREE:![0-9]+]] - // MSVC-SAME: ) - // MSVC: [[TYPE_OF_THREE]] = distinct !DICompositeType - // MSVC-SAME: tag: DW_TAG_structure_type - // MSVC-SAME: name: "named" - // MSVC-SAME: identifier: ".?AUnamed@?1??main@@9@" + // MSVC-SAME: type: [[TYPE_OF_THREE]] // MSVC-SAME: ) @@ -87,21 +111,11 @@ int main(int argc, char* argv[], char* arge[]) { auto four = [argc](int i) -> int { return argc == i ? 1 : 0; }; // // LINUX: !{{[0-9]+}} = !DILocalVariable(name: "four" - // LINUX-SAME: type: [[TYPE_OF_FOUR:![0-9]+]] - // LINUX-SAME: ) - // LINUX: [[TYPE_OF_FOUR]] = distinct !DICompositeType( - // LINUX-SAME: tag: DW_TAG_class_type - // LINUX-NOT: name: - // LINUX-NOT: identifier: + // LINUX-SAME: type: [[TYPE_OF_FOUR]] // LINUX-SAME: ) // // MSVC: !{{[0-9]+}} = !DILocalVariable(name: "four" - // MSVC-SAME: type: [[TYPE_OF_FOUR:![0-9]+]] - // MSVC-SAME: ) - // MSVC: [[TYPE_OF_FOUR]] = distinct !DICompositeType - // MSVC-SAME: tag: DW_TAG_class_type - // MSVC-SAME: name: "" - // MSVC-SAME: identifier: ".?AV@?0??main@@9@" + // MSVC-SAME: type: [[TYPE_OF_FOUR]] // MSVC-SAME: ) return 0; diff --git a/clang/test/CodeGenCXX/debug-info-gline-tables-only-codeview.cpp b/clang/test/CodeGenCXX/debug-info-gline-tables-only-codeview.cpp index 6b9c9a243decd1ee68b6b0b4b15f459ddd49469a..122e4aa62ea7dfcd34654064d666403a2ea2f1cb 100644 --- a/clang/test/CodeGenCXX/debug-info-gline-tables-only-codeview.cpp +++ b/clang/test/CodeGenCXX/debug-info-gline-tables-only-codeview.cpp @@ -51,9 +51,9 @@ void test() { // CHECK-SAME: name: "", c.lambda_params(); - // CHECK: !DISubprogram(name: "operator()", scope: ![[LAMBDA1:[0-9]+]], - // CHECK: ![[LAMBDA1]] = !DICompositeType(tag: DW_TAG_class_type, + // CHECK: ![[LAMBDA1:[0-9]+]] = !DICompositeType(tag: DW_TAG_class_type, // CHECK-SAME: name: "", // CHECK-SAME: flags: DIFlagFwdDecl + // CHECK: !DISubprogram(name: "operator()", scope: ![[LAMBDA1]], c.lambda2(); } diff --git a/clang/test/CodeGenCXX/debug-lambda-this.cpp b/clang/test/CodeGenCXX/debug-lambda-this.cpp index eecbac6520ac97d4d39d480fc83e0a20d0ae12a0..3d659e7bfd004a1815d65ff4ed51bb5eae04c8a5 100644 --- a/clang/test/CodeGenCXX/debug-lambda-this.cpp +++ b/clang/test/CodeGenCXX/debug-lambda-this.cpp @@ -13,10 +13,10 @@ int D::d(int x) { } // CHECK: ![[D:[0-9]+]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "D", -// CHECK: ![[POINTER:.*]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[D]], size: 64) // CHECK: !DIDerivedType(tag: DW_TAG_member, name: "this", // CHECK-SAME: line: 11 -// CHECK-SAME: baseType: ![[POINTER]] +// CHECK-SAME: baseType: ![[POINTER:[0-9]+]] // CHECK-SAME: size: 64 // CHECK-NOT: offset: 0 // CHECK-SAME: ){{$}} +// CHECK: ![[POINTER]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[D]], size: 64) diff --git a/clang/test/CodeGenCXX/exceptions.cpp b/clang/test/CodeGenCXX/exceptions.cpp index 483876cc212e3010e2b4ab8df0e431f5b7c691a6..e8179f9828fb6bea946523b320bc5c9624edaf6d 100644 --- a/clang/test/CodeGenCXX/exceptions.cpp +++ b/clang/test/CodeGenCXX/exceptions.cpp @@ -142,12 +142,12 @@ namespace test1 { // CHECK: [[ACTIVE:%.*]] = alloca i1 // CHECK: [[NEW:%.*]] = call noalias nonnull ptr @_Znwm(i64 8) // CHECK-NEXT: store i1 true, ptr [[ACTIVE]] - // CHECK-NEXT: invoke void @_ZN5test15makeBEv(ptr sret([[B:%.*]]) align 4 [[T0:%.*]]) + // CHECK-NEXT: invoke void @_ZN5test15makeBEv(ptr dead_on_unwind writable sret([[B:%.*]]) align 4 [[T0:%.*]]) // CHECK: [[T1:%.*]] = invoke i32 @_ZN5test11BcviEv(ptr {{[^,]*}} [[T0]]) // CHECK: invoke void @_ZN5test11AC1Ei(ptr {{[^,]*}} [[NEW]], i32 [[T1]]) // CHECK: store i1 false, ptr [[ACTIVE]] // CHECK-NEXT: store ptr [[NEW]], ptr [[X]], align 8 - // CHECK: invoke void @_ZN5test15makeBEv(ptr sret([[B:%.*]]) align 4 [[T2:%.*]]) + // CHECK: invoke void @_ZN5test15makeBEv(ptr dead_on_unwind writable sret([[B:%.*]]) align 4 [[T2:%.*]]) // CHECK: [[RET:%.*]] = load ptr, ptr [[X]], align 8 // CHECK98: invoke void @_ZN5test11BD1Ev(ptr {{[^,]*}} [[T2]]) @@ -231,7 +231,7 @@ namespace test3 { // CHECK-NEXT: store ptr [[NEW]], ptr [[SAVED0]] // CHECK-NEXT: store ptr [[FOO]], ptr [[SAVED1]] // CHECK-NEXT: store i1 true, ptr [[CLEANUPACTIVE]] - // CHECK-NEXT: invoke void @_ZN5test35makeAEv(ptr sret([[A:%.*]]) align 8 [[NEW]]) + // CHECK-NEXT: invoke void @_ZN5test35makeAEv(ptr dead_on_unwind writable sret([[A:%.*]]) align 8 [[NEW]]) // CHECK: br label // -> cond.end new(foo(),10.0) A(makeA()) : diff --git a/clang/test/CodeGenCXX/homogeneous-aggregates.cpp b/clang/test/CodeGenCXX/homogeneous-aggregates.cpp index bd83b9f932aad43f6dd6bcfa8d67a4d5b0bcc2e7..63ffc6b5bfac84cc58141984badf5e5dba96cf96 100644 --- a/clang/test/CodeGenCXX/homogeneous-aggregates.cpp +++ b/clang/test/CodeGenCXX/homogeneous-aggregates.cpp @@ -39,10 +39,10 @@ struct I2 : Base2 {}; struct I3 : Base2 {}; struct D5 : I1, I2, I3 {}; // homogeneous aggregate -// PPC: define{{.*}} void @_Z7func_D12D1(ptr noalias sret(%struct.D1) align 8 %agg.result, [3 x i64] %x.coerce) -// ARM32: define{{.*}} arm_aapcs_vfpcc void @_Z7func_D12D1(ptr noalias sret(%struct.D1) align 8 %agg.result, [3 x i64] %x.coerce) -// ARM64: define{{.*}} void @_Z7func_D12D1(ptr noalias sret(%struct.D1) align 8 %agg.result, ptr noundef %x) -// X64: define dso_local x86_vectorcallcc void @"\01_Z7func_D12D1@@24"(ptr noalias sret(%struct.D1) align 8 %agg.result, ptr noundef %x) +// PPC: define{{.*}} void @_Z7func_D12D1(ptr dead_on_unwind noalias writable sret(%struct.D1) align 8 %agg.result, [3 x i64] %x.coerce) +// ARM32: define{{.*}} arm_aapcs_vfpcc void @_Z7func_D12D1(ptr dead_on_unwind noalias writable sret(%struct.D1) align 8 %agg.result, [3 x i64] %x.coerce) +// ARM64: define{{.*}} void @_Z7func_D12D1(ptr dead_on_unwind noalias writable sret(%struct.D1) align 8 %agg.result, ptr noundef %x) +// X64: define dso_local x86_vectorcallcc void @"\01_Z7func_D12D1@@24"(ptr dead_on_unwind noalias writable sret(%struct.D1) align 8 %agg.result, ptr noundef %x) D1 CC func_D1(D1 x) { return x; } // PPC: define{{.*}} [3 x double] @_Z7func_D22D2([3 x double] %x.coerce) @@ -51,9 +51,9 @@ D1 CC func_D1(D1 x) { return x; } // X64: define dso_local x86_vectorcallcc %struct.D2 @"\01_Z7func_D22D2@@24"(%struct.D2 inreg %x.coerce) D2 CC func_D2(D2 x) { return x; } -// PPC: define{{.*}} void @_Z7func_D32D3(ptr noalias sret(%struct.D3) align 8 %agg.result, [4 x i64] %x.coerce) -// ARM32: define{{.*}} arm_aapcs_vfpcc void @_Z7func_D32D3(ptr noalias sret(%struct.D3) align 8 %agg.result, [4 x i64] %x.coerce) -// ARM64: define{{.*}} void @_Z7func_D32D3(ptr noalias sret(%struct.D3) align 8 %agg.result, ptr noundef %x) +// PPC: define{{.*}} void @_Z7func_D32D3(ptr dead_on_unwind noalias writable sret(%struct.D3) align 8 %agg.result, [4 x i64] %x.coerce) +// ARM32: define{{.*}} arm_aapcs_vfpcc void @_Z7func_D32D3(ptr dead_on_unwind noalias writable sret(%struct.D3) align 8 %agg.result, [4 x i64] %x.coerce) +// ARM64: define{{.*}} void @_Z7func_D32D3(ptr dead_on_unwind noalias writable sret(%struct.D3) align 8 %agg.result, ptr noundef %x) D3 CC func_D3(D3 x) { return x; } // PPC: define{{.*}} [4 x double] @_Z7func_D42D4([4 x double] %x.coerce) @@ -133,13 +133,13 @@ struct HasEmptyBase : public Empty { struct HasPodBase : public Pod {}; // WOA64-LABEL: define dso_local %"struct.pr47611::Pod" @"?copy@pr47611@@YA?AUPod@1@PEAU21@@Z"(ptr noundef %x) Pod copy(Pod *x) { return *x; } // MSVC: ldp d0,d1,[x0], Clang: ldp d0,d1,[x0] -// WOA64-LABEL: define dso_local void @"?copy@pr47611@@YA?AUNotCXX14Aggregate@1@PEAU21@@Z"(ptr inreg noalias sret(%"struct.pr47611::NotCXX14Aggregate") align 8 %agg.result, ptr noundef %x) +// WOA64-LABEL: define dso_local void @"?copy@pr47611@@YA?AUNotCXX14Aggregate@1@PEAU21@@Z"(ptr dead_on_unwind inreg noalias writable sret(%"struct.pr47611::NotCXX14Aggregate") align 8 %agg.result, ptr noundef %x) NotCXX14Aggregate copy(NotCXX14Aggregate *x) { return *x; } // MSVC: stp x8,x9,[x0], Clang: str q0,[x0] // WOA64-LABEL: define dso_local [2 x i64] @"?copy@pr47611@@YA?AUNotPod@1@PEAU21@@Z"(ptr noundef %x) NotPod copy(NotPod *x) { return *x; } -// WOA64-LABEL: define dso_local void @"?copy@pr47611@@YA?AUHasEmptyBase@1@PEAU21@@Z"(ptr inreg noalias sret(%"struct.pr47611::HasEmptyBase") align 8 %agg.result, ptr noundef %x) +// WOA64-LABEL: define dso_local void @"?copy@pr47611@@YA?AUHasEmptyBase@1@PEAU21@@Z"(ptr dead_on_unwind inreg noalias writable sret(%"struct.pr47611::HasEmptyBase") align 8 %agg.result, ptr noundef %x) HasEmptyBase copy(HasEmptyBase *x) { return *x; } -// WOA64-LABEL: define dso_local void @"?copy@pr47611@@YA?AUHasPodBase@1@PEAU21@@Z"(ptr inreg noalias sret(%"struct.pr47611::HasPodBase") align 8 %agg.result, ptr noundef %x) +// WOA64-LABEL: define dso_local void @"?copy@pr47611@@YA?AUHasPodBase@1@PEAU21@@Z"(ptr dead_on_unwind inreg noalias writable sret(%"struct.pr47611::HasPodBase") align 8 %agg.result, ptr noundef %x) HasPodBase copy(HasPodBase *x) { return *x; } void call_copy_pod(Pod *pod) { @@ -151,7 +151,7 @@ void call_copy_pod(Pod *pod) { void call_copy_notcxx14aggregate(NotCXX14Aggregate *notcxx14aggregate) { *notcxx14aggregate = copy(notcxx14aggregate); // WOA64-LABEL: define dso_local void @"?call_copy_notcxx14aggregate@pr47611@@YAXPEAUNotCXX14Aggregate@1@@Z" - // WOA64: call void @"?copy@pr47611@@YA?AUNotCXX14Aggregate@1@PEAU21@@Z"(ptr inreg sret(%"struct.pr47611::NotCXX14Aggregate") align 8 %{{.*}}, ptr noundef %{{.*}}) + // WOA64: call void @"?copy@pr47611@@YA?AUNotCXX14Aggregate@1@PEAU21@@Z"(ptr dead_on_unwind inreg writable sret(%"struct.pr47611::NotCXX14Aggregate") align 8 %{{.*}}, ptr noundef %{{.*}}) } void call_copy_notpod(NotPod *notPod) { @@ -163,13 +163,13 @@ void call_copy_notpod(NotPod *notPod) { void call_copy_hasemptybase(HasEmptyBase *hasEmptyBase) { *hasEmptyBase = copy(hasEmptyBase); // WOA64-LABEL: define dso_local void @"?call_copy_hasemptybase@pr47611@@YAXPEAUHasEmptyBase@1@@Z" - // WOA64: call void @"?copy@pr47611@@YA?AUHasEmptyBase@1@PEAU21@@Z"(ptr inreg sret(%"struct.pr47611::HasEmptyBase") align 8 %{{.*}}, ptr noundef %{{.*}}) + // WOA64: call void @"?copy@pr47611@@YA?AUHasEmptyBase@1@PEAU21@@Z"(ptr dead_on_unwind inreg writable sret(%"struct.pr47611::HasEmptyBase") align 8 %{{.*}}, ptr noundef %{{.*}}) } void call_copy_haspodbase(HasPodBase *hasPodBase) { *hasPodBase = copy(hasPodBase); // WOA64-LABEL: define dso_local void @"?call_copy_haspodbase@pr47611@@YAXPEAUHasPodBase@1@@Z" - // WOA64: call void @"?copy@pr47611@@YA?AUHasPodBase@1@PEAU21@@Z"(ptr inreg sret(%"struct.pr47611::HasPodBase") align 8 %{{.*}}, ptr noundef %{{.*}}) + // WOA64: call void @"?copy@pr47611@@YA?AUHasPodBase@1@PEAU21@@Z"(ptr dead_on_unwind inreg writable sret(%"struct.pr47611::HasPodBase") align 8 %{{.*}}, ptr noundef %{{.*}}) } } // namespace pr47611 @@ -300,5 +300,5 @@ test f(test *x) { return *x; } struct base2 { double v; }; struct test2 : base2 { test2(double); protected: double v2;}; test2 f(test2 *x) { return *x; } -// WOA64: define dso_local void @"?f@pr62223@@YA?AUtest2@1@PEAU21@@Z"(ptr inreg noalias sret(%"struct.pr62223::test2") align 8 %{{.*}}, ptr noundef %{{.*}}) +// WOA64: define dso_local void @"?f@pr62223@@YA?AUtest2@1@PEAU21@@Z"(ptr dead_on_unwind inreg noalias writable sret(%"struct.pr62223::test2") align 8 %{{.*}}, ptr noundef %{{.*}}) } diff --git a/clang/test/CodeGenCXX/lambda-expressions.cpp b/clang/test/CodeGenCXX/lambda-expressions.cpp index 3ad982a195cc9610d34ab14279f96fc2ce251b08..b929aa0c675132e76e677fb1d5af6218df4cf402 100644 --- a/clang/test/CodeGenCXX/lambda-expressions.cpp +++ b/clang/test/CodeGenCXX/lambda-expressions.cpp @@ -193,8 +193,8 @@ namespace pr28595 { // CHECK-NEXT: call noundef i32 @"_ZZ1fvENK3$_0clEii" // CHECK-NEXT: ret i32 -// CHECK-LABEL: define internal void @"_ZZ1hvEN3$_08__invokeEv"(ptr noalias sret(%struct.A) align 1 %agg.result) {{.*}} { -// CHECK: call void @"_ZZ1hvENK3$_0clEv"(ptr sret(%struct.A) align 1 %agg.result, +// CHECK-LABEL: define internal void @"_ZZ1hvEN3$_08__invokeEv"(ptr dead_on_unwind noalias writable sret(%struct.A) align 1 %agg.result) {{.*}} { +// CHECK: call void @"_ZZ1hvENK3$_0clEv"(ptr dead_on_unwind writable sret(%struct.A) align 1 %agg.result, // CHECK-NEXT: ret void struct A { ~A(); }; void h() { diff --git a/clang/test/CodeGenCXX/matrix-casts.cpp b/clang/test/CodeGenCXX/matrix-casts.cpp index 4369d99a349158387034bb6a343c0832213105c1..0a946e464adef38f54087509ff0739d247b39d41 100644 --- a/clang/test/CodeGenCXX/matrix-casts.cpp +++ b/clang/test/CodeGenCXX/matrix-casts.cpp @@ -324,7 +324,7 @@ public: }; Foo class_constructor_matrix_ty(matrix_5_5 m) { - // CHECK-LABEL: define void @_Z27class_constructor_matrix_tyu11matrix_typeILm5ELm5EiE(ptr noalias sret(%class.Foo) align 4 %agg.result, <25 x i32> noundef %m) + // CHECK-LABEL: define void @_Z27class_constructor_matrix_tyu11matrix_typeILm5ELm5EiE(ptr dead_on_unwind noalias writable sret(%class.Foo) align 4 %agg.result, <25 x i32> noundef %m) // CHECK: [[M:%.*]] = load <25 x i32>, ptr {{.*}}, align 4 // CHECK-NEXT: call void @_ZN3FooC1Eu11matrix_typeILm5ELm5EiE(ptr noundef nonnull align 4 dereferenceable(40) %agg.result, <25 x i32> noundef [[M]]) // CHECK-NEXT: ret void @@ -338,7 +338,7 @@ struct Bar { }; Bar struct_constructor_matrix_ty(matrix_4_4 m) { - // CHECK-LABEL: define void @_Z28struct_constructor_matrix_tyu11matrix_typeILm4ELm4EfE(ptr noalias sret(%struct.Bar) align 4 %agg.result, <16 x float> noundef %m) + // CHECK-LABEL: define void @_Z28struct_constructor_matrix_tyu11matrix_typeILm4ELm4EfE(ptr dead_on_unwind noalias writable sret(%struct.Bar) align 4 %agg.result, <16 x float> noundef %m) // CHECK: [[M:%.*]] = load <16 x float>, ptr {{.*}}, align 4 // CHECK-NEXT: call void @_ZN3BarC1Eu11matrix_typeILm4ELm4EfE(ptr noundef nonnull align 4 dereferenceable(40) %agg.result, <16 x float> noundef [[M]]) // CHECK-NEXT: ret void diff --git a/clang/test/CodeGenCXX/matrix-type-builtins.cpp b/clang/test/CodeGenCXX/matrix-type-builtins.cpp index 732fe1a18db3b0fd08204bf7e30c2b677d740241..9c334a6858f15113aa8240b240b30084967730ae 100644 --- a/clang/test/CodeGenCXX/matrix-type-builtins.cpp +++ b/clang/test/CodeGenCXX/matrix-type-builtins.cpp @@ -19,7 +19,7 @@ MyMatrix transpose(const MyMatrix &M) { void test_transpose_template1() { // CHECK-LABEL: define{{.*}} void @_Z24test_transpose_template1v() - // CHECK: call void @_Z9transposeIiLj4ELj10EE8MyMatrixIT_XT1_EXT0_EERKS0_IS1_XT0_EXT1_EE(ptr sret(%struct.MyMatrix.0) align 4 %M1_t, ptr noundef nonnull align 4 dereferenceable(160) %M1) + // CHECK: call void @_Z9transposeIiLj4ELj10EE8MyMatrixIT_XT1_EXT0_EERKS0_IS1_XT0_EXT1_EE(ptr dead_on_unwind writable sret(%struct.MyMatrix.0) align 4 %M1_t, ptr noundef nonnull align 4 dereferenceable(160) %M1) // CHECK-LABEL: define linkonce_odr void @_Z9transposeIiLj4ELj10EE8MyMatrixIT_XT1_EXT0_EERKS0_IS1_XT0_EXT1_EE( // CHECK: [[M:%.*]] = load <40 x i32>, ptr {{.*}}, align 4 @@ -31,9 +31,9 @@ void test_transpose_template1() { void test_transpose_template2(MyMatrix &M) { // CHECK-LABEL: define{{.*}} void @_Z24test_transpose_template2R8MyMatrixIdLj7ELj6EE( - // CHECK: call void @_Z9transposeIdLj7ELj6EE8MyMatrixIT_XT1_EXT0_EERKS0_IS1_XT0_EXT1_EE(ptr sret(%struct.MyMatrix.1) align 8 %ref.tmp1, ptr noundef nonnull align 8 dereferenceable(336) %0) - // CHECK-NEXT: call void @_Z9transposeIdLj6ELj7EE8MyMatrixIT_XT1_EXT0_EERKS0_IS1_XT0_EXT1_EE(ptr sret(%struct.MyMatrix.2) align 8 %ref.tmp, ptr noundef nonnull align 8 dereferenceable(336) %ref.tmp1) - // CHECK-NEXT: call void @_Z9transposeIdLj7ELj6EE8MyMatrixIT_XT1_EXT0_EERKS0_IS1_XT0_EXT1_EE(ptr sret(%struct.MyMatrix.1) align 8 %M2_t, ptr noundef nonnull align 8 dereferenceable(336) %ref.tmp) + // CHECK: call void @_Z9transposeIdLj7ELj6EE8MyMatrixIT_XT1_EXT0_EERKS0_IS1_XT0_EXT1_EE(ptr dead_on_unwind writable sret(%struct.MyMatrix.1) align 8 %ref.tmp1, ptr noundef nonnull align 8 dereferenceable(336) %0) + // CHECK-NEXT: call void @_Z9transposeIdLj6ELj7EE8MyMatrixIT_XT1_EXT0_EERKS0_IS1_XT0_EXT1_EE(ptr dead_on_unwind writable sret(%struct.MyMatrix.2) align 8 %ref.tmp, ptr noundef nonnull align 8 dereferenceable(336) %ref.tmp1) + // CHECK-NEXT: call void @_Z9transposeIdLj7ELj6EE8MyMatrixIT_XT1_EXT0_EERKS0_IS1_XT0_EXT1_EE(ptr dead_on_unwind writable sret(%struct.MyMatrix.1) align 8 %M2_t, ptr noundef nonnull align 8 dereferenceable(336) %ref.tmp) // CHECK-LABEL: define linkonce_odr void @_Z9transposeIdLj7ELj6EE8MyMatrixIT_XT1_EXT0_EERKS0_IS1_XT0_EXT1_EE( // CHECK: [[M:%.*]] = load <42 x double>, ptr {{.*}}, align 8 diff --git a/clang/test/CodeGenCXX/matrix-type.cpp b/clang/test/CodeGenCXX/matrix-type.cpp index 79bceabb115f835d5a163682531ffb778cef53ca..d93db29d4d0aa4d9068799ca56aaca2a12ccce5b 100644 --- a/clang/test/CodeGenCXX/matrix-type.cpp +++ b/clang/test/CodeGenCXX/matrix-type.cpp @@ -127,7 +127,7 @@ void matrix_template_reference(MatrixClassTemplate &a, MatrixCla } MatrixClassTemplate matrix_template_reference_caller(float *Data) { - // CHECK-LABEL: define{{.*}} void @_Z32matrix_template_reference_callerPf(ptr noalias sret(%class.MatrixClassTemplate) align 8 %agg.result, ptr %Data + // CHECK-LABEL: define{{.*}} void @_Z32matrix_template_reference_callerPf(ptr dead_on_unwind noalias writable sret(%class.MatrixClassTemplate) align 8 %agg.result, ptr %Data // CHECK-NEXT: entry: // CHECK-NEXT: %Data.addr = alloca ptr, align 8 // CHECK-NEXT: %Arg = alloca %class.MatrixClassTemplate, align 8 diff --git a/clang/test/CodeGenCXX/microsoft-abi-byval-sret.cpp b/clang/test/CodeGenCXX/microsoft-abi-byval-sret.cpp index fde27c6ce85dbcb81d49f5b724954756d80a285a..668a27e9d26231c27fe3559a40cd50843f4bf75a 100644 --- a/clang/test/CodeGenCXX/microsoft-abi-byval-sret.cpp +++ b/clang/test/CodeGenCXX/microsoft-abi-byval-sret.cpp @@ -49,7 +49,7 @@ A B::qux(A x) { } // CHECK-LABEL: define dso_local x86_fastcallcc void @"?qux@B@@QAI?AUA@@U2@@Z" -// CHECK: (ptr inreg noundef %this, ptr inreg noalias sret(%struct.A) align 4 %agg.result, ptr inalloca(<{ %struct.A }>) %0) +// CHECK: (ptr inreg noundef %this, ptr dead_on_unwind inreg noalias writable sret(%struct.A) align 4 %agg.result, ptr inalloca(<{ %struct.A }>) %0) // CHECK: ret void int main() { @@ -67,4 +67,4 @@ int main() { // CHECK: call x86_stdcallcc ptr @"?baz@B@@QAG?AUA@@U2@@Z" // CHECK: (ptr inalloca(<{ ptr, ptr, %struct.A }>) %{{[^,]*}}) // CHECK: call x86_fastcallcc void @"?qux@B@@QAI?AUA@@U2@@Z" -// CHECK: (ptr inreg noundef %{{[^,]*}}, ptr inreg sret(%struct.A) align 4 %{{.*}}, ptr inalloca(<{ %struct.A }>) %{{[^,]*}}) +// CHECK: (ptr inreg noundef %{{[^,]*}}, ptr dead_on_unwind inreg writable sret(%struct.A) align 4 %{{.*}}, ptr inalloca(<{ %struct.A }>) %{{[^,]*}}) diff --git a/clang/test/CodeGenCXX/microsoft-abi-byval-thunks.cpp b/clang/test/CodeGenCXX/microsoft-abi-byval-thunks.cpp index 66ecf500a8693892c66ee49067a0537eb8912548..4c485fc3142abf65138a6f678f8338e1dadf09f6 100644 --- a/clang/test/CodeGenCXX/microsoft-abi-byval-thunks.cpp +++ b/clang/test/CodeGenCXX/microsoft-abi-byval-thunks.cpp @@ -86,10 +86,10 @@ C::C() {} // force emission // CHECK32-NEXT: ret ptr %[[rv]] // CHECK64-LABEL: define linkonce_odr dso_local void @"?foo@C@sret_thunk@@W7EAA?AUAgg@2@U32@@Z" -// CHECK64: (ptr noundef %this, ptr noalias sret(%"struct.sret_thunk::Agg") align 4 %agg.result, ptr noundef %x) +// CHECK64: (ptr noundef %this, ptr dead_on_unwind noalias writable sret(%"struct.sret_thunk::Agg") align 4 %agg.result, ptr noundef %x) // CHECK64: getelementptr i8, ptr %{{.*}}, i32 -8 // CHECK64: call void @"?foo@C@sret_thunk@@UEAA?AUAgg@2@U32@@Z" -// CHECK64: (ptr {{[^,]*}} %{{.*}}, ptr sret(%"struct.sret_thunk::Agg") align 4 %agg.result, ptr noundef %x) +// CHECK64: (ptr {{[^,]*}} %{{.*}}, ptr dead_on_unwind writable sret(%"struct.sret_thunk::Agg") align 4 %agg.result, ptr noundef %x) // CHECK64-NOT: call // CHECK64: ret void } diff --git a/clang/test/CodeGenCXX/microsoft-abi-cdecl-method-sret.cpp b/clang/test/CodeGenCXX/microsoft-abi-cdecl-method-sret.cpp index b4a6ff8e6d0ff6ccfbde4dcf61d4bc9e6b920a38..a1faab25b109c0530a2b0a12e4c3508b620823bb 100644 --- a/clang/test/CodeGenCXX/microsoft-abi-cdecl-method-sret.cpp +++ b/clang/test/CodeGenCXX/microsoft-abi-cdecl-method-sret.cpp @@ -19,9 +19,9 @@ S C::variadic_sret(const char *f, ...) { return S(); } S C::cdecl_sret() { return S(); } S C::byval_and_sret(S a) { return S(); } -// CHECK: define dso_local void @"?variadic_sret@C@@QAA?AUS@@PBDZZ"(ptr {{[^,]*}} %this, ptr noalias sret(%struct.S) align 4 %agg.result, ptr noundef %f, ...) -// CHECK: define dso_local void @"?cdecl_sret@C@@QAA?AUS@@XZ"(ptr {{[^,]*}} %this, ptr noalias sret(%struct.S) align 4 %agg.result) -// CHECK: define dso_local void @"?byval_and_sret@C@@QAA?AUS@@U2@@Z"(ptr {{[^,]*}} %this, ptr noalias sret(%struct.S) align 4 %agg.result, ptr noundef byval(%struct.S) align 4 %a) +// CHECK: define dso_local void @"?variadic_sret@C@@QAA?AUS@@PBDZZ"(ptr {{[^,]*}} %this, ptr dead_on_unwind noalias writable sret(%struct.S) align 4 %agg.result, ptr noundef %f, ...) +// CHECK: define dso_local void @"?cdecl_sret@C@@QAA?AUS@@XZ"(ptr {{[^,]*}} %this, ptr dead_on_unwind noalias writable sret(%struct.S) align 4 %agg.result) +// CHECK: define dso_local void @"?byval_and_sret@C@@QAA?AUS@@U2@@Z"(ptr {{[^,]*}} %this, ptr dead_on_unwind noalias writable sret(%struct.S) align 4 %agg.result, ptr noundef byval(%struct.S) align 4 %a) int main() { C c; @@ -41,4 +41,4 @@ struct A { S A::f(int x) { return S(); } -// CHECK-LABEL: define dso_local x86_fastcallcc void @"?f@A@@QAI?AUS@@H@Z"(ptr inreg noundef nonnull align 1 dereferenceable(1) %this, ptr inreg noalias sret(%struct.S) align 4 %agg.result, i32 noundef %x) +// CHECK-LABEL: define dso_local x86_fastcallcc void @"?f@A@@QAI?AUS@@H@Z"(ptr inreg noundef nonnull align 1 dereferenceable(1) %this, ptr dead_on_unwind inreg noalias writable sret(%struct.S) align 4 %agg.result, i32 noundef %x) diff --git a/clang/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp b/clang/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp index 4bff7ccf8986b5e4b121e931757ca1740bd6cb27..f00cf9076275671b183ae7d3b66f3f8a8c95c317 100644 --- a/clang/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp +++ b/clang/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp @@ -18,9 +18,9 @@ void HasEHCleanup() { // WIN32-LABEL: define dso_local void @"?HasEHCleanup@@YAXXZ"() {{.*}} { // WIN32: %[[base:.*]] = call ptr @llvm.stacksave.p0() // If this call throws, we have to restore the stack. -// WIN32: call void @"?getA@@YA?AUA@@XZ"(ptr sret(%struct.A) align 4 %{{.*}}) +// WIN32: call void @"?getA@@YA?AUA@@XZ"(ptr dead_on_unwind writable sret(%struct.A) align 4 %{{.*}}) // If this call throws, we have to cleanup the first temporary. -// WIN32: invoke void @"?getA@@YA?AUA@@XZ"(ptr sret(%struct.A) align 4 %{{.*}}) +// WIN32: invoke void @"?getA@@YA?AUA@@XZ"(ptr dead_on_unwind writable sret(%struct.A) align 4 %{{.*}}) // If this call throws, we have to cleanup the stacksave. // WIN32: call noundef i32 @"?TakesTwo@@YAHUA@@0@Z" // WIN32: call void @llvm.stackrestore @@ -42,8 +42,8 @@ void HasEHCleanupNoexcept() noexcept { // With exceptions, we need to clean up at least one of these temporaries. // WIN32-LABEL: define dso_local void @"?HasEHCleanupNoexcept@@YAXXZ"() {{.*}} { // WIN32: %[[base:.*]] = call ptr @llvm.stacksave.p0() -// WIN32: invoke void @"?getA@@YA?AUA@@XZ"(ptr sret(%struct.A) align 4 %{{.*}}) -// WIN32: invoke void @"?getA@@YA?AUA@@XZ"(ptr sret(%struct.A) align 4 %{{.*}}) +// WIN32: invoke void @"?getA@@YA?AUA@@XZ"(ptr dead_on_unwind writable sret(%struct.A) align 4 %{{.*}}) +// WIN32: invoke void @"?getA@@YA?AUA@@XZ"(ptr dead_on_unwind writable sret(%struct.A) align 4 %{{.*}}) // WIN32: invoke noundef i32 @"?TakesTwo@@YAHUA@@0@Z" // WIN32: call void @llvm.stackrestore // WIN32: ret void diff --git a/clang/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp b/clang/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp index 9d737e3979ddddbd79faaa4e7337aafce6e59ac6..585167d0a1423734b0bf87997d2868071ae706b0 100644 --- a/clang/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp +++ b/clang/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp @@ -87,58 +87,58 @@ void call_bools_and_chars() { // Returning structs that fit into a register. Small small_return() { return Small(); } -// LINUX-LABEL: define{{.*}} void @_Z12small_returnv(ptr noalias sret(%struct.Small) align 4 %agg.result) +// LINUX-LABEL: define{{.*}} void @_Z12small_returnv(ptr dead_on_unwind noalias writable sret(%struct.Small) align 4 %agg.result) // WIN32: define dso_local i32 @"?small_return@@YA?AUSmall@@XZ"() // WIN64: define dso_local i32 @"?small_return@@YA?AUSmall@@XZ"() // WOA64: define dso_local i32 @"?small_return@@YA?AUSmall@@XZ"() Medium medium_return() { return Medium(); } -// LINUX-LABEL: define{{.*}} void @_Z13medium_returnv(ptr noalias sret(%struct.Medium) align 4 %agg.result) +// LINUX-LABEL: define{{.*}} void @_Z13medium_returnv(ptr dead_on_unwind noalias writable sret(%struct.Medium) align 4 %agg.result) // WIN32: define dso_local i64 @"?medium_return@@YA?AUMedium@@XZ"() // WIN64: define dso_local i64 @"?medium_return@@YA?AUMedium@@XZ"() // WOA64: define dso_local i64 @"?medium_return@@YA?AUMedium@@XZ"() // Returning structs that fit into a register but are not POD. SmallCpp11NotCpp03Pod small_non_pod_return() { return SmallCpp11NotCpp03Pod(); } -// LINUX-LABEL: define{{.*}} void @_Z20small_non_pod_returnv(ptr noalias sret(%struct.SmallCpp11NotCpp03Pod) align 4 %agg.result) -// WIN32: define dso_local void @"?small_non_pod_return@@YA?AUSmallCpp11NotCpp03Pod@@XZ"(ptr noalias sret(%struct.SmallCpp11NotCpp03Pod) align 4 %agg.result) -// WIN64: define dso_local void @"?small_non_pod_return@@YA?AUSmallCpp11NotCpp03Pod@@XZ"(ptr noalias sret(%struct.SmallCpp11NotCpp03Pod) align 4 %agg.result) -// WOA64: define dso_local void @"?small_non_pod_return@@YA?AUSmallCpp11NotCpp03Pod@@XZ"(ptr inreg noalias sret(%struct.SmallCpp11NotCpp03Pod) align 4 %agg.result) +// LINUX-LABEL: define{{.*}} void @_Z20small_non_pod_returnv(ptr dead_on_unwind noalias writable sret(%struct.SmallCpp11NotCpp03Pod) align 4 %agg.result) +// WIN32: define dso_local void @"?small_non_pod_return@@YA?AUSmallCpp11NotCpp03Pod@@XZ"(ptr dead_on_unwind noalias writable sret(%struct.SmallCpp11NotCpp03Pod) align 4 %agg.result) +// WIN64: define dso_local void @"?small_non_pod_return@@YA?AUSmallCpp11NotCpp03Pod@@XZ"(ptr dead_on_unwind noalias writable sret(%struct.SmallCpp11NotCpp03Pod) align 4 %agg.result) +// WOA64: define dso_local void @"?small_non_pod_return@@YA?AUSmallCpp11NotCpp03Pod@@XZ"(ptr dead_on_unwind inreg noalias writable sret(%struct.SmallCpp11NotCpp03Pod) align 4 %agg.result) SmallWithCtor small_with_ctor_return() { return SmallWithCtor(); } -// LINUX-LABEL: define{{.*}} void @_Z22small_with_ctor_returnv(ptr noalias sret(%struct.SmallWithCtor) align 4 %agg.result) -// WIN32: define dso_local void @"?small_with_ctor_return@@YA?AUSmallWithCtor@@XZ"(ptr noalias sret(%struct.SmallWithCtor) align 4 %agg.result) -// WIN64: define dso_local void @"?small_with_ctor_return@@YA?AUSmallWithCtor@@XZ"(ptr noalias sret(%struct.SmallWithCtor) align 4 %agg.result) +// LINUX-LABEL: define{{.*}} void @_Z22small_with_ctor_returnv(ptr dead_on_unwind noalias writable sret(%struct.SmallWithCtor) align 4 %agg.result) +// WIN32: define dso_local void @"?small_with_ctor_return@@YA?AUSmallWithCtor@@XZ"(ptr dead_on_unwind noalias writable sret(%struct.SmallWithCtor) align 4 %agg.result) +// WIN64: define dso_local void @"?small_with_ctor_return@@YA?AUSmallWithCtor@@XZ"(ptr dead_on_unwind noalias writable sret(%struct.SmallWithCtor) align 4 %agg.result) // FIXME: The 'sret' mark here doesn't seem to be enough to convince LLVM to // preserve the hidden sret pointer in R0 across the function. -// WOA: define dso_local arm_aapcs_vfpcc void @"?small_with_ctor_return@@YA?AUSmallWithCtor@@XZ"(ptr noalias sret(%struct.SmallWithCtor) align 4 %agg.result) -// WOA64: define dso_local void @"?small_with_ctor_return@@YA?AUSmallWithCtor@@XZ"(ptr inreg noalias sret(%struct.SmallWithCtor) align 4 %agg.result) +// WOA: define dso_local arm_aapcs_vfpcc void @"?small_with_ctor_return@@YA?AUSmallWithCtor@@XZ"(ptr dead_on_unwind noalias writable sret(%struct.SmallWithCtor) align 4 %agg.result) +// WOA64: define dso_local void @"?small_with_ctor_return@@YA?AUSmallWithCtor@@XZ"(ptr dead_on_unwind inreg noalias writable sret(%struct.SmallWithCtor) align 4 %agg.result) SmallWithDtor small_with_dtor_return() { return SmallWithDtor(); } -// LINUX-LABEL: define{{.*}} void @_Z22small_with_dtor_returnv(ptr noalias sret(%struct.SmallWithDtor) align 4 %agg.result) -// WIN32: define dso_local void @"?small_with_dtor_return@@YA?AUSmallWithDtor@@XZ"(ptr noalias sret(%struct.SmallWithDtor) align 4 %agg.result) -// WIN64: define dso_local void @"?small_with_dtor_return@@YA?AUSmallWithDtor@@XZ"(ptr noalias sret(%struct.SmallWithDtor) align 4 %agg.result) -// WOA64: define dso_local void @"?small_with_dtor_return@@YA?AUSmallWithDtor@@XZ"(ptr inreg noalias sret(%struct.SmallWithDtor) align 4 %agg.result) +// LINUX-LABEL: define{{.*}} void @_Z22small_with_dtor_returnv(ptr dead_on_unwind noalias writable sret(%struct.SmallWithDtor) align 4 %agg.result) +// WIN32: define dso_local void @"?small_with_dtor_return@@YA?AUSmallWithDtor@@XZ"(ptr dead_on_unwind noalias writable sret(%struct.SmallWithDtor) align 4 %agg.result) +// WIN64: define dso_local void @"?small_with_dtor_return@@YA?AUSmallWithDtor@@XZ"(ptr dead_on_unwind noalias writable sret(%struct.SmallWithDtor) align 4 %agg.result) +// WOA64: define dso_local void @"?small_with_dtor_return@@YA?AUSmallWithDtor@@XZ"(ptr dead_on_unwind inreg noalias writable sret(%struct.SmallWithDtor) align 4 %agg.result) SmallWithVftable small_with_vftable_return() { return SmallWithVftable(); } -// LINUX-LABEL: define{{.*}} void @_Z25small_with_vftable_returnv(ptr noalias sret(%struct.SmallWithVftable) align 4 %agg.result) -// WIN32: define dso_local void @"?small_with_vftable_return@@YA?AUSmallWithVftable@@XZ"(ptr noalias sret(%struct.SmallWithVftable) align 4 %agg.result) -// WIN64: define dso_local void @"?small_with_vftable_return@@YA?AUSmallWithVftable@@XZ"(ptr noalias sret(%struct.SmallWithVftable) align 8 %agg.result) -// WOA64: define dso_local void @"?small_with_vftable_return@@YA?AUSmallWithVftable@@XZ"(ptr inreg noalias sret(%struct.SmallWithVftable) align 8 %agg.result) +// LINUX-LABEL: define{{.*}} void @_Z25small_with_vftable_returnv(ptr dead_on_unwind noalias writable sret(%struct.SmallWithVftable) align 4 %agg.result) +// WIN32: define dso_local void @"?small_with_vftable_return@@YA?AUSmallWithVftable@@XZ"(ptr dead_on_unwind noalias writable sret(%struct.SmallWithVftable) align 4 %agg.result) +// WIN64: define dso_local void @"?small_with_vftable_return@@YA?AUSmallWithVftable@@XZ"(ptr dead_on_unwind noalias writable sret(%struct.SmallWithVftable) align 8 %agg.result) +// WOA64: define dso_local void @"?small_with_vftable_return@@YA?AUSmallWithVftable@@XZ"(ptr dead_on_unwind inreg noalias writable sret(%struct.SmallWithVftable) align 8 %agg.result) MediumWithCopyCtor medium_with_copy_ctor_return() { return MediumWithCopyCtor(); } -// LINUX-LABEL: define{{.*}} void @_Z28medium_with_copy_ctor_returnv(ptr noalias sret(%struct.MediumWithCopyCtor) align 4 %agg.result) -// WIN32: define dso_local void @"?medium_with_copy_ctor_return@@YA?AUMediumWithCopyCtor@@XZ"(ptr noalias sret(%struct.MediumWithCopyCtor) align 4 %agg.result) -// WIN64: define dso_local void @"?medium_with_copy_ctor_return@@YA?AUMediumWithCopyCtor@@XZ"(ptr noalias sret(%struct.MediumWithCopyCtor) align 4 %agg.result) -// WOA: define dso_local arm_aapcs_vfpcc void @"?medium_with_copy_ctor_return@@YA?AUMediumWithCopyCtor@@XZ"(ptr noalias sret(%struct.MediumWithCopyCtor) align 4 %agg.result) -// WOA64: define dso_local void @"?medium_with_copy_ctor_return@@YA?AUMediumWithCopyCtor@@XZ"(ptr inreg noalias sret(%struct.MediumWithCopyCtor) align 4 %agg.result) +// LINUX-LABEL: define{{.*}} void @_Z28medium_with_copy_ctor_returnv(ptr dead_on_unwind noalias writable sret(%struct.MediumWithCopyCtor) align 4 %agg.result) +// WIN32: define dso_local void @"?medium_with_copy_ctor_return@@YA?AUMediumWithCopyCtor@@XZ"(ptr dead_on_unwind noalias writable sret(%struct.MediumWithCopyCtor) align 4 %agg.result) +// WIN64: define dso_local void @"?medium_with_copy_ctor_return@@YA?AUMediumWithCopyCtor@@XZ"(ptr dead_on_unwind noalias writable sret(%struct.MediumWithCopyCtor) align 4 %agg.result) +// WOA: define dso_local arm_aapcs_vfpcc void @"?medium_with_copy_ctor_return@@YA?AUMediumWithCopyCtor@@XZ"(ptr dead_on_unwind noalias writable sret(%struct.MediumWithCopyCtor) align 4 %agg.result) +// WOA64: define dso_local void @"?medium_with_copy_ctor_return@@YA?AUMediumWithCopyCtor@@XZ"(ptr dead_on_unwind inreg noalias writable sret(%struct.MediumWithCopyCtor) align 4 %agg.result) // Returning a large struct that doesn't fit into a register. Big big_return() { return Big(); } -// LINUX-LABEL: define{{.*}} void @_Z10big_returnv(ptr noalias sret(%struct.Big) align 4 %agg.result) -// WIN32: define dso_local void @"?big_return@@YA?AUBig@@XZ"(ptr noalias sret(%struct.Big) align 4 %agg.result) -// WIN64: define dso_local void @"?big_return@@YA?AUBig@@XZ"(ptr noalias sret(%struct.Big) align 4 %agg.result) -// WOA64: define dso_local void @"?big_return@@YA?AUBig@@XZ"(ptr noalias sret(%struct.Big) align 4 %agg.result) +// LINUX-LABEL: define{{.*}} void @_Z10big_returnv(ptr dead_on_unwind noalias writable sret(%struct.Big) align 4 %agg.result) +// WIN32: define dso_local void @"?big_return@@YA?AUBig@@XZ"(ptr dead_on_unwind noalias writable sret(%struct.Big) align 4 %agg.result) +// WIN64: define dso_local void @"?big_return@@YA?AUBig@@XZ"(ptr dead_on_unwind noalias writable sret(%struct.Big) align 4 %agg.result) +// WOA64: define dso_local void @"?big_return@@YA?AUBig@@XZ"(ptr dead_on_unwind noalias writable sret(%struct.Big) align 4 %agg.result) void small_arg(Small s) {} @@ -197,7 +197,7 @@ void small_arg_with_dtor(SmallWithDtor s) {} // Test that the eligible non-aggregate is passed directly, but returned // indirectly on ARM64 Windows. -// WOA64: define dso_local void @"?small_arg_with_private_member@@YA?AUSmallWithPrivate@@U1@@Z"(ptr inreg noalias sret(%struct.SmallWithPrivate) align 4 %agg.result, i64 %s.coerce) {{.*}} { +// WOA64: define dso_local void @"?small_arg_with_private_member@@YA?AUSmallWithPrivate@@U1@@Z"(ptr dead_on_unwind inreg noalias writable sret(%struct.SmallWithPrivate) align 4 %agg.result, i64 %s.coerce) {{.*}} { SmallWithPrivate small_arg_with_private_member(SmallWithPrivate s) { return s; } // WOA64: define dso_local i32 @"?small_arg_with_small_struct_with_private_member@@YA?AUSmallWithSmallWithPrivate@@U1@@Z"(i64 %s.coerce) {{.*}} { @@ -301,27 +301,27 @@ void pass_ref_field() { class Class { public: Small thiscall_method_small() { return Small(); } - // LINUX: define {{.*}} void @_ZN5Class21thiscall_method_smallEv(ptr noalias sret(%struct.Small) align 4 %agg.result, ptr {{[^,]*}} %this) - // WIN32: define {{.*}} x86_thiscallcc void @"?thiscall_method_small@Class@@QAE?AUSmall@@XZ"(ptr {{[^,]*}} %this, ptr noalias sret(%struct.Small) align 4 %agg.result) - // WIN64: define linkonce_odr dso_local void @"?thiscall_method_small@Class@@QEAA?AUSmall@@XZ"(ptr {{[^,]*}} %this, ptr noalias sret(%struct.Small) align 4 %agg.result) - // WOA64: define linkonce_odr dso_local void @"?thiscall_method_small@Class@@QEAA?AUSmall@@XZ"(ptr {{[^,]*}} %this, ptr inreg noalias sret(%struct.Small) align 4 %agg.result) + // LINUX: define {{.*}} void @_ZN5Class21thiscall_method_smallEv(ptr dead_on_unwind noalias writable sret(%struct.Small) align 4 %agg.result, ptr {{[^,]*}} %this) + // WIN32: define {{.*}} x86_thiscallcc void @"?thiscall_method_small@Class@@QAE?AUSmall@@XZ"(ptr {{[^,]*}} %this, ptr dead_on_unwind noalias writable sret(%struct.Small) align 4 %agg.result) + // WIN64: define linkonce_odr dso_local void @"?thiscall_method_small@Class@@QEAA?AUSmall@@XZ"(ptr {{[^,]*}} %this, ptr dead_on_unwind noalias writable sret(%struct.Small) align 4 %agg.result) + // WOA64: define linkonce_odr dso_local void @"?thiscall_method_small@Class@@QEAA?AUSmall@@XZ"(ptr {{[^,]*}} %this, ptr dead_on_unwind inreg noalias writable sret(%struct.Small) align 4 %agg.result) SmallWithCtor thiscall_method_small_with_ctor() { return SmallWithCtor(); } - // LINUX: define {{.*}} void @_ZN5Class31thiscall_method_small_with_ctorEv(ptr noalias sret(%struct.SmallWithCtor) align 4 %agg.result, ptr {{[^,]*}} %this) - // WIN32: define {{.*}} x86_thiscallcc void @"?thiscall_method_small_with_ctor@Class@@QAE?AUSmallWithCtor@@XZ"(ptr {{[^,]*}} %this, ptr noalias sret(%struct.SmallWithCtor) align 4 %agg.result) - // WIN64: define linkonce_odr dso_local void @"?thiscall_method_small_with_ctor@Class@@QEAA?AUSmallWithCtor@@XZ"(ptr {{[^,]*}} %this, ptr noalias sret(%struct.SmallWithCtor) align 4 %agg.result) - // WOA64: define linkonce_odr dso_local void @"?thiscall_method_small_with_ctor@Class@@QEAA?AUSmallWithCtor@@XZ"(ptr {{[^,]*}} %this, ptr inreg noalias sret(%struct.SmallWithCtor) align 4 %agg.result) + // LINUX: define {{.*}} void @_ZN5Class31thiscall_method_small_with_ctorEv(ptr dead_on_unwind noalias writable sret(%struct.SmallWithCtor) align 4 %agg.result, ptr {{[^,]*}} %this) + // WIN32: define {{.*}} x86_thiscallcc void @"?thiscall_method_small_with_ctor@Class@@QAE?AUSmallWithCtor@@XZ"(ptr {{[^,]*}} %this, ptr dead_on_unwind noalias writable sret(%struct.SmallWithCtor) align 4 %agg.result) + // WIN64: define linkonce_odr dso_local void @"?thiscall_method_small_with_ctor@Class@@QEAA?AUSmallWithCtor@@XZ"(ptr {{[^,]*}} %this, ptr dead_on_unwind noalias writable sret(%struct.SmallWithCtor) align 4 %agg.result) + // WOA64: define linkonce_odr dso_local void @"?thiscall_method_small_with_ctor@Class@@QEAA?AUSmallWithCtor@@XZ"(ptr {{[^,]*}} %this, ptr dead_on_unwind inreg noalias writable sret(%struct.SmallWithCtor) align 4 %agg.result) Small __cdecl cdecl_method_small() { return Small(); } - // LINUX: define {{.*}} void @_ZN5Class18cdecl_method_smallEv(ptr noalias sret(%struct.Small) align 4 %agg.result, ptr {{[^,]*}} %this) - // WIN32: define {{.*}} void @"?cdecl_method_small@Class@@QAA?AUSmall@@XZ"(ptr {{[^,]*}} %this, ptr noalias sret(%struct.Small) align 4 %agg.result) - // WIN64: define linkonce_odr dso_local void @"?cdecl_method_small@Class@@QEAA?AUSmall@@XZ"(ptr {{[^,]*}} %this, ptr noalias sret(%struct.Small) align 4 %agg.result) + // LINUX: define {{.*}} void @_ZN5Class18cdecl_method_smallEv(ptr dead_on_unwind noalias writable sret(%struct.Small) align 4 %agg.result, ptr {{[^,]*}} %this) + // WIN32: define {{.*}} void @"?cdecl_method_small@Class@@QAA?AUSmall@@XZ"(ptr {{[^,]*}} %this, ptr dead_on_unwind noalias writable sret(%struct.Small) align 4 %agg.result) + // WIN64: define linkonce_odr dso_local void @"?cdecl_method_small@Class@@QEAA?AUSmall@@XZ"(ptr {{[^,]*}} %this, ptr dead_on_unwind noalias writable sret(%struct.Small) align 4 %agg.result) Big __cdecl cdecl_method_big() { return Big(); } - // LINUX: define {{.*}} void @_ZN5Class16cdecl_method_bigEv(ptr noalias sret(%struct.Big) align 4 %agg.result, ptr {{[^,]*}} %this) - // WIN32: define {{.*}} void @"?cdecl_method_big@Class@@QAA?AUBig@@XZ"(ptr {{[^,]*}} %this, ptr noalias sret(%struct.Big) align 4 %agg.result) - // WIN64: define linkonce_odr dso_local void @"?cdecl_method_big@Class@@QEAA?AUBig@@XZ"(ptr {{[^,]*}} %this, ptr noalias sret(%struct.Big) align 4 %agg.result) - // WOA64: define linkonce_odr dso_local void @"?cdecl_method_big@Class@@QEAA?AUBig@@XZ"(ptr {{[^,]*}} %this, ptr inreg noalias sret(%struct.Big) align 4 %agg.result) + // LINUX: define {{.*}} void @_ZN5Class16cdecl_method_bigEv(ptr dead_on_unwind noalias writable sret(%struct.Big) align 4 %agg.result, ptr {{[^,]*}} %this) + // WIN32: define {{.*}} void @"?cdecl_method_big@Class@@QAA?AUBig@@XZ"(ptr {{[^,]*}} %this, ptr dead_on_unwind noalias writable sret(%struct.Big) align 4 %agg.result) + // WIN64: define linkonce_odr dso_local void @"?cdecl_method_big@Class@@QEAA?AUBig@@XZ"(ptr {{[^,]*}} %this, ptr dead_on_unwind noalias writable sret(%struct.Big) align 4 %agg.result) + // WOA64: define linkonce_odr dso_local void @"?cdecl_method_big@Class@@QEAA?AUBig@@XZ"(ptr {{[^,]*}} %this, ptr dead_on_unwind inreg noalias writable sret(%struct.Big) align 4 %agg.result) void thiscall_method_arg(Empty s) {} // LINUX: define {{.*}} void @_ZN5Class19thiscall_method_argE5Empty(ptr {{[^,]*}} %this) diff --git a/clang/test/CodeGenCXX/microsoft-abi-unknown-arch.cpp b/clang/test/CodeGenCXX/microsoft-abi-unknown-arch.cpp index 3045e90777cbc2165258fa3b2a90a40483e3db0a..9e37e71e257fd1ee1af4c813dbddb6444c23ab25 100644 --- a/clang/test/CodeGenCXX/microsoft-abi-unknown-arch.cpp +++ b/clang/test/CodeGenCXX/microsoft-abi-unknown-arch.cpp @@ -18,4 +18,4 @@ A B::foo(A x) { return x; } -// CHECK-LABEL: define{{.*}} void @"?foo@B@@QEAA?AUA@@U2@@Z"(ptr {{[^,]*}} %this, ptr noalias sret(%struct.A) align 4 %agg.result, ptr noundef %x) +// CHECK-LABEL: define{{.*}} void @"?foo@B@@QEAA?AUA@@U2@@Z"(ptr {{[^,]*}} %this, ptr dead_on_unwind noalias writable sret(%struct.A) align 4 %agg.result, ptr noundef %x) diff --git a/clang/test/CodeGenCXX/microsoft-abi-vmemptr-conflicts.cpp b/clang/test/CodeGenCXX/microsoft-abi-vmemptr-conflicts.cpp index 2a29a080d025a54e2d8fd4bc125af44d21cb1cbd..615a2e34d7a2b46b2be28da5fe56fab2e2e97fa8 100644 --- a/clang/test/CodeGenCXX/microsoft-abi-vmemptr-conflicts.cpp +++ b/clang/test/CodeGenCXX/microsoft-abi-vmemptr-conflicts.cpp @@ -65,7 +65,7 @@ void f(C *c) { // CHECK-LABEL: define dso_local void @"?f@sret@@YAXPAUC@1@@Z"(ptr noundef %c) // CHECK: call x86_thiscallcc noundef i32 @"??_9C@sret@@$BA@AE"(ptr {{[^,]*}} %{{.*}}) -// CHECK: call x86_thiscallcc void @"??_9C@sret@@$BA@AE"(ptr {{[^,]*}} %{{.*}}, ptr sret(%"struct.sret::Big") align 4 %{{.*}}) +// CHECK: call x86_thiscallcc void @"??_9C@sret@@$BA@AE"(ptr {{[^,]*}} %{{.*}}, ptr dead_on_unwind writable sret(%"struct.sret::Big") align 4 %{{.*}}) // CHECK-LABEL: define linkonce_odr x86_thiscallcc void @"??_9C@sret@@$BA@AE"(ptr noundef %this, ...) {{.*}} comdat // CHECK: musttail call x86_thiscallcc void (ptr, ...) %{{.*}}(ptr noundef %{{.*}}, ...) diff --git a/clang/test/CodeGenCXX/module-initializer-guard-elision.cpp b/clang/test/CodeGenCXX/module-initializer-guard-elision.cpp index bae7c930b51029ca62c960a78850f320b500a9b5..53e4b909ee2a17b054de4f382d2273b0d66f86b5 100644 --- a/clang/test/CodeGenCXX/module-initializer-guard-elision.cpp +++ b/clang/test/CodeGenCXX/module-initializer-guard-elision.cpp @@ -8,9 +8,9 @@ // RUN: -o - | FileCheck %s --check-prefix=CHECK-O // RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 P.cpp \ -// RUN: -emit-module-interface -fmodule-file=O=O.pcm -o P.pcm +// RUN: -emit-module-interface -fprebuilt-module-path=%t -o P.pcm // RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 P.pcm -S -emit-llvm \ -// RUN: -o - | FileCheck %s --check-prefix=CHECK-P +// RUN: -fprebuilt-module-path=%t -o - | FileCheck %s --check-prefix=CHECK-P // RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 Q.cpp \ // RUN: -emit-module-interface -o Q.pcm @@ -18,24 +18,24 @@ // RUN: -o - | FileCheck %s --check-prefix=CHECK-Q // RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 R.cpp \ -// RUN: -emit-module-interface -fmodule-file=Q=Q.pcm -o R.pcm +// RUN: -emit-module-interface -fprebuilt-module-path=%t -o R.pcm // RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 R.pcm -S -emit-llvm \ -// RUN: -o - | FileCheck %s --check-prefix=CHECK-R +// RUN: -fprebuilt-module-path=%t -o - | FileCheck %s --check-prefix=CHECK-R // RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 S.cpp \ -// RUN: -emit-module-interface -fmodule-file=Q=Q.pcm -fmodule-file=R=R.pcm -o S.pcm +// RUN: -emit-module-interface -fprebuilt-module-path=%t -o S.pcm // RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 S.pcm -S -emit-llvm \ -// RUN: -o - | FileCheck %s --check-prefix=CHECK-S +// RUN: -fprebuilt-module-path=%t -o - | FileCheck %s --check-prefix=CHECK-S // RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 T.cpp \ -// RUN: -emit-module-interface -fmodule-file=S=S.pcm -fmodule-file=R=R.pcm -o T.pcm +// RUN: -emit-module-interface -fprebuilt-module-path=%t -o T.pcm // RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 T.pcm -S -emit-llvm \ -// RUN: -o - | FileCheck %s --check-prefix=CHECK-T +// RUN: -fprebuilt-module-path=%t -o - | FileCheck %s --check-prefix=CHECK-T // RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 U.cpp \ -// RUN: -emit-module-interface -fmodule-file=T=T.pcm -fmodule-file=R=R.pcm -o U.pcm +// RUN: -emit-module-interface -fprebuilt-module-path=%t -o U.pcm // RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 U.pcm -S -emit-llvm \ -// RUN: -o - | FileCheck %s --check-prefix=CHECK-U +// RUN: -fprebuilt-module-path=%t -o - | FileCheck %s --check-prefix=CHECK-U // Testing cases where we can elide the module initializer guard variable. diff --git a/clang/test/CodeGenCXX/module-intializer.cpp b/clang/test/CodeGenCXX/module-intializer.cpp index d365d180ac59d1b4a2927a9848a456991e147df9..8a464ae7403d6696ef163242cb1d87dd16d83aa9 100644 --- a/clang/test/CodeGenCXX/module-intializer.cpp +++ b/clang/test/CodeGenCXX/module-intializer.cpp @@ -12,24 +12,23 @@ // RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 O.pcm -S -emit-llvm \ // RUN: -o - | FileCheck %s --check-prefix=CHECK-O -// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 M-part.cpp \ -// RUN: -emit-module-interface -o M-part.pcm -// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 M-part.pcm -S \ -// RUN: -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-P +// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 M-Part.cpp \ +// RUN: -emit-module-interface -o M-Part.pcm +// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 M-Part.pcm -S \ +// RUN: -emit-module-interface -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-P // RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 M.cpp \ -// RUN: -fmodule-file=N=N.pcm -fmodule-file=O=O.pcm -fmodule-file=M:Part=M-part.pcm \ -// RUN: -emit-module-interface -o M.pcm +// RUN: -fprebuilt-module-path=%t -emit-module-interface -o M.pcm // RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 M.pcm -S -emit-llvm \ -// RUN: -o - | FileCheck %s --check-prefix=CHECK-M +// RUN: -fprebuilt-module-path=%t -o - | FileCheck %s --check-prefix=CHECK-M // RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 useM.cpp \ -// RUN: -fmodule-file=M=M.pcm -S -emit-llvm -o - \ -// RUN: | FileCheck %s --check-prefix=CHECK-USE +// RUN: -fprebuilt-module-path=%t -S -emit-llvm -o - \ +// RUN: | FileCheck %s --check-prefix=CHECK-USE // RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 M-impl.cpp \ -// RUN: -fmodule-file=M=M.pcm -S -emit-llvm -o - \ -// RUN: | FileCheck %s --check-prefix=CHECK-IMPL +// RUN: -fprebuilt-module-path=%t -S -emit-llvm -o - \ +// RUN: | FileCheck %s --check-prefix=CHECK-IMPL // RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 N.cpp -S -emit-llvm \ // RUN: -o - | FileCheck %s --check-prefix=CHECK-N @@ -37,12 +36,11 @@ // RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 O.cpp -S -emit-llvm \ // RUN: -o - | FileCheck %s --check-prefix=CHECK-O -// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 M-part.cpp -S -emit-llvm \ +// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 M-Part.cpp -S -emit-llvm \ // RUN: -o - | FileCheck %s --check-prefix=CHECK-P // RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 M.cpp \ -// RUN: -fmodule-file=N.pcm -fmodule-file=O=O.pcm -fmodule-file=M:Part=M-part.pcm \ -// RUN: -S -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-M +// RUN: -fprebuilt-module-path=%t -S -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-M //--- N-h.h @@ -112,7 +110,7 @@ struct Croak { Croak Frog; -//--- M-part.cpp +//--- M-Part.cpp module; #include "P-h.h" diff --git a/clang/test/CodeGenCXX/ms-thread_local.cpp b/clang/test/CodeGenCXX/ms-thread_local.cpp index a6c62967f23dec7ddf13637c1527f5cc195c2037..cb0e8720c19b8b742634133a5bc290678320b632 100644 --- a/clang/test/CodeGenCXX/ms-thread_local.cpp +++ b/clang/test/CodeGenCXX/ms-thread_local.cpp @@ -29,9 +29,9 @@ thread_local A b; // CHECK-LD-LABEL: declare dso_local void @__dyn_tls_on_demand_init() // CHECK-LEGACY-NOT: declare dso_local void @__dyn_tls_on_demand_init() -// CHECK-LABEL: define dso_local void @"?f@@YA?AUA@@XZ"(ptr noalias sret(%struct.A) align 1 %agg.result) +// CHECK-LABEL: define dso_local void @"?f@@YA?AUA@@XZ"(ptr dead_on_unwind noalias writable sret(%struct.A) align 1 %agg.result) // CHECK: call void @__dyn_tls_on_demand_init() -// CHECK-LD-LABEL: define dso_local void @"?f@@YA?AUA@@XZ"(ptr noalias sret(%struct.A) align 1 %agg.result) +// CHECK-LD-LABEL: define dso_local void @"?f@@YA?AUA@@XZ"(ptr dead_on_unwind noalias writable sret(%struct.A) align 1 %agg.result) // CHECK-LD: call void @__dyn_tls_on_demand_init() // CHECK-LEGACY-NOT: call void @__dyn_tls_on_demand_init() diff --git a/clang/test/CodeGenCXX/nrvo.cpp b/clang/test/CodeGenCXX/nrvo.cpp index 975cf6ee1b66df4e8a1390dc6a81979774f23bea..33dc4cf9dbc8d25893a67fa9eaf7576203fd2472 100644 --- a/clang/test/CodeGenCXX/nrvo.cpp +++ b/clang/test/CodeGenCXX/nrvo.cpp @@ -1059,7 +1059,7 @@ X test8(bool b) { // CHECK-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 // CHECK-NEXT: [[TMP:%.*]] = alloca [[STRUCT_Y:%.*]], align 1 // CHECK-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 -// CHECK-NEXT: call void @_ZN1YIiE1fEv(ptr sret([[STRUCT_Y]]) align 1 [[TMP]]) +// CHECK-NEXT: call void @_ZN1YIiE1fEv(ptr dead_on_unwind writable sret([[STRUCT_Y]]) align 1 [[TMP]]) // CHECK-NEXT: call void @llvm.trap() // CHECK-NEXT: unreachable // @@ -1068,7 +1068,7 @@ X test8(bool b) { // CHECK-EH-03-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 // CHECK-EH-03-NEXT: [[TMP:%.*]] = alloca [[STRUCT_Y:%.*]], align 1 // CHECK-EH-03-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 -// CHECK-EH-03-NEXT: call void @_ZN1YIiE1fEv(ptr sret([[STRUCT_Y]]) align 1 [[TMP]]) +// CHECK-EH-03-NEXT: call void @_ZN1YIiE1fEv(ptr dead_on_unwind writable sret([[STRUCT_Y]]) align 1 [[TMP]]) // CHECK-EH-03-NEXT: call void @llvm.trap() // CHECK-EH-03-NEXT: unreachable // @@ -1077,7 +1077,7 @@ X test8(bool b) { // CHECK-EH-11-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 // CHECK-EH-11-NEXT: [[TMP:%.*]] = alloca [[STRUCT_Y:%.*]], align 1 // CHECK-EH-11-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 -// CHECK-EH-11-NEXT: call void @_ZN1YIiE1fEv(ptr sret([[STRUCT_Y]]) align 1 [[TMP]]) +// CHECK-EH-11-NEXT: call void @_ZN1YIiE1fEv(ptr dead_on_unwind writable sret([[STRUCT_Y]]) align 1 [[TMP]]) // CHECK-EH-11-NEXT: call void @llvm.trap() // CHECK-EH-11-NEXT: unreachable // @@ -1915,7 +1915,7 @@ X test15(bool b) { // http://wg21.link/p2025r2#ex-15 // CHECK-EH-11-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) // CHECK-EH-11-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[CLASS_ANON]], ptr [[REF_TMP]], i32 0, i32 0 // CHECK-EH-11-NEXT: store ptr [[X]], ptr [[TMP0]], align 4 -// CHECK-EH-11-NEXT: invoke void @"_ZZ6test16vENK3$_0clEv"(ptr sret([[CLASS_X]]) align 1 [[AGG_TMP]], ptr noundef nonnull align 4 dereferenceable(4) [[REF_TMP]]) +// CHECK-EH-11-NEXT: invoke void @"_ZZ6test16vENK3$_0clEv"(ptr dead_on_unwind writable sret([[CLASS_X]]) align 1 [[AGG_TMP]], ptr noundef nonnull align 4 dereferenceable(4) [[REF_TMP]]) // CHECK-EH-11-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]] // CHECK-EH-11: invoke.cont: // CHECK-EH-11-NEXT: invoke void @_Z8ConsumeX1X(ptr noundef [[AGG_TMP]]) @@ -2530,7 +2530,7 @@ X test18(int i) { // http://wg21.link/p2025r2#ex-11 // CHECK-EH-11-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) // CHECK-EH-11-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[CLASS_ANON_0]], ptr [[REF_TMP]], i32 0, i32 0 // CHECK-EH-11-NEXT: store ptr [[AGG_RESULT]], ptr [[TMP0]], align 4 -// CHECK-EH-11-NEXT: invoke void @"_ZZ6test19vENK3$_0clEv"(ptr sret([[CLASS_X]]) align 1 [[L]], ptr noundef nonnull align 4 dereferenceable(4) [[REF_TMP]]) +// CHECK-EH-11-NEXT: invoke void @"_ZZ6test19vENK3$_0clEv"(ptr dead_on_unwind writable sret([[CLASS_X]]) align 1 [[L]], ptr noundef nonnull align 4 dereferenceable(4) [[REF_TMP]]) // CHECK-EH-11-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]] // CHECK-EH-11: invoke.cont: // CHECK-EH-11-NEXT: store i1 true, ptr [[NRVO]], align 1 @@ -2584,9 +2584,9 @@ X test20() { // http://wg21.link/p2025r2#ex-18 // CHECK-EH-11-NEXT: entry: // CHECK-EH-11-NEXT: [[AGG_TMP_ENSURED:%.*]] = alloca [[CLASS_X:%.*]], align 1 // CHECK-EH-11-NEXT: [[AGG_TMP_ENSURED1:%.*]] = alloca [[CLASS_X]], align 1 -// CHECK-EH-11-NEXT: call void @_Z6test20ILb1EE1Xv(ptr sret([[CLASS_X]]) align 1 [[AGG_TMP_ENSURED]]) +// CHECK-EH-11-NEXT: call void @_Z6test20ILb1EE1Xv(ptr dead_on_unwind writable sret([[CLASS_X]]) align 1 [[AGG_TMP_ENSURED]]) // CHECK-EH-11-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_TMP_ENSURED]]) #[[ATTR6]] -// CHECK-EH-11-NEXT: call void @_Z6test20ILb0EE1Xv(ptr sret([[CLASS_X]]) align 1 [[AGG_TMP_ENSURED1]]) +// CHECK-EH-11-NEXT: call void @_Z6test20ILb0EE1Xv(ptr dead_on_unwind writable sret([[CLASS_X]]) align 1 [[AGG_TMP_ENSURED1]]) // CHECK-EH-11-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_TMP_ENSURED1]]) #[[ATTR6]] // CHECK-EH-11-NEXT: ret void // @@ -2934,9 +2934,9 @@ X test25() { // CHECK-EH-11-NEXT: entry: // CHECK-EH-11-NEXT: [[AGG_TMP_ENSURED:%.*]] = alloca [[CLASS_X:%.*]], align 1 // CHECK-EH-11-NEXT: [[AGG_TMP_ENSURED1:%.*]] = alloca [[CLASS_X]], align 1 -// CHECK-EH-11-NEXT: call void @_Z6test25ILb1EE1Xv(ptr sret([[CLASS_X]]) align 1 [[AGG_TMP_ENSURED]]) +// CHECK-EH-11-NEXT: call void @_Z6test25ILb1EE1Xv(ptr dead_on_unwind writable sret([[CLASS_X]]) align 1 [[AGG_TMP_ENSURED]]) // CHECK-EH-11-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_TMP_ENSURED]]) #[[ATTR6]] -// CHECK-EH-11-NEXT: call void @_Z6test25ILb0EE1Xv(ptr sret([[CLASS_X]]) align 1 [[AGG_TMP_ENSURED1]]) +// CHECK-EH-11-NEXT: call void @_Z6test25ILb0EE1Xv(ptr dead_on_unwind writable sret([[CLASS_X]]) align 1 [[AGG_TMP_ENSURED1]]) // CHECK-EH-11-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_TMP_ENSURED1]]) #[[ATTR6]] // CHECK-EH-11-NEXT: ret void // diff --git a/clang/test/CodeGenCXX/partitions.cpp b/clang/test/CodeGenCXX/partitions.cpp index b58e88fafdc6b15cbef0dcf9b00b4b0040445167..3b3e69271e7c7b00bac4c4b6e3d321da962436cb 100644 --- a/clang/test/CodeGenCXX/partitions.cpp +++ b/clang/test/CodeGenCXX/partitions.cpp @@ -4,14 +4,14 @@ // RUN: %clang_cc1 -std=c++20 -emit-module-interface -triple %itanium_abi_triple %t/parta.cppm -o %t/mod-parta.pcm // RUN: %clang_cc1 -std=c++20 -emit-module-interface -triple %itanium_abi_triple %t/partb.cppm -o %t/mod-partb.pcm -// RUN: %clang_cc1 -std=c++20 -emit-module-interface -triple %itanium_abi_triple -fmodule-file=%t/mod-parta.pcm \ -// RUN: -fmodule-file=%t/mod-partb.pcm %t/mod.cppm -o %t/mod.pcm +// RUN: %clang_cc1 -std=c++20 -emit-module-interface -triple %itanium_abi_triple %t/mod.cppm \ +// RUN: -fprebuilt-module-path=%t -o %t/mod.pcm // RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/mod.pcm -S -emit-llvm -disable-llvm-passes -o - \ -// RUN: | FileCheck %t/mod.cppm -// RUN: %clang_cc1 -std=c++20 -O2 -emit-module-interface -triple %itanium_abi_triple -fmodule-file=%t/mod-parta.pcm \ -// RUN: -fmodule-file=%t/mod-partb.pcm %t/mod.cppm -o %t/mod.pcm -// RUN: %clang_cc1 -std=c++20 -O2 -triple %itanium_abi_triple %t/mod.pcm -S -emit-llvm -disable-llvm-passes -o - \ -// RUN: | FileCheck %t/mod.cppm -check-prefix=CHECK-OPT +// RUN: -fprebuilt-module-path=%t | FileCheck %t/mod.cppm +// RUN: %clang_cc1 -std=c++20 -O2 -emit-module-interface -triple %itanium_abi_triple \ +// RUN: -fprebuilt-module-path=%t %t/mod.cppm -o %t/mod.pcm +// RUN: %clang_cc1 -std=c++20 -O2 -triple %itanium_abi_triple %t/mod.pcm -S -emit-llvm \ +// RUN: -fprebuilt-module-path=%t -disable-llvm-passes -o - | FileCheck %t/mod.cppm -check-prefix=CHECK-OPT //--- parta.cppm export module mod:parta; diff --git a/clang/test/CodeGenCXX/pass-by-value-noalias.cpp b/clang/test/CodeGenCXX/pass-by-value-noalias.cpp index 765a6fb66a72bc5691f8110a7d24b61aa9053b94..773cf6b81c3b255e09ff2d815d7cdb86d25e9aab 100644 --- a/clang/test/CodeGenCXX/pass-by-value-noalias.cpp +++ b/clang/test/CodeGenCXX/pass-by-value-noalias.cpp @@ -58,8 +58,8 @@ A *p; // NO_NOALIAS: define{{.*}} void @_Z4take1A(ptr noundef %arg) void take(A arg) {} -// WITH_NOALIAS: define{{.*}} void @_Z7CreateAPP1A(ptr noalias sret(%struct.A) align 1 %agg.result, ptr noundef %where) -// NO_NOALIAS: define{{.*}} void @_Z7CreateAPP1A(ptr noalias sret(%struct.A) align 1 %agg.result, ptr noundef %where) +// WITH_NOALIAS: define{{.*}} void @_Z7CreateAPP1A(ptr dead_on_unwind noalias writable sret(%struct.A) align 1 %agg.result, ptr noundef %where) +// NO_NOALIAS: define{{.*}} void @_Z7CreateAPP1A(ptr dead_on_unwind noalias writable sret(%struct.A) align 1 %agg.result, ptr noundef %where) A CreateA(A **where) { A justlikethis; *where = &justlikethis; //Escaped pointer 2 (should also be UB, then) diff --git a/clang/test/CodeGenCXX/regcall.cpp b/clang/test/CodeGenCXX/regcall.cpp index b47a2125d787332c518f1898bffdee9a885dd682..1ff7597e9deef8e79bcf2fb99f829cbbfa96669c 100644 --- a/clang/test/CodeGenCXX/regcall.cpp +++ b/clang/test/CodeGenCXX/regcall.cpp @@ -74,8 +74,8 @@ bool __regcall operator ==(const test_class&, const test_class&){ --x; return fa // CHECK-WIN32-DAG: define dso_local x86_regcallcc noundef zeroext i1 @"??8@Yw_NABVtest_class@@0@Z" test_class __regcall operator""_test_class (unsigned long long) { ++x; return test_class{};} -// CHECK-LIN64-DAG: define{{.*}} x86_regcallcc void @_Zli11_test_classy(ptr noalias sret(%class.test_class) align 4 %agg.result, i64 noundef %0) -// CHECK-LIN32-DAG: define{{.*}} x86_regcallcc void @_Zli11_test_classy(ptr inreg noalias sret(%class.test_class) align 4 %agg.result, i64 noundef %0) +// CHECK-LIN64-DAG: define{{.*}} x86_regcallcc void @_Zli11_test_classy(ptr dead_on_unwind noalias writable sret(%class.test_class) align 4 %agg.result, i64 noundef %0) +// CHECK-LIN32-DAG: define{{.*}} x86_regcallcc void @_Zli11_test_classy(ptr dead_on_unwind inreg noalias writable sret(%class.test_class) align 4 %agg.result, i64 noundef %0) // CHECK-WIN64-DAG: ??__K_test_class@@Yw?AVtest_class@@_K@Z" // CHECK-WIN32-DAG: ??__K_test_class@@Yw?AVtest_class@@_K@Z" @@ -99,8 +99,8 @@ void force_gen() { long double _Complex __regcall foo(long double _Complex f) { return f; } -// CHECK-LIN64-DAG: define{{.*}} x86_regcallcc void @_Z15__regcall3__fooCe(ptr noalias sret({ x86_fp80, x86_fp80 }) align 16 %agg.result, ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 %f) -// CHECK-LIN32-DAG: define{{.*}} x86_regcallcc void @_Z15__regcall3__fooCe(ptr inreg noalias sret({ x86_fp80, x86_fp80 }) align 4 %agg.result, ptr noundef byval({ x86_fp80, x86_fp80 }) align 4 %f) +// CHECK-LIN64-DAG: define{{.*}} x86_regcallcc void @_Z15__regcall3__fooCe(ptr dead_on_unwind noalias writable sret({ x86_fp80, x86_fp80 }) align 16 %agg.result, ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 %f) +// CHECK-LIN32-DAG: define{{.*}} x86_regcallcc void @_Z15__regcall3__fooCe(ptr dead_on_unwind inreg noalias writable sret({ x86_fp80, x86_fp80 }) align 4 %agg.result, ptr noundef byval({ x86_fp80, x86_fp80 }) align 4 %f) // CHECK-WIN64-DAG: define dso_local x86_regcallcc noundef { double, double } @"?foo@@YwU?$_Complex@O@__clang@@U12@@Z"(double noundef %f.0, double noundef %f.1) // CHECK-WIN32-DAG: define dso_local x86_regcallcc noundef { double, double } @"?foo@@YwU?$_Complex@O@__clang@@U12@@Z"(double noundef %f.0, double noundef %f.1) diff --git a/clang/test/CodeGenCXX/regcall4.cpp b/clang/test/CodeGenCXX/regcall4.cpp index 7c35db36e1053d418a4cde148ee53c810eb26bf6..2ecd5b4951c757e020c2c2c11974af09b3074dd4 100644 --- a/clang/test/CodeGenCXX/regcall4.cpp +++ b/clang/test/CodeGenCXX/regcall4.cpp @@ -74,8 +74,8 @@ bool __regcall operator ==(const test_class&, const test_class&){ --x; return fa // CHECK-WIN32-DAG: define dso_local x86_regcallcc noundef zeroext i1 @"??8@Yx_NABVtest_class@@0@Z" test_class __regcall operator""_test_class (unsigned long long) { ++x; return test_class{};} -// CHECK-LIN64-DAG: define{{.*}} x86_regcallcc void @_Zli11_test_classy(ptr noalias sret(%class.test_class) align 4 %agg.result, i64 noundef %0) -// CHECK-LIN32-DAG: define{{.*}} x86_regcallcc void @_Zli11_test_classy(ptr inreg noalias sret(%class.test_class) align 4 %agg.result, i64 noundef %0) +// CHECK-LIN64-DAG: define{{.*}} x86_regcallcc void @_Zli11_test_classy(ptr dead_on_unwind noalias writable sret(%class.test_class) align 4 %agg.result, i64 noundef %0) +// CHECK-LIN32-DAG: define{{.*}} x86_regcallcc void @_Zli11_test_classy(ptr dead_on_unwind inreg noalias writable sret(%class.test_class) align 4 %agg.result, i64 noundef %0) // CHECK-WIN64-DAG: ??__K_test_class@@Yx?AVtest_class@@_K@Z" // CHECK-WIN32-DAG: ??__K_test_class@@Yx?AVtest_class@@_K@Z" @@ -99,8 +99,8 @@ void force_gen() { long double _Complex __regcall foo(long double _Complex f) { return f; } -// CHECK-LIN64-DAG: define{{.*}} x86_regcallcc void @_Z15__regcall4__fooCe(ptr noalias sret({ x86_fp80, x86_fp80 }) align 16 %agg.result, ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 %f) -// CHECK-LIN32-DAG: define{{.*}} x86_regcallcc void @_Z15__regcall4__fooCe(ptr inreg noalias sret({ x86_fp80, x86_fp80 }) align 4 %agg.result, ptr noundef byval({ x86_fp80, x86_fp80 }) align 4 %f) +// CHECK-LIN64-DAG: define{{.*}} x86_regcallcc void @_Z15__regcall4__fooCe(ptr dead_on_unwind noalias writable sret({ x86_fp80, x86_fp80 }) align 16 %agg.result, ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 %f) +// CHECK-LIN32-DAG: define{{.*}} x86_regcallcc void @_Z15__regcall4__fooCe(ptr dead_on_unwind inreg noalias writable sret({ x86_fp80, x86_fp80 }) align 4 %agg.result, ptr noundef byval({ x86_fp80, x86_fp80 }) align 4 %f) // CHECK-WIN64-DAG: define dso_local x86_regcallcc noundef { double, double } @"?foo@@YxU?$_Complex@O@__clang@@U12@@Z"(double noundef %f.0, double noundef %f.1) // CHECK-WIN32-DAG: define dso_local x86_regcallcc noundef { double, double } @"?foo@@YxU?$_Complex@O@__clang@@U12@@Z"(double noundef %f.0, double noundef %f.1) diff --git a/clang/test/CodeGenCXX/stack-reuse-miscompile.cpp b/clang/test/CodeGenCXX/stack-reuse-miscompile.cpp index dbeea5e32cfb803863d8f1c5ba0fcda94dba2da2..50a8d167f5b77254cbbe90a23be7e492907b8590 100644 --- a/clang/test/CodeGenCXX/stack-reuse-miscompile.cpp +++ b/clang/test/CodeGenCXX/stack-reuse-miscompile.cpp @@ -36,7 +36,7 @@ const char * f(S s) // CHECK: call void @llvm.lifetime.start.p0(i64 16, ptr [[T3]]) // CHECK: [[T5:%.*]] = call noundef ptr @_ZN1TC1E1S(ptr {{[^,]*}} [[T3]], [2 x i32] %{{.*}}) // -// CHECK: call void @_ZNK1T6concatERKS_(ptr sret(%class.T) align 4 [[T1]], ptr {{[^,]*}} [[T2]], ptr noundef nonnull align 4 dereferenceable(16) [[T3]]) +// CHECK: call void @_ZNK1T6concatERKS_(ptr dead_on_unwind writable sret(%class.T) align 4 [[T1]], ptr {{[^,]*}} [[T2]], ptr noundef nonnull align 4 dereferenceable(16) [[T3]]) // CHECK: [[T6:%.*]] = call noundef ptr @_ZNK1T3strEv(ptr {{[^,]*}} [[T1]]) // // CHECK: call void @llvm.lifetime.end.p0( diff --git a/clang/test/CodeGenCXX/stack-reuse.cpp b/clang/test/CodeGenCXX/stack-reuse.cpp index e2412a55c1f62f1277871c1db0b0e4469b40b4ab..ca73781b79ec1d1aac0424468086fb1c4f04fdaf 100644 --- a/clang/test/CodeGenCXX/stack-reuse.cpp +++ b/clang/test/CodeGenCXX/stack-reuse.cpp @@ -135,7 +135,7 @@ int large_combiner_test(S_large s) { // CHECK: [[T2:%.*]] = alloca %struct.Combiner // CHECK: [[T1:%.*]] = alloca %struct.Combiner // CHECK: [[T3:%.*]] = call noundef ptr @_ZN8CombinerC1E7S_large(ptr {{[^,]*}} [[T1]], [9 x i32] %s.coerce) -// CHECK: call void @_ZN8Combiner1fEv(ptr nonnull sret(%struct.Combiner) align 4 [[T2]], ptr {{[^,]*}} [[T1]]) +// CHECK: call void @_ZN8Combiner1fEv(ptr dead_on_unwind nonnull writable sret(%struct.Combiner) align 4 [[T2]], ptr {{[^,]*}} [[T1]]) // CHECK: [[T5:%.*]] = load i32, ptr [[T2]] // CHECK: ret i32 [[T5]] diff --git a/clang/test/CodeGenCXX/temporaries.cpp b/clang/test/CodeGenCXX/temporaries.cpp index c5adb42a6f17374d47a36f1ab636ecad3437b2fb..9f29d3b7327839515c3aebd40127cab921434482 100644 --- a/clang/test/CodeGenCXX/temporaries.cpp +++ b/clang/test/CodeGenCXX/temporaries.cpp @@ -414,13 +414,13 @@ namespace Elision { // CHECK-NEXT: call void @_ZN7Elision1AC1Ev(ptr {{[^,]*}} [[I]]) A i = (foo(), A()); - // CHECK-NEXT: call void @_ZN7Elision4fooAEv(ptr sret([[A]]) align 8 [[T0]]) + // CHECK-NEXT: call void @_ZN7Elision4fooAEv(ptr dead_on_unwind writable sret([[A]]) align 8 [[T0]]) // CHECK-NEXT: call void @_ZN7Elision1AC1Ev(ptr {{[^,]*}} [[J]]) // CHECK-NEXT: call void @_ZN7Elision1AD1Ev(ptr {{[^,]*}} [[T0]]) A j = (fooA(), A()); // CHECK-NEXT: call void @_ZN7Elision1AC1Ev(ptr {{[^,]*}} [[T1]]) - // CHECK-NEXT: call void @_ZN7Elision4fooAEv(ptr sret([[A]]) align 8 [[K]]) + // CHECK-NEXT: call void @_ZN7Elision4fooAEv(ptr dead_on_unwind writable sret([[A]]) align 8 [[K]]) // CHECK-NEXT: call void @_ZN7Elision1AD1Ev(ptr {{[^,]*}} [[T1]]) A k = (A(), fooA()); @@ -447,7 +447,7 @@ namespace Elision { // CHECK-NEXT: call void @_ZN7Elision1AD1Ev(ptr {{[^,]*}} [[I]]) } - // CHECK: define{{.*}} void @_ZN7Elision5test2Ev(ptr noalias sret([[A]]) align 8 + // CHECK: define{{.*}} void @_ZN7Elision5test2Ev(ptr dead_on_unwind noalias writable sret([[A]]) align 8 A test2() { // CHECK: call void @_ZN7Elision3fooEv() // CHECK-NEXT: call void @_ZN7Elision1AC1Ev(ptr {{[^,]*}} [[RET:%.*]]) @@ -455,7 +455,7 @@ namespace Elision { return (foo(), A()); } - // CHECK: define{{.*}} void @_ZN7Elision5test3EiNS_1AE(ptr noalias sret([[A]]) align 8 + // CHECK: define{{.*}} void @_ZN7Elision5test3EiNS_1AE(ptr dead_on_unwind noalias writable sret([[A]]) align 8 A test3(int v, A x) { if (v < 5) // CHECK: call void @_ZN7Elision1AC1Ev(ptr {{[^,]*}} [[RET:%.*]]) @@ -495,7 +495,7 @@ namespace Elision { // CHECK: call void @_ZN7Elision1AD1Ev(ptr {{[^,]*}} [[X]]) } - // CHECK: define{{.*}} void @_ZN7Elision5test5Ev(ptr noalias sret([[A]]) align 8 + // CHECK: define{{.*}} void @_ZN7Elision5test5Ev(ptr dead_on_unwind noalias writable sret([[A]]) align 8 struct B { A a; B(); }; A test5() { // CHECK: [[AT0:%.*]] = alloca [[A]], align 8 @@ -533,7 +533,7 @@ namespace Elision { void test6(const C *x) { // CHECK: [[T0:%.*]] = alloca [[A]], align 8 // CHECK: [[X:%.*]] = load ptr, ptr {{%.*}}, align 8 - // CHECK-NEXT: call void @_ZNK7Elision1CcvNS_1AEEv(ptr sret([[A]]) align 8 [[T0]], ptr {{[^,]*}} [[X]]) + // CHECK-NEXT: call void @_ZNK7Elision1CcvNS_1AEEv(ptr dead_on_unwind writable sret([[A]]) align 8 [[T0]], ptr {{[^,]*}} [[X]]) // CHECK-NEXT: call void @_ZNK7Elision1A3fooEv(ptr {{[^,]*}} [[T0]]) // CHECK-NEXT: call void @_ZN7Elision1AD1Ev(ptr {{[^,]*}} [[T0]]) // CHECK-NEXT: ret void diff --git a/clang/test/CodeGenCXX/thiscall-struct-return.cpp b/clang/test/CodeGenCXX/thiscall-struct-return.cpp index c29ec56b41c1a82f39414097b8acbc0b5c341cbe..7802ed4b18ebd2634a9da101fb5209f49418cc1e 100644 --- a/clang/test/CodeGenCXX/thiscall-struct-return.cpp +++ b/clang/test/CodeGenCXX/thiscall-struct-return.cpp @@ -34,8 +34,8 @@ void test( void ) { // CHECK: call void @_ZN1CC1Ev(ptr {{[^,]*}} [[C:%.+]]) C c; -// CHECK: call x86_thiscallcc void @_ZNK1C5SmallEv(ptr sret(%struct.S) align 4 %{{.+}}, ptr {{[^,]*}} [[C]]) +// CHECK: call x86_thiscallcc void @_ZNK1C5SmallEv(ptr dead_on_unwind writable sret(%struct.S) align 4 %{{.+}}, ptr {{[^,]*}} [[C]]) (void)c.Small(); -// CHECK: call x86_thiscallcc void @_ZNK1C6MediumEv(ptr sret(%struct.M) align 4 %{{.+}}, ptr {{[^,]*}} [[C]]) +// CHECK: call x86_thiscallcc void @_ZNK1C6MediumEv(ptr dead_on_unwind writable sret(%struct.M) align 4 %{{.+}}, ptr {{[^,]*}} [[C]]) (void)c.Medium(); } diff --git a/clang/test/CodeGenCXX/thunk-returning-memptr.cpp b/clang/test/CodeGenCXX/thunk-returning-memptr.cpp index aaa5c8605f23e75f2fb75135416afa194efcab1a..99ef76f91cecf3463e16aa70e770a3e235a1aebb 100644 --- a/clang/test/CodeGenCXX/thunk-returning-memptr.cpp +++ b/clang/test/CodeGenCXX/thunk-returning-memptr.cpp @@ -23,5 +23,5 @@ C::C() {} // Because of the tail call, the return value cannot be copied into a local // alloca. (PR39901) -// CHECK-LABEL: define linkonce_odr void @_ZThn4_N1C1fEv(ptr noalias sret({ i32, i32 }) align 4 %agg.result, ptr noundef %this) -// CHECK: tail call void @_ZN1C1fEv(ptr sret({ i32, i32 }) align 4 %agg.result +// CHECK-LABEL: define linkonce_odr void @_ZThn4_N1C1fEv(ptr dead_on_unwind noalias writable sret({ i32, i32 }) align 4 %agg.result, ptr noundef %this) +// CHECK: tail call void @_ZN1C1fEv(ptr dead_on_unwind writable sret({ i32, i32 }) align 4 %agg.result diff --git a/clang/test/CodeGenCXX/trivial_abi.cpp b/clang/test/CodeGenCXX/trivial_abi.cpp index 3249df129157f41dd72f24b9e5079db018cd3837..3012b0f2bc33dcdd40713c48ef509ef39b0ef6da 100644 --- a/clang/test/CodeGenCXX/trivial_abi.cpp +++ b/clang/test/CodeGenCXX/trivial_abi.cpp @@ -151,7 +151,7 @@ void testIgnoredSmall() { void testParamLarge(Large a) noexcept { } -// CHECK: define{{.*}} void @_Z15testReturnLargev(ptr noalias sret(%[[STRUCT_LARGE]]) align 8 %[[AGG_RESULT:.*]]) +// CHECK: define{{.*}} void @_Z15testReturnLargev(ptr dead_on_unwind noalias writable sret(%[[STRUCT_LARGE]]) align 8 %[[AGG_RESULT:.*]]) // CHECK: %[[CALL:.*]] = call noundef ptr @_ZN5LargeC1Ev(ptr {{[^,]*}} %[[AGG_RESULT]]) // CHECK: ret void // CHECK: } @@ -178,7 +178,7 @@ void testCallLarge0() { // CHECK: define{{.*}} void @_Z14testCallLarge1v() // CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_LARGE:.*]], align 8 -// CHECK: call void @_Z15testReturnLargev(ptr sret(%[[STRUCT_LARGE]]) align 8 %[[AGG_TMP]]) +// CHECK: call void @_Z15testReturnLargev(ptr dead_on_unwind writable sret(%[[STRUCT_LARGE]]) align 8 %[[AGG_TMP]]) // CHECK: call void @_Z14testParamLarge5Large(ptr noundef %[[AGG_TMP]]) // CHECK: ret void // CHECK: } @@ -189,7 +189,7 @@ void testCallLarge1() { // CHECK: define{{.*}} void @_Z16testIgnoredLargev() // CHECK: %[[AGG_TMP_ENSURED:.*]] = alloca %[[STRUCT_LARGE:.*]], align 8 -// CHECK: call void @_Z15testReturnLargev(ptr sret(%[[STRUCT_LARGE]]) align 8 %[[AGG_TMP_ENSURED]]) +// CHECK: call void @_Z15testReturnLargev(ptr dead_on_unwind writable sret(%[[STRUCT_LARGE]]) align 8 %[[AGG_TMP_ENSURED]]) // CHECK: %[[CALL:.*]] = call noundef ptr @_ZN5LargeD1Ev(ptr {{[^,]*}} %[[AGG_TMP_ENSURED]]) // CHECK: ret void // CHECK: } @@ -210,7 +210,7 @@ Trivial testReturnHasTrivial() { return t; } -// CHECK: define{{.*}} void @_Z23testReturnHasNonTrivialv(ptr noalias sret(%[[STRUCT_NONTRIVIAL:.*]]) align 4 %[[AGG_RESULT:.*]]) +// CHECK: define{{.*}} void @_Z23testReturnHasNonTrivialv(ptr dead_on_unwind noalias writable sret(%[[STRUCT_NONTRIVIAL:.*]]) align 4 %[[AGG_RESULT:.*]]) // CHECK: %[[CALL:.*]] = call noundef ptr @_ZN10NonTrivialC1Ev(ptr {{[^,]*}} %[[AGG_RESULT]]) // CHECK: ret void // CHECK: } diff --git a/clang/test/CodeGenCXX/unknown-anytype.cpp b/clang/test/CodeGenCXX/unknown-anytype.cpp index 862b8fe8b66dd4e2dd29e960a12619f4bcd40cd8..ade9a6482d75caede418801a9e4e4128b1154ca0 100644 --- a/clang/test/CodeGenCXX/unknown-anytype.cpp +++ b/clang/test/CodeGenCXX/unknown-anytype.cpp @@ -70,7 +70,7 @@ struct Test7 { }; extern "C" __unknown_anytype test7_any(int); Test7 test7() { - // COMMON: call void @test7_any(ptr sret({{%.*}}) align 1 {{%.*}}, i32 noundef 5) + // COMMON: call void @test7_any(ptr dead_on_unwind writable sret({{%.*}}) align 1 {{%.*}}, i32 noundef 5) return (Test7) test7_any(5); } diff --git a/clang/test/CodeGenCXX/wasm-args-returns.cpp b/clang/test/CodeGenCXX/wasm-args-returns.cpp index 090ca9a99756f70125923ad9eebdb76a5e5576c9..e80dfefedece16862c8303c90c84060d8ccd6efe 100644 --- a/clang/test/CodeGenCXX/wasm-args-returns.cpp +++ b/clang/test/CodeGenCXX/wasm-args-returns.cpp @@ -30,52 +30,52 @@ struct two_fields { double d, e; }; test(two_fields); -// CHECK: define void @_Z7forward10two_fields(ptr noalias nocapture writeonly sret(%struct.two_fields) align 8 %{{.*}}, ptr nocapture readonly byval(%struct.two_fields) align 8 %{{.*}}) +// CHECK: define void @_Z7forward10two_fields(ptr dead_on_unwind noalias nocapture writable writeonly sret(%struct.two_fields) align 8 %{{.*}}, ptr nocapture readonly byval(%struct.two_fields) align 8 %{{.*}}) // // CHECK: define void @_Z15test_two_fieldsv() // CHECK: %[[tmp:.*]] = alloca %struct.two_fields, align 8 -// CHECK: call void @_Z14def_two_fieldsv(ptr nonnull sret(%struct.two_fields) align 8 %[[tmp]]) +// CHECK: call void @_Z14def_two_fieldsv(ptr dead_on_unwind nonnull writable sret(%struct.two_fields) align 8 %[[tmp]]) // CHECK: call void @_Z3use10two_fields(ptr nonnull byval(%struct.two_fields) align 8 %[[tmp]]) // CHECK: ret void // // CHECK: declare void @_Z3use10two_fields(ptr byval(%struct.two_fields) align 8) -// CHECK: declare void @_Z14def_two_fieldsv(ptr sret(%struct.two_fields) align 8) +// CHECK: declare void @_Z14def_two_fieldsv(ptr dead_on_unwind writable sret(%struct.two_fields) align 8) struct copy_ctor { double d; copy_ctor(copy_ctor const &); }; test(copy_ctor); -// CHECK: define void @_Z7forward9copy_ctor(ptr noalias {{[^,]*}} sret(%struct.copy_ctor) align 8 %{{.*}}, ptr nonnull %{{.*}}) +// CHECK: define void @_Z7forward9copy_ctor(ptr dead_on_unwind noalias {{[^,]*}} sret(%struct.copy_ctor) align 8 %{{.*}}, ptr nonnull %{{.*}}) // // CHECK: declare ptr @_ZN9copy_ctorC1ERKS_(ptr {{[^,]*}} returned {{[^,]*}}, ptr nonnull align 8 dereferenceable(8)) // // CHECK: define void @_Z14test_copy_ctorv() // CHECK: %[[tmp:.*]] = alloca %struct.copy_ctor, align 8 -// CHECK: call void @_Z13def_copy_ctorv(ptr nonnull sret(%struct.copy_ctor) align 8 %[[tmp]]) +// CHECK: call void @_Z13def_copy_ctorv(ptr dead_on_unwind nonnull writable sret(%struct.copy_ctor) align 8 %[[tmp]]) // CHECK: call void @_Z3use9copy_ctor(ptr nonnull %[[tmp]]) // CHECK: ret void // // CHECK: declare void @_Z3use9copy_ctor(ptr) -// CHECK: declare void @_Z13def_copy_ctorv(ptr sret(%struct.copy_ctor) align 8) +// CHECK: declare void @_Z13def_copy_ctorv(ptr dead_on_unwind writable sret(%struct.copy_ctor) align 8) struct __attribute__((aligned(16))) aligned_copy_ctor { double d, e; aligned_copy_ctor(aligned_copy_ctor const &); }; test(aligned_copy_ctor); -// CHECK: define void @_Z7forward17aligned_copy_ctor(ptr noalias {{[^,]*}} sret(%struct.aligned_copy_ctor) align 16 %{{.*}}, ptr nonnull %{{.*}}) +// CHECK: define void @_Z7forward17aligned_copy_ctor(ptr dead_on_unwind noalias {{[^,]*}} sret(%struct.aligned_copy_ctor) align 16 %{{.*}}, ptr nonnull %{{.*}}) // // CHECK: declare ptr @_ZN17aligned_copy_ctorC1ERKS_(ptr {{[^,]*}} returned {{[^,]*}}, ptr nonnull align 16 dereferenceable(16)) // // CHECK: define void @_Z22test_aligned_copy_ctorv() // CHECK: %[[tmp:.*]] = alloca %struct.aligned_copy_ctor, align 16 -// CHECK: call void @_Z21def_aligned_copy_ctorv(ptr nonnull sret(%struct.aligned_copy_ctor) align 16 %[[tmp]]) +// CHECK: call void @_Z21def_aligned_copy_ctorv(ptr dead_on_unwind nonnull writable sret(%struct.aligned_copy_ctor) align 16 %[[tmp]]) // CHECK: call void @_Z3use17aligned_copy_ctor(ptr nonnull %[[tmp]]) // CHECK: ret void // // CHECK: declare void @_Z3use17aligned_copy_ctor(ptr) -// CHECK: declare void @_Z21def_aligned_copy_ctorv(ptr sret(%struct.aligned_copy_ctor) align 16) +// CHECK: declare void @_Z21def_aligned_copy_ctorv(ptr dead_on_unwind writable sret(%struct.aligned_copy_ctor) align 16) struct empty {}; test(empty); diff --git a/clang/test/CodeGenCXX/x86_32-arguments.cpp b/clang/test/CodeGenCXX/x86_32-arguments.cpp index 7388b2fcfe6cdddfe8d51c3e2681403b79516862..c071548327e8d1e19629415379c460beb8ec56a2 100644 --- a/clang/test/CodeGenCXX/x86_32-arguments.cpp +++ b/clang/test/CodeGenCXX/x86_32-arguments.cpp @@ -6,7 +6,7 @@ struct S { short s; }; -// CHECK-LABEL: define{{.*}} void @_Z1fv(ptr noalias sret(%struct.S) align 2 % +// CHECK-LABEL: define{{.*}} void @_Z1fv(ptr dead_on_unwind noalias writable sret(%struct.S) align 2 % S f() { return S(); } // CHECK-LABEL: define{{.*}} void @_Z1f1S(ptr noundef %0) void f(S) { } @@ -18,7 +18,7 @@ public: double c; }; -// CHECK-LABEL: define{{.*}} void @_Z1gv(ptr noalias sret(%class.C) align 4 % +// CHECK-LABEL: define{{.*}} void @_Z1gv(ptr dead_on_unwind noalias writable sret(%class.C) align 4 % C g() { return C(); } // CHECK-LABEL: define{{.*}} void @_Z1f1C(ptr noundef %0) @@ -103,13 +103,13 @@ struct s7_1 { double x; }; struct s7 : s7_0, s7_1 { }; s7 f7() { return s7(); } -// CHECK-LABEL: define{{.*}} void @_Z2f8v(ptr noalias sret(%struct.s8) align 4 %agg.result) +// CHECK-LABEL: define{{.*}} void @_Z2f8v(ptr dead_on_unwind noalias writable sret(%struct.s8) align 4 %agg.result) struct s8_0 { }; struct s8_1 { double x; }; struct s8 { s8_0 a; s8_1 b; }; s8 f8() { return s8(); } -// CHECK-LABEL: define{{.*}} void @_Z2f9v(ptr noalias sret(%struct.s9) align 4 %agg.result) +// CHECK-LABEL: define{{.*}} void @_Z2f9v(ptr dead_on_unwind noalias writable sret(%struct.s9) align 4 %agg.result) struct s9_0 { unsigned : 0; }; struct s9_1 { double x; }; struct s9 { s9_0 a; s9_1 b; }; diff --git a/clang/test/CodeGenCXX/x86_64-arguments.cpp b/clang/test/CodeGenCXX/x86_64-arguments.cpp index d1bbf5d30f59ea6b88a9513090afbc556d97790d..ebeba7fd6549525b9e7138d556a1423b2e610c68 100644 --- a/clang/test/CodeGenCXX/x86_64-arguments.cpp +++ b/clang/test/CodeGenCXX/x86_64-arguments.cpp @@ -173,7 +173,7 @@ namespace test9 { // CHECK: define{{.*}} void @_ZN5test93fooEPNS_1SEPNS_1TE(ptr %0, ptr %1) void foo(S*, T*) {} - // CHECK: define{{.*}} void @_ZN5test91aEiiiiNS_1TEPv(ptr noalias sret([[S:%.*]]) align 8 {{%.*}}, i32 %0, i32 %1, i32 %2, i32 %3, ptr byval([[T:%.*]]) align 8 %4, ptr %5) + // CHECK: define{{.*}} void @_ZN5test91aEiiiiNS_1TEPv(ptr dead_on_unwind noalias writable sret([[S:%.*]]) align 8 {{%.*}}, i32 %0, i32 %1, i32 %2, i32 %3, ptr byval([[T:%.*]]) align 8 %4, ptr %5) S a(int, int, int, int, T, void*) { return S(); } @@ -183,7 +183,7 @@ namespace test9 { return sret; } - // CHECK: define{{.*}} void @_ZN5test91cEiiiNS_1TEPv(ptr noalias sret([[S]]) align 8 {{%.*}}, i32 %0, i32 %1, i32 %2, ptr {{%.*}}, ptr {{%.*}}, ptr %3) + // CHECK: define{{.*}} void @_ZN5test91cEiiiNS_1TEPv(ptr dead_on_unwind noalias writable sret([[S]]) align 8 {{%.*}}, i32 %0, i32 %1, i32 %2, ptr {{%.*}}, ptr {{%.*}}, ptr %3) S c(int, int, int, T, void*) { return S(); } diff --git a/clang/test/CodeGenCoroutines/coro-await.cpp b/clang/test/CodeGenCoroutines/coro-await.cpp index e1c7039469afc2c68296222585f224429bd33ffc..dc5a765ccb83d782c10add7d6977b5f756fc5067 100644 --- a/clang/test/CodeGenCoroutines/coro-await.cpp +++ b/clang/test/CodeGenCoroutines/coro-await.cpp @@ -127,7 +127,7 @@ extern "C" void f1(int) { // CHECK: %[[PROMISE:.+]] = alloca %"struct.std::coroutine_traits::promise_type" // CHECK: %[[FRAME:.+]] = call ptr @llvm.coro.begin( co_yield 42; - // CHECK: call void @_ZNSt16coroutine_traitsIJviEE12promise_type11yield_valueEi(ptr sret(%struct.suspend_maybe) align 4 %[[AWAITER:.+]], ptr {{[^,]*}} %[[PROMISE]], i32 42) + // CHECK: call void @_ZNSt16coroutine_traitsIJviEE12promise_type11yield_valueEi(ptr dead_on_unwind writable sret(%struct.suspend_maybe) align 4 %[[AWAITER:.+]], ptr {{[^,]*}} %[[PROMISE]], i32 42) // See if we need to suspend: // -------------------------- @@ -194,20 +194,20 @@ extern "C" void UseAggr(Aggr&&); extern "C" void TestAggr() { UseAggr(co_await AggrAwaiter{}); Whatever(); - // CHECK: call void @_ZN11AggrAwaiter12await_resumeEv(ptr sret(%struct.Aggr) align 4 %[[AwaitResume:.+]], + // CHECK: call void @_ZN11AggrAwaiter12await_resumeEv(ptr dead_on_unwind writable sret(%struct.Aggr) align 4 %[[AwaitResume:.+]], // CHECK: call void @UseAggr(ptr nonnull align 4 dereferenceable(12) %[[AwaitResume]]) // CHECK: call void @_ZN4AggrD1Ev(ptr {{[^,]*}} %[[AwaitResume]]) // CHECK: call void @Whatever() co_await AggrAwaiter{}; Whatever(); - // CHECK: call void @_ZN11AggrAwaiter12await_resumeEv(ptr sret(%struct.Aggr) align 4 %[[AwaitResume2:.+]], + // CHECK: call void @_ZN11AggrAwaiter12await_resumeEv(ptr dead_on_unwind writable sret(%struct.Aggr) align 4 %[[AwaitResume2:.+]], // CHECK: call void @_ZN4AggrD1Ev(ptr {{[^,]*}} %[[AwaitResume2]]) // CHECK: call void @Whatever() Aggr Val = co_await AggrAwaiter{}; Whatever(); - // CHECK: call void @_ZN11AggrAwaiter12await_resumeEv(ptr sret(%struct.Aggr) align 4 %[[AwaitResume3:.+]], + // CHECK: call void @_ZN11AggrAwaiter12await_resumeEv(ptr dead_on_unwind writable sret(%struct.Aggr) align 4 %[[AwaitResume3:.+]], // CHECK: call void @Whatever() // CHECK: call void @_ZN4AggrD1Ev(ptr {{[^,]*}} %[[AwaitResume3]]) } @@ -252,7 +252,7 @@ extern "C" void TestOpAwait() { co_await MyAgg{}; // CHECK: call void @_ZN5MyAggawEv(ptr {{[^,]*}} % - // CHECK: call void @_ZN11AggrAwaiter12await_resumeEv(ptr sret(%struct.Aggr) align 4 % + // CHECK: call void @_ZN11AggrAwaiter12await_resumeEv(ptr dead_on_unwind writable sret(%struct.Aggr) align 4 % } // CHECK-LABEL: EndlessLoop( diff --git a/clang/test/CodeGenCoroutines/coro-gro2.cpp b/clang/test/CodeGenCoroutines/coro-gro2.cpp index b0faa66edd33387fe0b214c88e5495bc3d3fd486..56299574fbf2579166efb1bb4bb22d7ce7d48013 100644 --- a/clang/test/CodeGenCoroutines/coro-gro2.cpp +++ b/clang/test/CodeGenCoroutines/coro-gro2.cpp @@ -34,13 +34,13 @@ struct coro { }; // Verify that the RVO is applied. -// CHECK-LABEL: define{{.*}} void @_Z1fi(ptr noalias sret(%struct.coro) align 8 %agg.result, i32 noundef %0) +// CHECK-LABEL: define{{.*}} void @_Z1fi(ptr dead_on_unwind noalias writable sret(%struct.coro) align 8 %agg.result, i32 noundef %0) coro f(int) { // CHECK: %call = call noalias noundef nonnull ptr @_Znwm( // CHECK-NEXT: br label %[[CoroInit:.*]] // CHECK: {{.*}}[[CoroInit]]: -// CHECK: call void @{{.*get_return_objectEv}}(ptr sret(%struct.coro) align 8 %agg.result +// CHECK: call void @{{.*get_return_objectEv}}(ptr dead_on_unwind writable sret(%struct.coro) align 8 %agg.result co_return; } @@ -63,7 +63,7 @@ struct coro_two { }; // Verify that the RVO is applied. -// CHECK-LABEL: define{{.*}} void @_Z1hi(ptr noalias sret(%struct.coro_two) align 8 %agg.result, i32 noundef %0) +// CHECK-LABEL: define{{.*}} void @_Z1hi(ptr dead_on_unwind noalias writable sret(%struct.coro_two) align 8 %agg.result, i32 noundef %0) coro_two h(int) { // CHECK: %call = call noalias noundef ptr @_ZnwmRKSt9nothrow_t @@ -71,11 +71,11 @@ coro_two h(int) { // CHECK-NEXT: br i1 %[[CheckNull]], label %[[InitOnSuccess:.*]], label %[[InitOnFailure:.*]] // CHECK: {{.*}}[[InitOnFailure]]: - // CHECK-NEXT: call void @{{.*get_return_object_on_allocation_failureEv}}(ptr sret(%struct.coro_two) align 8 %agg.result + // CHECK-NEXT: call void @{{.*get_return_object_on_allocation_failureEv}}(ptr dead_on_unwind writable sret(%struct.coro_two) align 8 %agg.result // CHECK-NEXT: br label %[[RetLabel:.*]] // CHECK: {{.*}}[[InitOnSuccess]]: - // CHECK: call void @{{.*get_return_objectEv}}(ptr sret(%struct.coro_two) align 8 %agg.result + // CHECK: call void @{{.*get_return_objectEv}}(ptr dead_on_unwind writable sret(%struct.coro_two) align 8 %agg.result // CHECK: [[RetLabel]]: // CHECK-NEXT: ret void diff --git a/clang/test/CodeGenHLSL/sret_output.hlsl b/clang/test/CodeGenHLSL/sret_output.hlsl index 6b15e017a024d4556183ae607496c73bcb67df6f..33f88c639525f69a9cd316d58aea4574f4d968db 100644 --- a/clang/test/CodeGenHLSL/sret_output.hlsl +++ b/clang/test/CodeGenHLSL/sret_output.hlsl @@ -10,7 +10,7 @@ struct S { // Make sure sret parameter is generated. -// CHECK:define internal void @"?ps_main@@YA?AUS@@XZ"(ptr noalias sret(%struct.S) align 4 %agg.result) +// CHECK:define internal void @"?ps_main@@YA?AUS@@XZ"(ptr dead_on_unwind noalias writable sret(%struct.S) align 4 %agg.result) // FIXME: change it to real value instead of poison value once semantic is add to a. // Make sure the function with sret is called. // CHECK:call void @"?ps_main@@YA?AUS@@XZ"(ptr poison) diff --git a/clang/test/CodeGenObjC/arc.m b/clang/test/CodeGenObjC/arc.m index 74356d8895d144a6c7a5ca93378c9bcf67894bd3..aeead58f8131d70402af5f48fb7c2a92326aa42f 100644 --- a/clang/test/CodeGenObjC/arc.m +++ b/clang/test/CodeGenObjC/arc.m @@ -1358,11 +1358,11 @@ struct AggDtor getAggDtor(void); // CHECK-LABEL: define{{.*}} void @test71 void test71(void) { // CHECK: call void @llvm.lifetime.start.p0({{[^,]+}}, ptr %[[T:.*]]) - // CHECK: call void @getAggDtor(ptr sret(%struct.AggDtor) align 8 %[[T]]) + // CHECK: call void @getAggDtor(ptr dead_on_unwind writable sret(%struct.AggDtor) align 8 %[[T]]) // CHECK: call void @__destructor_8_s40(ptr %[[T]]) // CHECK: call void @llvm.lifetime.end.p0({{[^,]+}}, ptr %[[T]]) // CHECK: call void @llvm.lifetime.start.p0({{[^,]+}}, ptr %[[T2:.*]]) - // CHECK: call void @getAggDtor(ptr sret(%struct.AggDtor) align 8 %[[T2]]) + // CHECK: call void @getAggDtor(ptr dead_on_unwind writable sret(%struct.AggDtor) align 8 %[[T2]]) // CHECK: call void @__destructor_8_s40(ptr %[[T2]]) // CHECK: call void @llvm.lifetime.end.p0({{[^,]+}}, ptr %[[T2]]) getAggDtor(); diff --git a/clang/test/CodeGenObjC/direct-method.m b/clang/test/CodeGenObjC/direct-method.m index 8a3c2f575d2d328eba772c7e6734749c0bf6b618..028a0888d594ee1b60ee1ef0276b437b0f04abdb 100644 --- a/clang/test/CodeGenObjC/direct-method.m +++ b/clang/test/CodeGenObjC/direct-method.m @@ -111,7 +111,7 @@ __attribute__((objc_root_class)) // CHECK-LABEL: define hidden void @"\01-[Root getAggregate]"( - (struct my_aggregate_struct)getAggregate __attribute__((objc_direct)) { - // CHECK: ptr noalias sret(%struct.my_aggregate_struct) align 4 [[RETVAL:%[^,]*]], + // CHECK: ptr dead_on_unwind noalias writable sret(%struct.my_aggregate_struct) align 4 [[RETVAL:%[^,]*]], // loading parameters // CHECK-LABEL: entry: diff --git a/clang/test/CodeGenObjC/dllstorage.m b/clang/test/CodeGenObjC/dllstorage.m index 64ba21f9769ae2f444f89c4de475bca25eeb2fbd..f45eb7bb6aee78c47669d7d5ad694a7217ff47ea 100644 --- a/clang/test/CodeGenObjC/dllstorage.m +++ b/clang/test/CodeGenObjC/dllstorage.m @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -triple x86_64-unknown-windows-msvc -fdeclspec -fobjc-runtime=ios -fobjc-exceptions -S -emit-llvm -o - %s | FileCheck -allow-deprecated-dag-overlap -check-prefix CHECK-IR %s +// RUN: %clang_cc1 -triple x86_64-unknown-windows-msvc -fdeclspec -fobjc-runtime=gnustep-2.0 -fobjc-exceptions -S -emit-llvm -o - %s | FileCheck -allow-deprecated-dag-overlap -check-prefix CHECK-NF %s // RUN: %clang_cc1 -triple i686-windows-itanium -fms-extensions -fobjc-runtime=macosx -fdeclspec -fobjc-exceptions -S -emit-llvm -o - %s | FileCheck -allow-deprecated-dag-overlap -check-prefix CHECK-IR %s // RUN: %clang_cc1 -triple i686-windows-itanium -fms-extensions -fobjc-runtime=objfw -fdeclspec -fobjc-exceptions -S -emit-llvm -o - %s | FileCheck -allow-deprecated-dag-overlap -check-prefix CHECK-FW %s @@ -12,6 +13,8 @@ __declspec(dllimport) // CHECK-IR-DAG: @"OBJC_METACLASS_$_I" = external dllimport global %struct._class_t // CHECK-IR-DAG: @"OBJC_CLASS_$_I" = external dllimport global %struct._class_t +// CHECK-NF-DAG: @"$_OBJC_CLASS_I" = external dllimport global ptr + __declspec(dllexport) @interface J : I @end @@ -22,6 +25,9 @@ __declspec(dllexport) // CHECK-FW-DAG: @_OBJC_METACLASS_J = dso_local dllexport global // CHECK-FW-DAG: @_OBJC_CLASS_J = dso_local dllexport global +// CHECK-NF-DAG: @"$_OBJC_METACLASS_J" = internal global +// CHECK-NF-DAG: @"$_OBJC_CLASS_J" = dllexport global + @implementation J { id _ivar; } @@ -29,6 +35,8 @@ __declspec(dllexport) // CHECK-IR-DAG: @"OBJC_IVAR_$_J._ivar" = global i32 +// CHECK-NF-DAG: @"__objc_ivar_offset_J._ivar.@" = hidden global i32 + @interface K : J @end @@ -38,6 +46,9 @@ __declspec(dllexport) // CHECK-FW-DAG: @_OBJC_METACLASS_K = dso_local global // CHECK-FW-DAG: @_OBJC_CLASS_K = dso_local global +// CHECK-NF-DAG: @"$_OBJC_METACLASS_K" = internal global +// CHECK-NF-DAG: @"$_OBJC_CLASS_K" = global + @implementation K { id _ivar; } @@ -45,6 +56,8 @@ __declspec(dllexport) // CHECK-IR-DAG: @"OBJC_IVAR_$_K._ivar" = global i32 +// CHECK-NF-DAG: @"__objc_ivar_offset_K._ivar.@" = hidden global i32 + __declspec(dllexport) @interface L : K @end @@ -55,6 +68,9 @@ __declspec(dllexport) // CHECK-FW-DAG: @_OBJC_METACLASS_L = dso_local dllexport global // CHECK-FW-DAG: @_OBJC_CLASS_L = dso_local dllexport global +// CHECK-NF-DAG: @"$_OBJC_METACLASS_L" = internal global +// CHECK-NF-DAG: @"$_OBJC_CLASS_L" = dllexport global + @implementation L { id _none; @@ -78,6 +94,12 @@ __declspec(dllexport) // CHECK-IR-DAG: @"OBJC_IVAR_$_L._package" = global i32 // CHECK-IR-DAG: @"OBJC_IVAR_$_L._private" = global i32 +// CHECK-NF-DAG: @"__objc_ivar_offset_L._none.@" = hidden global i32 +// CHECK-NF-DAG: @"__objc_ivar_offset_L._public.@" = dso_local dllexport global i32 +// CHECK-NF-DAG: @"__objc_ivar_offset_L._protected.@" = dso_local dllexport global i32 +// CHECK-NF-DAG: @"__objc_ivar_offset_L._package.@" = hidden global i32 +// CHECK-NF-DAG: @"__objc_ivar_offset_L._private.@" = hidden global i32 + __declspec(dllimport) @interface M : I { @public @@ -89,6 +111,9 @@ __declspec(dllimport) // CHECK-IR-DAG: @"OBJC_IVAR_$_M._ivar" = external dllimport global i32 +// CHECK-NF-DAG: @"$_OBJC_REF_CLASS_M" = external dllimport global ptr +// CHECK-NF-DAG: @"__objc_ivar_offset_M._ivar.@" = external global i32 + __declspec(dllexport) __attribute__((__objc_exception__)) @interface N : I @@ -97,6 +122,8 @@ __attribute__((__objc_exception__)) // CHECK-FW-DAG: @_OBJC_METACLASS_N = dso_local dllexport global // CHECK-FW-DAG: @_OBJC_CLASS_N = dso_local dllexport global +// CHECK-NF-DAG: @"$_OBJC_CLASS_N" = dllexport global + @implementation N : I @end @@ -124,6 +151,8 @@ id f(Q *q) { // CHECK-IR-DAG: @"OBJC_IVAR_$_M._ivar" = external dllimport global i32 +// CHECK-NF-DAG: @"__objc_ivar_offset_M._ivar.@" = external global i32 + int g(void) { @autoreleasepool { M *mi = [M new]; diff --git a/clang/test/CodeGenObjC/encode-test-6.m b/clang/test/CodeGenObjC/encode-test-6.m index 261eb7fb3368b2dfe84716c69a377a21e9c88479..c32f8f24c00097b0718e281e6a72584da85963b8 100644 --- a/clang/test/CodeGenObjC/encode-test-6.m +++ b/clang/test/CodeGenObjC/encode-test-6.m @@ -1,5 +1,10 @@ -// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -o %t %s -// RUN: FileCheck < %t %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -o - %s | FileCheck -check-prefix CHECK-DWARF %s + +// RUN: %clang_cc1 -triple x86_64-w64-windows-gnu -emit-llvm -fobjc-runtime=gnustep-2.0 -o - %s | FileCheck -check-prefix CHECK-MINGW %s + +// RUN: %clang_cc1 -triple x86_64-windows-msvc -emit-llvm -fobjc-runtime=gnustep-2.0 -o - %s | FileCheck -check-prefix CHECK-MSVC %s + +// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -fobjc-runtime=gnustep-2.0 -o - %s | FileCheck -check-prefix CHECK-ELF %s typedef struct {} Z; @@ -13,8 +18,17 @@ typedef struct {} Z; -(void)foo:(Z)a: (char*)b : (Z)c : (double) d {} @end -// CHECK: private unnamed_addr constant [14 x i8] c"v16@0:8{?=}16 -// CHECK: private unnamed_addr constant [26 x i8] c"v32@0:8{?=}16*16{?=}24d24 +// CHECK-DWARF: private unnamed_addr constant [14 x i8] c"v16@0:8{?=}16 +// CHECK-DWARF: private unnamed_addr constant [26 x i8] c"v32@0:8{?=}16*16{?=}24d24 + +// CHECK-MINGW: @".objc_sel_types_v16@0:8{?\02}16" = linkonce_odr hidden constant [14 x i8] c"v16@0:8{?=}16\00" +// CHECK-MINGW: @".objc_sel_types_v32@0:8{?\02}16*16{?\02}24d24" = linkonce_odr hidden constant [26 x i8] c"v32@0:8{?=}16*16{?=}24d24\00" + +// CHECK-MSVC: @".objc_sel_types_v20@0:8{?\02}16" = linkonce_odr hidden constant [14 x i8] c"v20@0:8{?=}16\00" +// CHECK-MSVC: @".objc_sel_types_v40@0:8{?\02}16*20{?\02}28d32" = linkonce_odr hidden constant [26 x i8] c"v40@0:8{?=}16*20{?=}28d32\00" + +// CHECK-ELF: @".objc_sel_types_v16\010:8{?=}16" = linkonce_odr hidden constant [14 x i8] c"v16@0:8{?=}16\00" +// CHECK-ELF: @".objc_sel_types_v32\010:8{?=}16*16{?=}24d24" = linkonce_odr hidden constant [26 x i8] c"v32@0:8{?=}16*16{?=}24d24\00" @interface NSObject @end @@ -31,7 +45,10 @@ typedef BABugExample BABugExampleRedefinition; @synthesize property = _property; @end -// CHECK: private unnamed_addr constant [8 x i8] c"@16 +// CHECK-DWARF: private unnamed_addr constant [8 x i8] c"@16 +// CHECK-MINGW: @".objc_sel_types_@16@0:8" = linkonce_odr hidden constant [8 x i8] c"@16@0:8\00" +// CHECK-MSVC: @".objc_sel_types_@16@0:8" = linkonce_odr hidden constant [8 x i8] c"@16@0:8\00" +// CHECK-ELF @".objc_sel_types_\0116\010:8" = linkonce_odr hidden constant [8 x i8] c"@16@0:8\00" @class SCNCamera; typedef SCNCamera C3DCamera; @@ -48,7 +65,10 @@ typedef struct C3DCameraStorage _storage; } @end -// CHECK: private unnamed_addr constant [39 x i8] c"{?=\22presentationInstance\22@\22SCNCamera\22}\00" +// CHECK-DWARF: private unnamed_addr constant [39 x i8] c"{?=\22presentationInstance\22@\22SCNCamera\22}\00" +// CHECK-MINGW: @"__objc_ivar_offset_SCNCamera._storage.{?\02@}" +// CHECK-MSVC: @"__objc_ivar_offset_SCNCamera._storage.{?\02@}" +// CHECK-ELF: @"__objc_ivar_offset_SCNCamera._storage.{?=\01}" int i; typeof(@encode(typeof(i))) e = @encode(typeof(i)); @@ -56,6 +76,10 @@ const char * Test(void) { return e; } -// CHECK: @e ={{.*}} global [2 x i8] c"i\00", align 1 -// CHECK: define{{.*}} ptr @Test() -// CHECK: ret ptr @e +// CHECK-DWARF: @e ={{.*}} global [2 x i8] c"i\00", align 1 +// CHECK-DWARF: define{{.*}} ptr @Test() +// CHECK-DWARF: ret ptr @e + +// CHECK-MSVC: @e = dso_local global [2 x i8] c"i\00", align 1 +// CHECK-MINGW: @e = dso_local global [2 x i8] c"i\00", align 1 +// CHECK-ELF: @e = global [2 x i8] c"i\00", align 1 diff --git a/clang/test/CodeGenObjC/exceptions-personality.m b/clang/test/CodeGenObjC/exceptions-personality.m new file mode 100644 index 0000000000000000000000000000000000000000..9c25ee38b6d7cf56b428fe03c18b8a2fe75fa604 --- /dev/null +++ b/clang/test/CodeGenObjC/exceptions-personality.m @@ -0,0 +1,53 @@ +// RUN: %clang_cc1 -triple x86_64-w64-windows-gnu -emit-llvm -fobjc-runtime=gnustep-2.0 -fexceptions -fobjc-exceptions -o %t %s +// RUN: FileCheck --check-prefixes=CHECK-MINGW-OBJC2 < %t %s + +// RUN: %clang_cc1 -triple x86_64-w64-windows-gnu -emit-llvm -fobjc-runtime=gcc -fexceptions -fobjc-exceptions -o %t %s +// RUN: FileCheck --check-prefixes=CHECK-MINGW-GCC < %t %s + +// RUN: %clang_cc1 -triple x86_64-w64-windows-msvc -emit-llvm -fobjc-runtime=gnustep-2.0 -fexceptions -fobjc-exceptions -o %t %s +// RUN: FileCheck --check-prefixes=CHECK-MSVC-OBJC2 < %t %s + +// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-llvm -fobjc-runtime=gnustep-2.0 -fexceptions -fobjc-exceptions -o %t %s +// RUN: FileCheck --check-prefixes=CHECK-LINUX-OBJC2 < %t %s + +// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-llvm -fobjc-runtime=gcc -fexceptions -fobjc-exceptions -o %t %s +// RUN: FileCheck --check-prefixes=CHECK-LINUX-GCC < %t %s +@interface Foo @end + +void throwing(void) { + @try + { + // CHECK-MINGW-OBJC2: personality ptr @__gxx_personality_seh0 + // CHECK-MINGW-OBJC2: invoke void @objc_exception_throw + + // CHECK-MINGW-GCC: personality ptr @__gnu_objc_personality_v0 + // CHECK-MINGW-GCC: invoke void @objc_exception_throw + + // CHECK-MSVC-OBJC2: personality ptr @__CxxFrameHandler3 + // CHECK-MSVC-OBJC2: invoke void @objc_exception_throw + + // CHECK-LINUX-OBJC2: personality ptr @__gnustep_objc_personality_v0 + // CHECK-LINUX-OBJC2: invoke void @objc_exception_throw + + // CHECK-LINUX-GCC: personality ptr @__gnu_objc_personality_v0 + @throw(@"error!"); + } + @catch(...) + { + // CHECK-MINGW-OBJC2: call ptr @__cxa_begin_catch + // CHECK-MINGW-OBJC2: invoke ptr @__cxa_rethrow + // CHECK-MINGW-OBJC2: invoke void @__cxa_end_catch + + // CHECK-MINGW-GCC: call void @objc_exception_throw + + // CHECK-MSVC-OBJC2: call void @objc_exception_rethrow + + // CHECK-LINUX-OBJC2: call ptr @objc_begin_catch + // CHECK-LINUX-OBJC2: invoke void @objc_exception_throw + // CHECK-LINUX-OBJC2: invoke void @objc_end_catch() + + // CHECK-LINUX-GCC: invoke void @objc_exception_throw + + @throw; + } +} diff --git a/clang/test/CodeGenObjC/nontrivial-c-struct-exception.m b/clang/test/CodeGenObjC/nontrivial-c-struct-exception.m index 0159e111d9ad025c3d17b717739c23eb3f0a55ba..d2a954ae26a04dafb2533598d1940262071a4121 100644 --- a/clang/test/CodeGenObjC/nontrivial-c-struct-exception.m +++ b/clang/test/CodeGenObjC/nontrivial-c-struct-exception.m @@ -39,8 +39,8 @@ void testStrongException(void) { // CHECK: define{{.*}} void @testWeakException() // CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_WEAK]], align 8 // CHECK: %[[AGG_TMP1:.*]] = alloca %[[STRUCT_WEAK]], align 8 -// CHECK: call void @genWeak(ptr sret(%[[STRUCT_WEAK]]) align 8 %[[AGG_TMP]]) -// CHECK: invoke void @genWeak(ptr sret(%[[STRUCT_WEAK]]) align 8 %[[AGG_TMP1]]) +// CHECK: call void @genWeak(ptr dead_on_unwind writable sret(%[[STRUCT_WEAK]]) align 8 %[[AGG_TMP]]) +// CHECK: invoke void @genWeak(ptr dead_on_unwind writable sret(%[[STRUCT_WEAK]]) align 8 %[[AGG_TMP1]]) // CHECK: call void @calleeWeak(ptr noundef %[[AGG_TMP]], ptr noundef %[[AGG_TMP1]]) // CHECK: ret void diff --git a/clang/test/CodeGenObjC/objc-non-trivial-struct-nrvo.m b/clang/test/CodeGenObjC/objc-non-trivial-struct-nrvo.m index effba8c9584418b54991ed10d271dff574305065..cc697b0e15373b6f9daecbba082b1d3c73e5b6bd 100644 --- a/clang/test/CodeGenObjC/objc-non-trivial-struct-nrvo.m +++ b/clang/test/CodeGenObjC/objc-non-trivial-struct-nrvo.m @@ -37,7 +37,7 @@ Trivial testTrivial(void) { void func1(TrivialBig *); -// CHECK: define{{.*}} void @testTrivialBig(ptr noalias sret(%[[STRUCT_TRIVIALBIG]]) align 4 %[[AGG_RESULT:.*]]) +// CHECK: define{{.*}} void @testTrivialBig(ptr dead_on_unwind noalias writable sret(%[[STRUCT_TRIVIALBIG]]) align 4 %[[AGG_RESULT:.*]]) // CHECK: call void @func1(ptr noundef %[[AGG_RESULT]]) // CHECK-NEXT: ret void @@ -67,7 +67,7 @@ Strong testStrong(void) { return a; } -// CHECK: define{{.*}} void @testWeak(ptr noalias sret(%[[STRUCT_WEAK]]) align 8 %[[AGG_RESULT:.*]]) +// CHECK: define{{.*}} void @testWeak(ptr dead_on_unwind noalias writable sret(%[[STRUCT_WEAK]]) align 8 %[[AGG_RESULT:.*]]) // CHECK: %[[NRVO:.*]] = alloca i1, align 1 // CHECK: call void @__default_constructor_8_w0(ptr %[[AGG_RESULT]]) // CHECK: store i1 true, ptr %[[NRVO]], align 1 @@ -101,7 +101,7 @@ Weak testWeak2(int c) { return b; } -// CHECK: define internal void @"\01-[C1 foo1]"(ptr noalias sret(%[[STRUCT_WEAK]]) align 8 %[[AGG_RESULT:.*]], ptr noundef %{{.*}}, ptr noundef %{{.*}}) +// CHECK: define internal void @"\01-[C1 foo1]"(ptr dead_on_unwind noalias writable sret(%[[STRUCT_WEAK]]) align 8 %[[AGG_RESULT:.*]], ptr noundef %{{.*}}, ptr noundef %{{.*}}) // CHECK: %[[NRVO:.*]] = alloca i1, align 1 // CHECK: call void @__default_constructor_8_w0(ptr %[[AGG_RESULT]]) // CHECK: store i1 true, ptr %[[NRVO]], align 1 diff --git a/clang/test/CodeGenObjC/personality.m b/clang/test/CodeGenObjC/personality.m index 6ec67ace3f1ac31505c8a841025c22d6951475f9..ede0aa34eaf62560ecaa4e99fd05e7b71aa9beb0 100644 --- a/clang/test/CodeGenObjC/personality.m +++ b/clang/test/CodeGenObjC/personality.m @@ -27,8 +27,8 @@ // RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fobjc-exceptions -fobjc-runtime=ios -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS // RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fobjc-exceptions -fobjc-runtime=macosx -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS // RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fobjc-exceptions -fobjc-runtime=watchos -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS -// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fobjc-exceptions -fobjc-runtime=gnustep-1.7 -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GNUSTEP-1_7 -// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fobjc-exceptions -fobjc-runtime=gnustep -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GNUSTEP +// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fobjc-exceptions -fobjc-runtime=gnustep-1.7 -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-GNU +// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fobjc-exceptions -fobjc-runtime=gnustep -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-GNU // RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fobjc-exceptions -fobjc-runtime=gcc -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GCC // RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -exception-model=seh -fobjc-exceptions -fobjc-runtime=gcc -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GCC-SEH // RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -exception-model=sjlj -fobjc-exceptions -fobjc-runtime=gcc -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GCC-SJLJ @@ -50,6 +50,7 @@ void g(void); // CHECK-OBJFW-SJLJ: personality ptr @__gnu_objc_personality_sj0 // CHECK-WIN-MSVC: personality ptr @__CxxFrameHandler3 +// CHECK-WIN-GNU: personality ptr @__gxx_personality_seh0 // CHECK-MACOSX-FRAGILE-MINGW-DWARF: personality ptr @__gcc_personality_v0 // CHECK-MACOSX-FRAGILE-MINGW-SEH: personality ptr @__gcc_personality_seh0 diff --git a/clang/test/CodeGenObjC/stret-1.m b/clang/test/CodeGenObjC/stret-1.m index fb1b4abe70f4c41bf2cb2838eca1bcc4e94c0d61..20e26af72c6f99b106d2a6f2906e47f9fdfcb07b 100644 --- a/clang/test/CodeGenObjC/stret-1.m +++ b/clang/test/CodeGenObjC/stret-1.m @@ -13,18 +13,18 @@ int main(int argc, const char **argv) { struct stret s; s = [(id)(argc&~255) method]; - // CHECK: call void @objc_msgSend(ptr sret(%struct.stret) align 4 [[T0:%[^,]+]] + // CHECK: call void @objc_msgSend(ptr dead_on_unwind writable sret(%struct.stret) align 4 [[T0:%[^,]+]] // CHECK: call void @llvm.memset.p0.i64(ptr align 4 [[T0]], i8 0, i64 400, i1 false) s = [Test method]; - // CHECK: call void @objc_msgSend(ptr sret(%struct.stret) align 4 [[T1:%[^,]+]] + // CHECK: call void @objc_msgSend(ptr dead_on_unwind writable sret(%struct.stret) align 4 [[T1:%[^,]+]] // CHECK-NOT: call void @llvm.memset.p0.i64( [(id)(argc&~255) method]; - // CHECK: call void @objc_msgSend(ptr sret(%struct.stret) align 4 [[T1:%[^,]+]] + // CHECK: call void @objc_msgSend(ptr dead_on_unwind writable sret(%struct.stret) align 4 [[T1:%[^,]+]] // CHECK-NOT: call void @llvm.memset.p0.i64( [Test method]; - // CHECK: call void @objc_msgSend(ptr sret(%struct.stret) align 4 [[T1:%[^,]+]] + // CHECK: call void @objc_msgSend(ptr dead_on_unwind writable sret(%struct.stret) align 4 [[T1:%[^,]+]] // CHECK-NOT: call void @llvm.memset.p0.i64( } diff --git a/clang/test/CodeGenObjC/stret_lookup.m b/clang/test/CodeGenObjC/stret_lookup.m index 1a4665d4309db6c4cecb274d9a6b65ff3613c5df..315a1627da5b795f1fdb1fa1920467d173443ae5 100644 --- a/clang/test/CodeGenObjC/stret_lookup.m +++ b/clang/test/CodeGenObjC/stret_lookup.m @@ -20,8 +20,8 @@ void test0(void) { // HASSTRET-LABEL: define{{.*}} void @test0() // HASSTRET: [[T0:%.*]] = call ptr @objc_msg_lookup_stret(ptr @_OBJC_CLASS_Test0, -// HASSTRET-NEXT: call void [[T0]](ptr sret(%struct.test) {{.*}}, ptr noundef @_OBJC_CLASS_Test0, +// HASSTRET-NEXT: call void [[T0]](ptr dead_on_unwind writable sret(%struct.test) {{.*}}, ptr noundef @_OBJC_CLASS_Test0, // NOSTRET-LABEL: define{{.*}} void @test0() // NOSTRET: [[T0:%.*]] = call ptr @objc_msg_lookup(ptr -// NOSTRET-NEXT: call void [[T0]](ptr sret(%struct.test) {{.*}}, ptr {{.*}}, ptr noundef +// NOSTRET-NEXT: call void [[T0]](ptr dead_on_unwind writable sret(%struct.test) {{.*}}, ptr {{.*}}, ptr noundef diff --git a/clang/test/CodeGenObjC/weak-in-c-struct.m b/clang/test/CodeGenObjC/weak-in-c-struct.m index 3ec08c2b9f18b17681c85ed4de2c52330794b69b..be80edd1ff11ddcb21da6de83c0e66107b13e424 100644 --- a/clang/test/CodeGenObjC/weak-in-c-struct.m +++ b/clang/test/CodeGenObjC/weak-in-c-struct.m @@ -149,7 +149,7 @@ void test_argument_Weak(Weak *a) { calleeWeak(*a); } -// COMMON: define{{.*}} void @test_return_Weak(ptr noalias sret(%[[STRUCT_WEAK]]) align {{.*}} %[[AGG_RESULT:.*]], ptr noundef %[[A:.*]]) +// COMMON: define{{.*}} void @test_return_Weak(ptr dead_on_unwind noalias writable sret(%[[STRUCT_WEAK]]) align {{.*}} %[[AGG_RESULT:.*]], ptr noundef %[[A:.*]]) // COMMON: %[[A_ADDR:.*]] = alloca ptr // COMMON: store ptr %[[A]], ptr %[[A_ADDR]] // COMMON: %[[V0:.*]] = load ptr, ptr %[[A_ADDR]] diff --git a/clang/test/CodeGenObjC/x86_64-struct-return-gc.m b/clang/test/CodeGenObjC/x86_64-struct-return-gc.m index 6bc2929c7596f3f0cc0dc6806cfc75dc32ae0eb4..bc0b88ff037ffdc731cee165c62deb1992ac6e5d 100644 --- a/clang/test/CodeGenObjC/x86_64-struct-return-gc.m +++ b/clang/test/CodeGenObjC/x86_64-struct-return-gc.m @@ -25,7 +25,7 @@ struct Indirect indirect_func(void); void Indirect_test(void) { struct Indirect i; - // CHECK: call void @indirect_func(ptr sret + // CHECK: call void @indirect_func(ptr dead_on_unwind writable sret // CHECK: call ptr @objc_memmove_collectable( i = indirect_func(); } diff --git a/clang/test/CodeGenObjCXX/objc-struct-cxx-abi.mm b/clang/test/CodeGenObjCXX/objc-struct-cxx-abi.mm index ed35eb1a7983adf1496211837c4bf2e2c4865094..f9f783ff5cacaf7798d1a00b2c6c054959d13434 100644 --- a/clang/test/CodeGenObjCXX/objc-struct-cxx-abi.mm +++ b/clang/test/CodeGenObjCXX/objc-struct-cxx-abi.mm @@ -96,7 +96,7 @@ void testCallStrongWeak(StrongWeak *a) { testParamStrongWeak(*a); } -// CHECK: define{{.*}} void @_Z20testReturnStrongWeakP10StrongWeak(ptr noalias sret(%[[STRUCT_STRONGWEAK:.*]]) align 8 %[[AGG_RESULT:.*]], ptr noundef %[[A:.*]]) +// CHECK: define{{.*}} void @_Z20testReturnStrongWeakP10StrongWeak(ptr dead_on_unwind noalias writable sret(%[[STRUCT_STRONGWEAK:.*]]) align 8 %[[AGG_RESULT:.*]], ptr noundef %[[A:.*]]) // CHECK: %[[A_ADDR:a.addr]] = alloca ptr, align 8 // CHECK: store ptr %[[A]], ptr %[[A_ADDR]], align 8 // CHECK: %[[V0:.*]] = load ptr, ptr %[[A_ADDR]], align 8 diff --git a/clang/test/CodeGenObjCXX/personality.mm b/clang/test/CodeGenObjCXX/personality.mm index c6debe6f60c2a25cdc7e087bb1d3eadf4fa45df3..b8c7af962bd0bd6cb06b36a143c22bffa1d0aed5 100644 --- a/clang/test/CodeGenObjCXX/personality.mm +++ b/clang/test/CodeGenObjCXX/personality.mm @@ -50,8 +50,8 @@ // RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -exception-model=dwarf -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=watchos -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS // RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -exception-model=seh -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=watchos -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS // RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -exception-model=sjlj -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=watchos -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS -// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=gnustep-1.7 -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GNUSTEP-1_7 -// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=gnustep -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GNUSTEP +// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=gnustep-1.7 -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-GNU +// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=gnustep -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-GNU // RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=gcc -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GCC // RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -exception-model=dwarf -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=gcc -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GCC // RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -exception-model=seh -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=gcc -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GCC-SEH @@ -81,6 +81,7 @@ void g(void); // CHECK-OBJFW-SJLJ: personality ptr @__gnu_objc_personality_sj0 // CHECK-WIN-MSVC: personality ptr @__CxxFrameHandler3 +// CHECK-WIN-GNU: personality ptr @__gxx_personality_seh0 void f(void) { @try { diff --git a/clang/test/CodeGenOpenCL/addr-space-struct-arg.cl b/clang/test/CodeGenOpenCL/addr-space-struct-arg.cl index 054fdc0662228f04fb087f657442eb0ceb2b61cb..385f8a753cd8e9ec6031d70a7767592bed309b5b 100644 --- a/clang/test/CodeGenOpenCL/addr-space-struct-arg.cl +++ b/clang/test/CodeGenOpenCL/addr-space-struct-arg.cl @@ -45,7 +45,7 @@ struct LargeStructTwoMember { struct LargeStructOneMember g_s; #endif -// X86-LABEL: define{{.*}} void @foo(ptr noalias sret(%struct.Mat4X4) align 4 %agg.result, ptr noundef byval(%struct.Mat3X3) align 4 %in) +// X86-LABEL: define{{.*}} void @foo(ptr dead_on_unwind noalias writable sret(%struct.Mat4X4) align 4 %agg.result, ptr noundef byval(%struct.Mat3X3) align 4 %in) // AMDGCN-LABEL: define{{.*}} %struct.Mat4X4 @foo([9 x i32] %in.coerce) Mat4X4 __attribute__((noinline)) foo(Mat3X3 in) { Mat4X4 out; @@ -65,8 +65,8 @@ kernel void ker(global Mat3X3 *in, global Mat4X4 *out) { out[0] = foo(in[1]); } -// X86-LABEL: define{{.*}} void @foo_large(ptr noalias sret(%struct.Mat64X64) align 4 %agg.result, ptr noundef byval(%struct.Mat32X32) align 4 %in) -// AMDGCN-LABEL: define{{.*}} void @foo_large(ptr addrspace(5) noalias sret(%struct.Mat64X64) align 4 %agg.result, ptr addrspace(5) noundef byref(%struct.Mat32X32) align 4 %{{.*}} +// X86-LABEL: define{{.*}} void @foo_large(ptr dead_on_unwind noalias writable sret(%struct.Mat64X64) align 4 %agg.result, ptr noundef byval(%struct.Mat32X32) align 4 %in) +// AMDGCN-LABEL: define{{.*}} void @foo_large(ptr addrspace(5) dead_on_unwind noalias writable sret(%struct.Mat64X64) align 4 %agg.result, ptr addrspace(5) noundef byref(%struct.Mat32X32) align 4 %{{.*}} // AMDGCN: %in = alloca %struct.Mat32X32, align 4, addrspace(5) // AMDGCN-NEXT: call void @llvm.memcpy.p5.p5.i64(ptr addrspace(5) align 4 %in, ptr addrspace(5) align 4 %{{.*}}, i64 4096, i1 false) Mat64X64 __attribute__((noinline)) foo_large(Mat32X32 in) { diff --git a/clang/test/CodeGenOpenCL/amdgpu-abi-struct-arg-byref.cl b/clang/test/CodeGenOpenCL/amdgpu-abi-struct-arg-byref.cl index 52fad9599de041a3a4283b5501d1daa8eabb5f4c..fa83a38a01b0a1af6a26ae9cc0d0d12795b01400 100644 --- a/clang/test/CodeGenOpenCL/amdgpu-abi-struct-arg-byref.cl +++ b/clang/test/CodeGenOpenCL/amdgpu-abi-struct-arg-byref.cl @@ -86,7 +86,7 @@ kernel void ker(global Mat3X3 *in, global Mat4X4 *out) { } // AMDGCN-LABEL: define dso_local void @foo_large -// AMDGCN-SAME: (ptr addrspace(5) noalias sret([[STRUCT_MAT64X64:%.*]]) align 4 [[AGG_RESULT:%.*]], ptr addrspace(5) noundef byref([[STRUCT_MAT32X32:%.*]]) align 4 [[TMP0:%.*]]) #[[ATTR0]] { +// AMDGCN-SAME: (ptr addrspace(5) dead_on_unwind noalias writable sret([[STRUCT_MAT64X64:%.*]]) align 4 [[AGG_RESULT:%.*]], ptr addrspace(5) noundef byref([[STRUCT_MAT32X32:%.*]]) align 4 [[TMP0:%.*]]) #[[ATTR0]] { // AMDGCN-NEXT: entry: // AMDGCN-NEXT: [[IN:%.*]] = alloca [[STRUCT_MAT32X32]], align 4, addrspace(5) // AMDGCN-NEXT: call void @llvm.memcpy.p5.p5.i64(ptr addrspace(5) align 4 [[IN]], ptr addrspace(5) align 4 [[TMP0]], i64 4096, i1 false) @@ -111,7 +111,7 @@ Mat64X64 __attribute__((noinline)) foo_large(Mat32X32 in) { // AMDGCN-NEXT: [[TMP1:%.*]] = load ptr addrspace(1), ptr addrspace(5) [[IN_ADDR]], align 8 // AMDGCN-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds [[STRUCT_MAT32X32]], ptr addrspace(1) [[TMP1]], i64 1 // AMDGCN-NEXT: call void @llvm.memcpy.p5.p1.i64(ptr addrspace(5) align 4 [[BYVAL_TEMP]], ptr addrspace(1) align 4 [[ARRAYIDX1]], i64 4096, i1 false) -// AMDGCN-NEXT: call void @foo_large(ptr addrspace(5) sret([[STRUCT_MAT64X64]]) align 4 [[TMP]], ptr addrspace(5) noundef byref([[STRUCT_MAT32X32]]) align 4 [[BYVAL_TEMP]]) #[[ATTR3]] +// AMDGCN-NEXT: call void @foo_large(ptr addrspace(5) dead_on_unwind writable sret([[STRUCT_MAT64X64]]) align 4 [[TMP]], ptr addrspace(5) noundef byref([[STRUCT_MAT32X32]]) align 4 [[BYVAL_TEMP]]) #[[ATTR3]] // AMDGCN-NEXT: call void @llvm.memcpy.p1.p5.i64(ptr addrspace(1) align 4 [[ARRAYIDX]], ptr addrspace(5) align 4 [[TMP]], i64 16384, i1 false) // AMDGCN-NEXT: ret void // diff --git a/clang/test/CodeGenOpenCL/amdgpu-abi-struct-coerce.cl b/clang/test/CodeGenOpenCL/amdgpu-abi-struct-coerce.cl index 665609e54a83e971ec04c514f17583c1560b4c89..90e4b65c6f1f73952bc77610c0cccef36f29ee04 100644 --- a/clang/test/CodeGenOpenCL/amdgpu-abi-struct-coerce.cl +++ b/clang/test/CodeGenOpenCL/amdgpu-abi-struct-coerce.cl @@ -402,14 +402,14 @@ struct_arr16 func_ret_struct_arr16() return s; } -// CHECK: define{{.*}} void @func_ret_struct_arr32(ptr addrspace(5) noalias nocapture writeonly sret(%struct.struct_arr32) align 4 %agg.result) +// CHECK: define{{.*}} void @func_ret_struct_arr32(ptr addrspace(5) dead_on_unwind noalias nocapture writable writeonly sret(%struct.struct_arr32) align 4 %agg.result) struct_arr32 func_ret_struct_arr32() { struct_arr32 s = { 0 }; return s; } -// CHECK: define{{.*}} void @func_ret_struct_arr33(ptr addrspace(5) noalias nocapture writeonly sret(%struct.struct_arr33) align 4 %agg.result) +// CHECK: define{{.*}} void @func_ret_struct_arr33(ptr addrspace(5) dead_on_unwind noalias nocapture writable writeonly sret(%struct.struct_arr33) align 4 %agg.result) struct_arr33 func_ret_struct_arr33() { struct_arr33 s = { 0 }; @@ -438,7 +438,7 @@ different_size_type_pair func_different_size_type_pair_ret() return s; } -// CHECK: define{{.*}} void @func_flexible_array_ret(ptr addrspace(5) noalias nocapture writeonly sret(%struct.flexible_array) align 4 %agg.result) +// CHECK: define{{.*}} void @func_flexible_array_ret(ptr addrspace(5) dead_on_unwind noalias nocapture writable writeonly sret(%struct.flexible_array) align 4 %agg.result) flexible_array func_flexible_array_ret() { flexible_array s = { 0 }; diff --git a/clang/test/CodeGenOpenCLCXX/addrspace-of-this.clcpp b/clang/test/CodeGenOpenCLCXX/addrspace-of-this.clcpp index 1c09743d3c8dbef29eb7efdb232038b37b23b29c..2f1b6c196fd519aec83f3df3e35fa21093da7c17 100644 --- a/clang/test/CodeGenOpenCLCXX/addrspace-of-this.clcpp +++ b/clang/test/CodeGenOpenCLCXX/addrspace-of-this.clcpp @@ -111,7 +111,7 @@ __kernel void test__global() { // Test the address space of 'this' when invoking the operator+ // COMMON: [[C1GEN:%[.a-z0-9]+]] = addrspacecast ptr %c1 to ptr addrspace(4) // COMMON: [[C2GEN:%[.a-z0-9]+]] = addrspacecast ptr %c2 to ptr addrspace(4) -// COMMON: call spir_func void @_ZNU3AS41CplERU3AS4KS_(ptr sret(%class.C) align 4 %c3, ptr addrspace(4) {{[^,]*}} [[C1GEN]], ptr addrspace(4) noundef align 4 dereferenceable(4) [[C2GEN]]) +// COMMON: call spir_func void @_ZNU3AS41CplERU3AS4KS_(ptr dead_on_unwind writable sret(%class.C) align 4 %c3, ptr addrspace(4) {{[^,]*}} [[C1GEN]], ptr addrspace(4) noundef align 4 dereferenceable(4) [[C2GEN]]) // Test the address space of 'this' when invoking the move constructor // COMMON: [[C4GEN:%[.a-z0-9]+]] = addrspacecast ptr %c4 to ptr addrspace(4) @@ -127,7 +127,7 @@ __kernel void test__global() { // Tests address space of inline members //COMMON: @_ZNU3AS41C3getEv(ptr addrspace(4) {{[^,]*}} %this) -//COMMON: @_ZNU3AS41CplERU3AS4KS_(ptr noalias sret(%class.C) align 4 %agg.result, ptr addrspace(4) {{[^,]*}} %this +//COMMON: @_ZNU3AS41CplERU3AS4KS_(ptr dead_on_unwind noalias writable sret(%class.C) align 4 %agg.result, ptr addrspace(4) {{[^,]*}} %this #define TEST(AS) \ __kernel void test##AS() { \ AS C c; \ diff --git a/clang/test/CoverageMapping/if.cpp b/clang/test/CoverageMapping/if.cpp index 65e3d62df79db4cc177071f8f0320bd5b8ab5079..92d560be01f3b7f141b1ac8e10b080d018d048c8 100644 --- a/clang/test/CoverageMapping/if.cpp +++ b/clang/test/CoverageMapping/if.cpp @@ -23,19 +23,49 @@ void foo() { // CHECK-NEXT: Gap,File 0, [[@LINE+1]]:21 -> [[@ } // CHECK-NEXT: [[@LINE-2]]:9 -> [[@LINE-1]]:5 = #1 // CHECK-NEXT: [[@LINE-2]]:5 -> [[@LINE-2]]:8 = #1 -// FIXME: Do not generate coverage for discarded branches in if consteval and if constexpr statements -constexpr int check_consteval(int i) { - if consteval { - i++; - } - if !consteval { - i++; - } - if consteval { - return 42; - } else { - return i; - } +// FIXME: Do not generate coverage for discarded branches in if constexpr +// CHECK-LABEL: _Z30check_constexpr_true_with_elsei: +int check_constexpr_true_with_else(int i) { // CHECK-NEXT: [[@LINE]]:{{[0-9]+}} -> {{[0-9]+}}:2 = #0 + // CHECK-NEXT: [[@LINE+2]]:16 -> [[@LINE+2]]:20 = #0 + // CHECK-NEXT: Branch,File 0, [[@LINE+1]]:16 -> [[@LINE+1]]:20 = 0, 0 + if constexpr(true) { // CHECK-NEXT: Gap,File 0, [[@LINE]]:21 -> [[@LINE]]:22 = #1 + i *= 3; // CHECK-NEXT: [[@LINE-1]]:22 -> [[@LINE+1]]:4 = #1 + } else { // CHECK-NEXT: Gap,File 0, [[@LINE]]:4 -> [[@LINE]]:10 = (#0 - #1) + i *= 5; // CHECK-NEXT: [[@LINE-1]]:10 -> [[@LINE+1]]:4 = (#0 - #1) + } + return i; +} + +// CHECK-LABEL: _Z33check_constexpr_true_without_elsei: +int check_constexpr_true_without_else(int i) { // CHECK-NEXT: [[@LINE]]:{{[0-9]+}} -> {{[0-9]+}}:2 = #0 + // CHECK-NEXT: [[@LINE+2]]:16 -> [[@LINE+2]]:20 = #0 + // CHECK-NEXT: Branch,File 0, [[@LINE+1]]:16 -> [[@LINE+1]]:20 = 0, 0 + if constexpr(true) { // CHECK-NEXT: Gap,File 0, [[@LINE]]:21 -> [[@LINE]]:22 = #1 + i *= 3; // CHECK-NEXT: [[@LINE-1]]:22 -> [[@LINE+1]]:4 = #1 + } + return i; +} + +// CHECK-LABEL: _Z31check_constexpr_false_with_elsei: +int check_constexpr_false_with_else(int i) { // CHECK-NEXT: [[@LINE]]:{{[0-9]+}} -> {{[0-9]+}}:2 = #0 + // CHECK-NEXT: [[@LINE+2]]:16 -> [[@LINE+2]]:21 = #0 + // CHECK-NEXT: Branch,File 0, [[@LINE+1]]:16 -> [[@LINE+1]]:21 = 0, 0 + if constexpr(false) { // CHECK-NEXT: Gap,File 0, [[@LINE]]:22 -> [[@LINE]]:23 = #1 + i *= 3; // CHECK-NEXT: File 0, [[@LINE-1]]:23 -> [[@LINE+1]]:4 = #1 + } else { // CHECK-NEXT: Gap,File 0, [[@LINE]]:4 -> [[@LINE]]:10 = (#0 - #1) + i *= 5; // CHECK-NEXT: File 0, [[@LINE-1]]:10 -> [[@LINE+1]]:4 = (#0 - #1) + } + return i; +} + +// CHECK-LABEL: _Z34check_constexpr_false_without_elsei: +int check_constexpr_false_without_else(int i) { // CHECK-NEXT: [[@LINE]]:{{[0-9]+}} -> {{[0-9]+}}:2 = #0 + // CHECK-NEXT: [[@LINE+2]]:16 -> [[@LINE+2]]:21 = #0 + // CHECK-NEXT: Branch,File 0, [[@LINE+1]]:16 -> [[@LINE+1]]:21 = 0, 0 + if constexpr(false) { // CHECK-NEXT: Gap,File 0, [[@LINE]]:22 -> [[@LINE]]:23 = #1 + i *= 3; // CHECK-NEXT: File 0, [[@LINE-1]]:23 -> [[@LINE+1]]:4 = #1 + } + return i; } // CHECK-LABEL: main: @@ -75,10 +105,6 @@ int main() { // CHECK: File 0, [[@LINE]]:12 -> {{[0-9]+}}:2 = // CHECK-NEXT: File 0, [[@LINE+1]]:14 -> [[@LINE+1]]:20 = #6 i = i == 0?i + 12:i + 10; // CHECK-NEXT: File 0, [[@LINE]]:21 -> [[@LINE]]:27 = (#0 - #6) - // GH-57377 - constexpr int c_i = check_consteval(0); - check_consteval(i); - // GH-45481 S s; s.the_prop = 0? 1 : 2; // CHECK-NEXT: File 0, [[@LINE]]:16 -> [[@LINE]]:17 = #0 @@ -98,3 +124,51 @@ int main() { // CHECK: File 0, [[@LINE]]:12 -> {{[0-9]+}}:2 = void ternary() { true ? FOO : FOO; // CHECK-NOT: Gap,{{.*}}, [[@LINE]]:8 -> } + +// GH-57377 +// CHECK-LABEL: _Z40check_consteval_with_else_discarded_theni: +// FIXME: Do not generate coverage for discarded branch in if consteval +constexpr int check_consteval_with_else_discarded_then(int i) { // CHECK-NEXT: [[@LINE]]:{{[0-9]+}} -> {{[0-9]+}}:2 = #0 + if consteval { + i *= 3; // CHECK-NEXT: [[@LINE-1]]:16 -> [[@LINE+1]]:4 = #1 + } else { // CHECK-NEXT: Gap,File 0, [[@LINE]]:4 -> [[@LINE]]:10 = #0 + i *= 5; // CHECK-NEXT: [[@LINE-1]]:10 -> [[@LINE+1]]:4 = #0 + } + return i; // CHECK-NEXT: [[@LINE]]:3 -> [[@LINE]]:11 = (#0 + #1) +} + +// CHECK-LABEL: _Z43check_notconsteval_with_else_discarded_elsei: +// FIXME: Do not generate coverage for discarded branch in if consteval +constexpr int check_notconsteval_with_else_discarded_else(int i) { // CHECK-NEXT: [[@LINE]]:{{[0-9]+}} -> {{[0-9]+}}:2 = #0 + if !consteval { + i *= 3; // CHECK-NEXT: [[@LINE-1]]:17 -> [[@LINE+1]]:4 = #0 + } else { // CHECK-NEXT: Gap,File 0, [[@LINE]]:4 -> [[@LINE]]:10 = 0 + i *= 5; // CHECK-NEXT: [[@LINE-1]]:10 -> [[@LINE+1]]:4 = 0 + } + return i; +} + +// CHECK-LABEL: _Z32check_consteval_branch_discardedi: +// FIXME: Do not generate coverage for discarded branch in if consteval +constexpr int check_consteval_branch_discarded(int i) { // CHECK-NEXT: [[@LINE]]:{{[0-9]+}} -> {{[0-9]+}}:2 = #0 + if consteval { + i *= 3; // CHECK-NEXT: [[@LINE-1]]:16 -> [[@LINE+1]]:4 = #1 + } + return i; // CHECK-NEXT: [[@LINE]]:3 -> [[@LINE]]:11 = (#0 + #1) +} + +// CHECK-LABEL: _Z30check_notconsteval_branch_kepti: +constexpr int check_notconsteval_branch_kept(int i) { // CHECK-NEXT: [[@LINE]]:{{[0-9]+}} -> {{[0-9]+}}:2 = #0 + if !consteval { + i *= 3; // CHECK-NEXT: [[@LINE-1]]:17 -> [[@LINE+1]]:4 = #0 + } + return i; +} + +int instantiate_consteval(int i) { + i *= check_consteval_with_else_discarded_then(i); + i *= check_notconsteval_with_else_discarded_else(i); + i *= check_consteval_branch_discarded(i); + i *= check_notconsteval_branch_kept(i); + return i; +} diff --git a/clang/test/Driver/Inputs/fedora_39_tree/usr/lib/gcc/x86_64-linux-gnu/13/crtbegin.o b/clang/test/Driver/Inputs/fedora_39_tree/usr/lib/gcc/x86_64-linux-gnu/13/crtbegin.o new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/clang/test/Driver/Inputs/fedora_39_tree/usr/lib/gcc/x86_64-linux-gnu/13/crtend.o b/clang/test/Driver/Inputs/fedora_39_tree/usr/lib/gcc/x86_64-linux-gnu/13/crtend.o new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/clang/test/Driver/Inputs/fedora_39_tree/usr/lib/gcc/x86_64-linux-gnu/13/crti.o b/clang/test/Driver/Inputs/fedora_39_tree/usr/lib/gcc/x86_64-linux-gnu/13/crti.o new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/clang/test/Driver/Inputs/fedora_39_tree/usr/lib/gcc/x86_64-linux-gnu/13/crtn.o b/clang/test/Driver/Inputs/fedora_39_tree/usr/lib/gcc/x86_64-linux-gnu/13/crtn.o new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/clang/test/Driver/Inputs/fedora_39_tree/usr/lib/gcc/x86_64-redhat-linux/13/crtbegin.o b/clang/test/Driver/Inputs/fedora_39_tree/usr/lib/gcc/x86_64-redhat-linux/13/crtbegin.o new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/clang/test/Driver/Inputs/fedora_39_tree/usr/lib/gcc/x86_64-redhat-linux/13/crtend.o b/clang/test/Driver/Inputs/fedora_39_tree/usr/lib/gcc/x86_64-redhat-linux/13/crtend.o new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/clang/test/Driver/Inputs/fedora_39_tree/usr/lib/gcc/x86_64-redhat-linux/13/crti.o b/clang/test/Driver/Inputs/fedora_39_tree/usr/lib/gcc/x86_64-redhat-linux/13/crti.o new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/clang/test/Driver/Inputs/fedora_39_tree/usr/lib/gcc/x86_64-redhat-linux/13/crtn.o b/clang/test/Driver/Inputs/fedora_39_tree/usr/lib/gcc/x86_64-redhat-linux/13/crtn.o new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/clang/test/Driver/aarch64-fix-cortex-a53-835769.c b/clang/test/Driver/aarch64-fix-cortex-a53-835769.c index a854920f3e6ef3404109f1dfe8ed5e68018ace33..d7a2ad9112611b43fc4db7776f4e2ef44e82136a 100644 --- a/clang/test/Driver/aarch64-fix-cortex-a53-835769.c +++ b/clang/test/Driver/aarch64-fix-cortex-a53-835769.c @@ -5,7 +5,7 @@ // RUN: %clang --target=aarch64-linux-eabi -mno-fix-cortex-a53-835769 %s -### 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-NO %s -// RUN: %clang --target=aarch64-android-eabi %s -### 2>&1 \ +// RUN: %clang --target=aarch64-linux-androideabi %s -### 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-YES %s // RUN: %clang --target=aarch64-fuchsia %s -### 2>&1 \ diff --git a/clang/test/Driver/aarch64-security-options.c b/clang/test/Driver/aarch64-security-options.c index e1f3013c4113729cf75d2de820cb1184011e2d96..146add2d1cf7043e8ba20b2d40df1a18bc896de8 100644 --- a/clang/test/Driver/aarch64-security-options.c +++ b/clang/test/Driver/aarch64-security-options.c @@ -1,17 +1,17 @@ // Check the -msign-return-address= option, which has a required argument to // select scope. // RUN: %clang --target=aarch64 -c %s -### -msign-return-address=none 2>&1 | \ -// RUN: FileCheck %s --check-prefix=RA-OFF --check-prefix=KEY --check-prefix=BTE-OFF --check-prefix=WARN +// RUN: FileCheck %s --check-prefix=RA-OFF --check-prefix=KEY --check-prefix=BTE-OFF --check-prefix=GCS-OFF --check-prefix=WARN // RUN: %clang --target=aarch64 -c %s -### -msign-return-address=non-leaf 2>&1 | \ -// RUN: FileCheck %s --check-prefix=RA-NON-LEAF --check-prefix=KEY-A --check-prefix=BTE-OFF --check-prefix=WARN +// RUN: FileCheck %s --check-prefix=RA-NON-LEAF --check-prefix=KEY-A --check-prefix=BTE-OFF --check-prefix=GCS-OFF --check-prefix=WARN // RUN: %clang --target=aarch64 -c %s -### -msign-return-address=all 2>&1 | \ -// RUN: FileCheck %s --check-prefix=RA-ALL --check-prefix=KEY-A --check-prefix=BTE-OFF --check-prefix=WARN +// RUN: FileCheck %s --check-prefix=RA-ALL --check-prefix=KEY-A --check-prefix=BTE-OFF --check-prefix=GCS-OFF --check-prefix=WARN // -mbranch-protection with standard // RUN: %clang --target=aarch64 -c %s -### -mbranch-protection=standard 2>&1 | \ -// RUN: FileCheck %s --check-prefix=RA-NON-LEAF --check-prefix=KEY-A --check-prefix=BTE-ON --check-prefix=WARN +// RUN: FileCheck %s --check-prefix=RA-NON-LEAF --check-prefix=KEY-A --check-prefix=BTE-ON --check-prefix=GCS-ON --check-prefix=WARN // If the -msign-return-address and -mbranch-protection are both used, the // right-most one controls return address signing. @@ -42,6 +42,9 @@ // BTE-OFF-NOT: "-mbranch-target-enforce" // BTE-ON: "-mbranch-target-enforce" +// GCS-OFF-NOT: "-mguarded-control-stack" +// GCS-ON: "-mguarded-control-stack" + // CONFLICT: "-msign-return-address=none" // BAD-RA-PROTECTION: unsupported argument 'foo' to option '-msign-return-address=' diff --git a/clang/test/Driver/android-version.cpp b/clang/test/Driver/android-version.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d365b701c0223b67953907873f5d99a68982c0c5 --- /dev/null +++ b/clang/test/Driver/android-version.cpp @@ -0,0 +1,16 @@ +// Check that we get the right Android version. + +// RUN: not %clang --target=aarch64-linux-androidS -c %s -### 2>&1 | \ +// RUN: FileCheck --check-prefix=CHECK-ERROR %s + +// CHECK-ERROR: error: version 'S' in target triple 'aarch64-unknown-linux-androidS' is invalid + +// RUN: not %clang --target=armv7-linux-androideabiS -c %s -### 2>&1 | \ +// RUN: FileCheck --check-prefix=CHECK-ERROR1 %s + +// CHECK-ERROR1: error: version 'S' in target triple 'armv7-unknown-linux-androidS' is invalid + +// RUN: %clang --target=aarch64-linux-android31 -c %s -### 2>&1 | \ +// RUN: FileCheck --check-prefix=CHECK-TARGET %s + +// CHECK-TARGET: "aarch64-unknown-linux-android31" diff --git a/clang/test/Driver/cl-x86-flags.c b/clang/test/Driver/cl-x86-flags.c index 51b16f0ce354630b8883fe14260636d5b4ea8f2d..716b02f02a15eb97aec4ea85babcc6bd501f12b1 100644 --- a/clang/test/Driver/cl-x86-flags.c +++ b/clang/test/Driver/cl-x86-flags.c @@ -69,7 +69,10 @@ // RUN: %clang_cl -m32 -arch:avx2 --target=i386-pc-windows -### -- 2>&1 %s | FileCheck -check-prefix=avx2 %s // avx2: invalid /arch: argument -// RUN: %clang_cl -m32 -arch:AVX512F --target=i386-pc-windows /c /Fo%t.obj -Xclang -verify -DTEST_32_ARCH_AVX512F -- %s +// RUN: %clang_cl -m32 -arch:AVX512F --target=i386-pc-windows /c /Fo%t.obj -Xclang -verify=KNL1 -DTEST_32_ARCH_AVX512F -- %s +// KNL1-warning@*:* {{KNL, KNM related Intel Xeon Phi CPU's specific ISA's supports will be removed in LLVM 19.}} +// KNL1-warning@*:* {{KNL, KNM related Intel Xeon Phi CPU's specific ISA's supports will be removed in LLVM 19.}} +// KNL1-warning@*:* {{KNL, KNM related Intel Xeon Phi CPU's specific ISA's supports will be removed in LLVM 19.}} #if defined(TEST_32_ARCH_AVX512F) #if _M_IX86_FP != 2 || !__AVX__ || !__AVX2__ || !__AVX512F__ || __AVX512BW__ #error fail @@ -109,7 +112,10 @@ // RUN: %clang_cl -m64 -arch:avx2 --target=x86_64-pc-windows -### -- 2>&1 %s | FileCheck -check-prefix=avx264 %s // avx264: invalid /arch: argument -// RUN: %clang_cl -m64 -arch:AVX512F --target=i386-pc-windows /c /Fo%t.obj -Xclang -verify -DTEST_64_ARCH_AVX512F -- %s +// RUN: %clang_cl -m64 -arch:AVX512F --target=i386-pc-windows /c /Fo%t.obj -Xclang -verify=KNL2 -DTEST_64_ARCH_AVX512F -- %s +// KNL2-warning@*:* {{KNL, KNM related Intel Xeon Phi CPU's specific ISA's supports will be removed in LLVM 19.}} +// KNL2-warning@*:* {{KNL, KNM related Intel Xeon Phi CPU's specific ISA's supports will be removed in LLVM 19.}} +// KNL2-warning@*:* {{KNL, KNM related Intel Xeon Phi CPU's specific ISA's supports will be removed in LLVM 19.}} #if defined(TEST_64_ARCH_AVX512F) #if _M_IX86_FP || !__AVX__ || !__AVX2__ || !__AVX512F__ || __AVX512BW__ #error fail diff --git a/clang/test/Driver/fsanitize.c b/clang/test/Driver/fsanitize.c index 84a8e2b6b203dd8a09e100b971070f0fa3eecf60..1671825042c3232d672abcf23796c23bd3841b85 100644 --- a/clang/test/Driver/fsanitize.c +++ b/clang/test/Driver/fsanitize.c @@ -896,11 +896,6 @@ // RUN: %clang --target=riscv64-linux-gnu -fsanitize=scudo %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SCUDO // CHECK-SCUDO: "-fsanitize=scudo" -// RUN: %clang --target=x86_64-linux-gnu -fsanitize=scudo %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SCUDO-PIE -// RUN: %clang --target=arm-linux-androideabi -fsanitize=scudo %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SCUDO-PIE -// CHECK-SCUDO-PIE: "-mrelocation-model" "pic" "-pic-level" "2" "-pic-is-pie" -// CHECK-SCUDO-PIE: "-pie" - // RUN: %clang --target=x86_64-linux-gnu -fsanitize=scudo,undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SCUDO-UBSAN // CHECK-SCUDO-UBSAN: "-fsanitize={{.*}}scudo" diff --git a/clang/test/Driver/gcc-triple.cpp b/clang/test/Driver/gcc-triple.cpp new file mode 100644 index 0000000000000000000000000000000000000000..17f045dae747409d0e269c43db1a542968148fe7 --- /dev/null +++ b/clang/test/Driver/gcc-triple.cpp @@ -0,0 +1,14 @@ +// UNSUPPORTED: system-windows + +// RUN: %clang --target=x86_64-redhat-linux-gnu \ +// RUN: --sysroot=%S/Inputs/fedora_39_tree --gcc-triple=x86_64-redhat-linux -v 2>&1 | \ +// RUN: FileCheck %s --check-prefix=TRIPLE_EXISTS + +// TRIPLE_EXISTS: {{^}}Selected GCC installation: +// TRIPLE_EXISTS: fedora_39_tree/usr/lib/gcc/x86_64-redhat-linux/13{{$}} + +// RUN: %clang --target=x86_64-redhat-linux-gnu \ +// RUN: --sysroot=%S/Inputs/fedora_39_tree --gcc-triple=x86_64-gentoo-linux -v 2>&1 | \ +// RUN: FileCheck %s --check-prefix=TRIPLE_DOESNT_EXIST + +// TRIPLE_DOESNT_EXIST-NOT: x86_64-gentoo-linux diff --git a/clang/test/Driver/large-data-threshold.c b/clang/test/Driver/large-data-threshold.c index 9914286701c6c12baf96ef2fd8d1b477dbe7afcb..6500edc0fc0ef2911b1c75631af79c9dff3b9d5f 100644 --- a/clang/test/Driver/large-data-threshold.c +++ b/clang/test/Driver/large-data-threshold.c @@ -1,8 +1,13 @@ +// RUN: %clang --target=x86_64 -### -c -mcmodel=large -mlarge-data-threshold=200 %s 2>&1 | FileCheck --check-prefix=ARG %s // RUN: %clang --target=x86_64 -### -c -mcmodel=medium -mlarge-data-threshold=200 %s 2>&1 | FileCheck --check-prefix=ARG %s -// RUN: %clang --target=x86_64 -### -c -mcmodel=small -mlarge-data-threshold=200 %s 2>&1 | FileCheck --check-prefix=SMALL %s +// RUN: %clang --target=x86_64 -### -c -mcmodel=large %s 2>&1 | FileCheck --check-prefix=ARG-LARGE-DEFAULT %s +// RUN: %clang --target=x86_64 -### -c -mcmodel=medium %s 2>&1 | FileCheck --check-prefix=ARG-MEDIUM-DEFAULT %s +// RUN: %clang --target=x86_64 -### -c -mcmodel=small -mlarge-data-threshold=200 %s 2>&1 | FileCheck --check-prefix=SMALL --implicit-check-not=mlarge-data-threshold %s // RUN: not %clang --target=riscv32 -### -c -mcmodel=medium -mlarge-data-threshold=200 %s 2>&1 | FileCheck --check-prefix=ARCH %s // ARG: "-mlarge-data-threshold=200" +// ARG-MEDIUM-DEFAULT: "-mlarge-data-threshold=65536" +// ARG-LARGE-DEFAULT: "-mlarge-data-threshold=0" -// SMALL: 'mlarge-data-threshold=' only applies to medium code model -// ARCH: unsupported option 'mlarge-data-threshold=' for target 'riscv32' +// SMALL: 'mlarge-data-threshold=' only applies to medium and large code models +// ARCH: unsupported option '-mlarge-data-threshold=' for target diff --git a/clang/test/Driver/linux-ld.c b/clang/test/Driver/linux-ld.c index 49693b6a2d87e201281691870857ce271f9fae49..dd3f4b6784d48712dc8b4a3648284eeaf8c88bc5 100644 --- a/clang/test/Driver/linux-ld.c +++ b/clang/test/Driver/linux-ld.c @@ -541,6 +541,15 @@ // RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/ubuntu_12.04_LTS_multiarch_tree \ // RUN: | FileCheck --check-prefix=CHECK-UBUNTU-12-04-ARM-HF %s +// +// Check that musleabihf is treated as a hardfloat config, with respect to +// multiarch directories. +// +// RUN: %clang -### %s -no-pie 2>&1 \ +// RUN: --target=arm-unknown-linux-musleabihf -rtlib=platform --unwindlib=platform \ +// RUN: --gcc-toolchain="" \ +// RUN: --sysroot=%S/Inputs/ubuntu_12.04_LTS_multiarch_tree \ +// RUN: | FileCheck --check-prefix=CHECK-UBUNTU-12-04-ARM-HF %s // CHECK-UBUNTU-12-04-ARM-HF: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" // CHECK-UBUNTU-12-04-ARM-HF: "{{.*}}/usr/lib/arm-linux-gnueabihf{{/|\\\\}}crt1.o" // CHECK-UBUNTU-12-04-ARM-HF: "{{.*}}/usr/lib/arm-linux-gnueabihf{{/|\\\\}}crti.o" diff --git a/clang/test/Driver/matrix.c b/clang/test/Driver/matrix.c index 15b44ce5a4ec150671d6939cc81c5f26dd0d5f95..4d2624ad39c16e4bbb41ea27504b4bfc0be7d317 100644 --- a/clang/test/Driver/matrix.c +++ b/clang/test/Driver/matrix.c @@ -6,3 +6,15 @@ // RUN: %clang -flto=thin -fenable-matrix %t.o -### --target=x86_64-unknown-linux 2>&1 \ // RUN: | FileCheck %s -check-prefix=CHECK-THINLTO-MATRIX // CHECK-THINLTO-MATRIX: "-plugin-opt=-enable-matrix" + +// RUN: %clang -flto -ffat-lto-objects -fenable-matrix %t.o -### --target=x86_64-unknown-linux 2>&1 \ +// RUN: | FileCheck %s -check-prefix=CHECK-THINLTO-MATRIX + +// RUN: %clang -flto=thin -ffat-lto-objects -fenable-matrix %t.o -### --target=x86_64-unknown-linux 2>&1 \ +// RUN: | FileCheck %s -check-prefix=CHECK-THINLTO-MATRIX + +// RUN: %clang -flto -funified-lto -fenable-matrix %t.o -### --target=x86_64-unknown-linux 2>&1 \ +// RUN: | FileCheck %s -check-prefix=CHECK-THINLTO-MATRIX + +// RUN: %clang -flto=thin -funified-lto -fenable-matrix %t.o -### --target=x86_64-unknown-linux 2>&1 \ +// RUN: | FileCheck %s -check-prefix=CHECK-THINLTO-MATRIX diff --git a/clang/test/Driver/mingw-sysroot.cpp b/clang/test/Driver/mingw-sysroot.cpp index 911dab4927073d6b0fe8d7cda8d51fa4286d6996..50152b2ca210d27883adffcba95a9f56468a2bf2 100644 --- a/clang/test/Driver/mingw-sysroot.cpp +++ b/clang/test/Driver/mingw-sysroot.cpp @@ -14,6 +14,12 @@ // RUN: ln -s %S/Inputs/mingw_ubuntu_posix_tree/usr/x86_64-w64-mingw32 %T/testroot-clang/x86_64-w64-mingw32 // RUN: ln -s %S/Inputs/mingw_arch_tree/usr/i686-w64-mingw32 %T/testroot-clang/i686-w64-mingw32 +// RUN: rm -rf %T/testroot-clang-native +// RUN: mkdir -p %T/testroot-clang-native/bin +// RUN: ln -s %clang %T/testroot-clang-native/bin/clang +// RUN: mkdir -p %T/testroot-clang-native/include/_mingw.h +// RUN: mkdir -p %T/testroot-clang-native/lib/libkernel32.a + // RUN: rm -rf %T/testroot-custom-triple // RUN: mkdir -p %T/testroot-custom-triple/bin // RUN: ln -s %clang %T/testroot-custom-triple/bin/clang @@ -58,6 +64,28 @@ // RUN: env "PATH=%T/testroot-gcc/bin:%PATH%" %T/testroot-gcc/bin/x86_64-w64-mingw32-clang -target x86_64-w64-mingw32 -rtlib=platform -stdlib=libstdc++ --sysroot="" -c -### %s 2>&1 | FileCheck -check-prefix=CHECK_TESTROOT_GCC %s +// If we're executing clang from a directory with what looks like a mingw sysroot, +// with headers in /include and libs in /lib, use that rather than looking +// for another GCC in the path. +// +// Note, this test has a surprising quirk: We're testing with an install directory, +// testroot-clang-native, which lacks the "x86_64-w64-mingw32" subdirectory, it only +// has the include and lib subdirectories without any triple prefix. +// +// Since commit fd15cb935d7aae25ad62bfe06fe9f17cea585978, we avoid using the +// /include and /lib directories when cross compiling. So technically, this +// case testcase only works exactly as expected when running on x86_64 Windows, when +// this target isn't considered cross compiling. +// +// However we do still pass the include directory /x86_64-w64-mingw32/include to +// the -cc1 interface, even if it is missing. Thus, this test looks for this path name, +// that indicates that we did choose the right base, even if this particular directory +// actually doesn't exist here. + +// RUN: env "PATH=%T/testroot-gcc/bin:%PATH%" %T/testroot-clang-native/bin/clang -target x86_64-w64-mingw32 -rtlib=compiler-rt -stdlib=libstdc++ --sysroot="" -c -### %s 2>&1 | FileCheck -check-prefix=CHECK_TESTROOT_CLANG_NATIVE %s +// CHECK_TESTROOT_CLANG_NATIVE: "{{[^"]+}}/testroot-clang-native{{/|\\\\}}x86_64-w64-mingw32{{/|\\\\}}include" + + // If the user requests a different arch via the -m32 option, which changes // x86_64 into i386, check that the driver notices that it can't find a // sysroot for i386 but there is one for i686, and uses that one. diff --git a/clang/test/Driver/riscv-rvv-vector-bits.c b/clang/test/Driver/riscv-rvv-vector-bits.c index e92b66c972daf38c8ca4842bcb5c1d5df536df3c..24af5f0c73c6ef542f7d04b45ba242a4b6e0ba5e 100644 --- a/clang/test/Driver/riscv-rvv-vector-bits.c +++ b/clang/test/Driver/riscv-rvv-vector-bits.c @@ -44,7 +44,7 @@ // CHECK-BAD-VALUE-ERROR: error: unsupported argument '{{.*}}' to option '-mrvv-vector-bits=' -// Error if using attribute without -msve-vector-bits= or if using -msve-vector-bits=+ syntax +// Error if using attribute without -mrvv-vector-bits= or if using -mrvv-vector-bits=+ syntax // ----------------------------------------------------------------------------- // RUN: not %clang -c %s -o /dev/null -target riscv64-linux-gnu \ // RUN: -march=rv64gc_zve64x 2>&1 | FileCheck --check-prefix=CHECK-NO-FLAG-ERROR %s diff --git a/clang/test/Driver/sanitizer-ld.c b/clang/test/Driver/sanitizer-ld.c index 2831c2dad8d24cce4479b186f11a2e576ade483d..79ce70e19ff4f1f51d7b068899fc650b893a1881 100644 --- a/clang/test/Driver/sanitizer-ld.c +++ b/clang/test/Driver/sanitizer-ld.c @@ -896,7 +896,6 @@ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-SCUDO-LINUX %s // CHECK-SCUDO-LINUX: "{{.*}}ld{{(.exe)?}}" -// CHECK-SCUDO-LINUX: "-pie" // CHECK-SCUDO-LINUX: "--whole-archive" "{{.*}}libclang_rt.scudo_standalone-i386.a" "--no-whole-archive" // CHECK-SCUDO-LINUX-NOT: "-lstdc++" // CHECK-SCUDO-LINUX: "-lpthread" diff --git a/clang/test/Format/clang-format-ignore.cpp b/clang/test/Format/clang-format-ignore.cpp index 0d6396a64a668de91d06aa91f2c93a64a701079d..3e09fe59fa212004fce73efc5e9f27d391a5738d 100644 --- a/clang/test/Format/clang-format-ignore.cpp +++ b/clang/test/Format/clang-format-ignore.cpp @@ -1,3 +1,4 @@ +// UNSUPPORTED: system-windows // RUN: rm -rf %t.dir // RUN: mkdir -p %t.dir/level1/level2 @@ -21,13 +22,26 @@ // RUN: touch .clang-format-ignore // RUN: clang-format -verbose foo.c foo.js 2> %t.stderr -// RUN: grep "Formatting \[1/2] foo.c" %t.stderr -// RUN: grep "Formatting \[2/2] foo.js" %t.stderr +// RUN: grep -Fx "Formatting [1/2] foo.c" %t.stderr +// RUN: grep -Fx "Formatting [2/2] foo.js" %t.stderr // RUN: echo "*.js" > .clang-format-ignore // RUN: clang-format -verbose foo.c foo.js 2> %t.stderr -// RUN: grep "Formatting \[1/2] foo.c" %t.stderr -// RUN: not grep "Formatting \[2/2] foo.js" %t.stderr +// RUN: grep -Fx "Formatting [1/2] foo.c" %t.stderr +// RUN: not grep -F foo.js %t.stderr -// RUN: cd ../../.. -// RUN: rm -rf %t.dir +// RUN: cd ../.. +// RUN: clang-format -verbose *.cc level1/*.c* level1/level2/foo.* 2> %t.stderr +// RUN: grep -x "Formatting \[1/5] .*foo\.c" %t.stderr +// RUN: not grep -F foo.js %t.stderr + +// RUN: rm .clang-format-ignore +// RUN: clang-format -verbose *.cc level1/*.c* level1/level2/foo.* 2> %t.stderr +// RUN: grep -x "Formatting \[1/5] .*foo\.cc" %t.stderr +// RUN: grep -x "Formatting \[2/5] .*bar\.cc" %t.stderr +// RUN: grep -x "Formatting \[3/5] .*baz\.c" %t.stderr +// RUN: grep -x "Formatting \[4/5] .*foo\.c" %t.stderr +// RUN: not grep -F foo.js %t.stderr + +// RUN: cd .. +// RUN: rm -r %t.dir diff --git a/clang/test/Frontend/verify.c b/clang/test/Frontend/verify.c index 221b715c19e416ea91b3351ef2fed37f8c39caa2..c549011d7b7a9a261b1b918969e88418ef247c9b 100644 --- a/clang/test/Frontend/verify.c +++ b/clang/test/Frontend/verify.c @@ -157,3 +157,33 @@ unexpected b; // expected-error@33 1-1 {{unknown type}} // what-error {{huh?}} // CHECK9: error: 'what-error' diagnostics expected but not seen: #endif + +#ifdef TEST_WIDE_DELIM +// RUN: not %clang_cc1 -DTEST_WIDE_DELIM -verify %s 2>&1 | FileCheck -check-prefix=CHECK-WIDE-DELIM %s + +// expected-error {{{some message with {{}} in it}}} +// expected-error {{{some message with {}} in it}}} +// expected-error {{{some message with {{} in it}}} + +// expected-error-re {{{some {{.*}} regex with double braces}}} +// expected-error-re {{{some message with {{} in it}}} + +// expected-error {{{mismatched delim}} +// expected-error-re {{{mismatched re {{.*} }}} +// expected-error-re {{{no regex}}} + +#if 0 +// CHECK-WIDE-DELIM: error: 'expected-error' diagnostics expected but not seen: +// CHECK-WIDE-DELIM-NEXT: verify.c Line 164: some message with {{[{]{}[}]}} in it +// CHECK-WIDE-DELIM-NEXT: verify.c Line 165: some message with {}} in it +// CHECK-WIDE-DELIM-NEXT: verify.c Line 166: some message with {{[{]{[}]}} in it +// CHECK-WIDE-DELIM-NEXT: verify.c Line 168: {some {{.*}} regex with double braces +// CHECK-WIDE-DELIM-NEXT: error: 'expected-error' diagnostics seen but not expected: +// CHECK-WIDE-DELIM-NEXT: verify.c Line 169: cannot find end ('}}') of expected regex +// CHECK-WIDE-DELIM-NEXT: verify.c Line 171: cannot find end ('}}}') of expected string +// CHECK-WIDE-DELIM-NEXT: verify.c Line 172: cannot find end ('}}') of expected regex +// CHECK-WIDE-DELIM-NEXT: verify.c Line 173: cannot find start of regex ('{{[{][{]}}') in {no regex +// CHECK-WIDE-DELIM-NEXT: 8 errors generated. +#endif + +#endif diff --git a/clang/test/Frontend/x86-target-cpu.c b/clang/test/Frontend/x86-target-cpu.c index 6c8502ac2c21eeaff139bf8675ee2b1242a36187..6b99b2c8574aef8a771bdd83956526d4e08b41ef 100644 --- a/clang/test/Frontend/x86-target-cpu.c +++ b/clang/test/Frontend/x86-target-cpu.c @@ -15,8 +15,14 @@ // RUN: %clang_cc1 -triple x86_64-unknown-unknown -target-cpu cannonlake -verify %s // RUN: %clang_cc1 -triple x86_64-unknown-unknown -target-cpu icelake-client -verify %s // RUN: %clang_cc1 -triple x86_64-unknown-unknown -target-cpu icelake-server -verify %s -// RUN: %clang_cc1 -triple x86_64-unknown-unknown -target-cpu knl -verify %s -// RUN: %clang_cc1 -triple x86_64-unknown-unknown -target-cpu knm -verify %s +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -target-cpu knl -verify=knl %s +// knl-warning@*:* {{KNL, KNM related Intel Xeon Phi CPU's specific ISA's supports will be removed in LLVM 19.}} +// knl-warning@*:* {{KNL, KNM related Intel Xeon Phi CPU's specific ISA's supports will be removed in LLVM 19.}} +// knl-warning@*:* {{KNL, KNM related Intel Xeon Phi CPU's specific ISA's supports will be removed in LLVM 19.}} +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -target-cpu knm -verify=knm %s +// knm-warning@*:* {{KNL, KNM related Intel Xeon Phi CPU's specific ISA's supports will be removed in LLVM 19.}} +// knm-warning@*:* {{KNL, KNM related Intel Xeon Phi CPU's specific ISA's supports will be removed in LLVM 19.}} +// knm-warning@*:* {{KNL, KNM related Intel Xeon Phi CPU's specific ISA's supports will be removed in LLVM 19.}} // RUN: %clang_cc1 -triple x86_64-unknown-unknown -target-cpu bonnell -verify %s // RUN: %clang_cc1 -triple x86_64-unknown-unknown -target-cpu silvermont -verify %s // RUN: %clang_cc1 -triple x86_64-unknown-unknown -target-cpu k8 -verify %s diff --git a/clang/test/Misc/pragma-attribute-supported-attributes-list.test b/clang/test/Misc/pragma-attribute-supported-attributes-list.test index 2f80c96e1d527187def063d915cf72ed3e84f612..e476c15b35ded939f4326e17707e5e3e53af8de0 100644 --- a/clang/test/Misc/pragma-attribute-supported-attributes-list.test +++ b/clang/test/Misc/pragma-attribute-supported-attributes-list.test @@ -62,6 +62,7 @@ // CHECK-NEXT: CoroOnlyDestroyWhenComplete (SubjectMatchRule_record) // CHECK-NEXT: CoroReturnType (SubjectMatchRule_record) // CHECK-NEXT: CoroWrapper (SubjectMatchRule_function) +// CHECK-NEXT: CountedBy (SubjectMatchRule_field) // CHECK-NEXT: DLLExport (SubjectMatchRule_function, SubjectMatchRule_variable, SubjectMatchRule_record, SubjectMatchRule_objc_interface) // CHECK-NEXT: DLLImport (SubjectMatchRule_function, SubjectMatchRule_variable, SubjectMatchRule_record, SubjectMatchRule_objc_interface) // CHECK-NEXT: Destructor (SubjectMatchRule_function) diff --git a/clang/test/Modules/Inputs/AutolinkTBD.framework/AutolinkTBD.tbd b/clang/test/Modules/Inputs/AutolinkTBD.framework/AutolinkTBD.tbd deleted file mode 100644 index 4aa0f85d0d56aa8959d1c3e1bf42c2d9bca66dcb..0000000000000000000000000000000000000000 --- a/clang/test/Modules/Inputs/AutolinkTBD.framework/AutolinkTBD.tbd +++ /dev/null @@ -1 +0,0 @@ -empty file - clang only needs to check if it exists. diff --git a/clang/test/Modules/Inputs/AutolinkTBD.framework/Headers/AutolinkTBD.h b/clang/test/Modules/Inputs/AutolinkTBD.framework/Headers/AutolinkTBD.h deleted file mode 100644 index 914983c49636c2c114b24d1e69989621637a5d4e..0000000000000000000000000000000000000000 --- a/clang/test/Modules/Inputs/AutolinkTBD.framework/Headers/AutolinkTBD.h +++ /dev/null @@ -1 +0,0 @@ -extern int foo(void); diff --git a/clang/test/Modules/autolinkTBD.m b/clang/test/Modules/autolinkTBD.m deleted file mode 100644 index 69253294f7b816622985380533f840eaf302a088..0000000000000000000000000000000000000000 --- a/clang/test/Modules/autolinkTBD.m +++ /dev/null @@ -1,16 +0,0 @@ -// UNSUPPORTED: target={{.*}}-zos{{.*}}, target={{.*}}-aix{{.*}} -// RUN: rm -rf %t -// RUN: %clang_cc1 -emit-llvm -o - -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -F %S/Inputs %s | FileCheck %s -// RUN: %clang_cc1 -emit-llvm -fno-autolink -o - -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -F %S/Inputs %s | FileCheck --check-prefix=CHECK-AUTOLINK-DISABLED %s - -@import AutolinkTBD; - -int f(void) { - return foo(); -} - -// CHECK: !llvm.linker.options = !{![[AUTOLINK_FRAMEWORK:[0-9]+]]} -// CHECK: ![[AUTOLINK_FRAMEWORK]] = !{!"-framework", !"AutolinkTBD"} - -// CHECK-AUTOLINK-DISABLED: !llvm.module.flags -// CHECK-AUTOLINK-DISABLED-NOT: !llvm.linker.options diff --git a/clang/test/Modules/autolink_private_module.m b/clang/test/Modules/autolink_private_module.m new file mode 100644 index 0000000000000000000000000000000000000000..0c8d166a42c7d3d48153b2da164b34cf5a456e94 --- /dev/null +++ b/clang/test/Modules/autolink_private_module.m @@ -0,0 +1,29 @@ +// UNSUPPORTED: target={{.*}}-zos{{.*}}, target={{.*}}-aix{{.*}} + +// Test that autolink hints for frameworks don't use the private module name. +// UNSUPPORTED: target={{.*}}-zos{{.*}}, target={{.*}}-aix{{.*}} + +// RUN: rm -rf %t && mkdir %t +// RUN: split-file %s %t + +// RUN: %clang_cc1 -emit-llvm -o - -fmodules-cache-path=%t/ModuleCache -fmodules -fimplicit-module-maps -F %t/Frameworks %t/test.m | FileCheck %s + +// CHECK: !{!"-framework", !"Autolink"} +// CHECK-NOT: !{!"-framework", !"Autolink_Private"} + +//--- test.m +#include +#include + +//--- Frameworks/Autolink.framework/Headers/Autolink.h +void public(); + +//--- Frameworks/Autolink.framework/PrivateHeaders/Autolink_Private.h +void private(); + +//--- Frameworks/Autolink.framework/Modules/module.modulemap +framework module Autolink { header "Autolink.h"} + +//--- Frameworks/Autolink.framework/Modules/module.private.modulemap +framework module Autolink_Private { header "Autolink_Private.h"} + diff --git a/clang/test/Modules/cxx20-10-1-ex1.cpp b/clang/test/Modules/cxx20-10-1-ex1.cpp index b9a5e8023d035f33cbbdf618b4977eee4c90705a..b330e0a6c9a9d88d5114116450dd3b0159cffc75 100644 --- a/clang/test/Modules/cxx20-10-1-ex1.cpp +++ b/clang/test/Modules/cxx20-10-1-ex1.cpp @@ -9,13 +9,15 @@ // RUN: -o %t/A_Internals.pcm // RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/std10-1-ex1-tu2.cpp \ -// RUN: -fmodule-file=%t/A_Internals.pcm -o %t/A_Foo.pcm +// RUN: -fmodule-file=A:Internals=%t/A_Internals.pcm -o %t/A_Foo.pcm // RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/std10-1-ex1-tu3.cpp \ -// RUN: -fmodule-file=%t/A_Foo.pcm -o %t/A.pcm +// RUN: -fmodule-file=A:Foo=%t/A_Foo.pcm -fmodule-file=A:Internals=%t/A_Internals.pcm \ +// RUN: -o %t/A.pcm // RUN: %clang_cc1 -std=c++20 -emit-obj %t/std10-1-ex1-tu4.cpp \ -// RUN: -fmodule-file=%t/A.pcm -o %t/ex1.o +// RUN: -fmodule-file=A=%t/A.pcm -fmodule-file=A:Foo=%t/A_Foo.pcm \ +// RUN: -fmodule-file=A:Internals=%t/A_Internals.pcm -o %t/ex1.o // expected-no-diagnostics diff --git a/clang/test/Modules/cxx20-importing-function-bodies.cppm b/clang/test/Modules/cxx20-importing-function-bodies.cppm index f1b8f9a8f0c91180ee578bda71ff70c58eced8e3..c34e48aaa3f671026a67ed5c9e25e220328d3a2f 100644 --- a/clang/test/Modules/cxx20-importing-function-bodies.cppm +++ b/clang/test/Modules/cxx20-importing-function-bodies.cppm @@ -9,7 +9,8 @@ // RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/c.cppm \ // RUN: -emit-module-interface -fprebuilt-module-path=%t -o %t/c.pcm // RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/c.pcm -S \ -// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %t/c.cppm +// RUN: -fprebuilt-module-path=%t -emit-llvm -disable-llvm-passes -o - \ +// RUN: | FileCheck %t/c.cppm // // Be sure that we keep the same behavior as if optization not enabled. // RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple -O3 %t/a.cppm \ @@ -19,7 +20,8 @@ // RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple -O3 %t/c.cppm \ // RUN: -emit-module-interface -fprebuilt-module-path=%t -o %t/c.pcm // RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple -O3 %t/c.pcm \ -// RUN: -S -emit-llvm -disable-llvm-passes -o - | FileCheck %t/c.cppm +// RUN: -fprebuilt-module-path=%t -S -emit-llvm -disable-llvm-passes \ +// RUN: -o - | FileCheck %t/c.cppm //--- a.cppm export module a; diff --git a/clang/test/Modules/cxx20-module-file-info.cpp b/clang/test/Modules/cxx20-module-file-info.cpp index 99a215645e8fe76e96600aeb213790ac3dda67ae..9ef061f076330c80d6431fd3dab4d1fa9e26d122 100644 --- a/clang/test/Modules/cxx20-module-file-info.cpp +++ b/clang/test/Modules/cxx20-module-file-info.cpp @@ -14,13 +14,14 @@ // RUN: -o %t/B.pcm // RUN: %clang_cc1 -std=c++20 -module-file-info %t/B.pcm | FileCheck \ -// RUN: --check-prefix=CHECK-B %s +// RUN: --check-prefix=CHECK-B %s // RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/mod-info-tu3.cpp \ -// RUN: -fmodule-file=%t/A.pcm -fmodule-file=%t/B.pcm -o %t/Foo.pcm +// RUN: -fmodule-file=A=%t/A.pcm -fmodule-file=B=%t/B.pcm -o %t/Foo.pcm -// RUN: %clang_cc1 -std=c++20 -module-file-info %t/Foo.pcm | FileCheck \ -// RUN: --check-prefix=CHECK-FOO %s +// RUN: %clang_cc1 -std=c++20 -module-file-info %t/Foo.pcm -fmodule-file=A=%t/A.pcm \ +// RUN: -fmodule-file=B=%t/B.pcm | FileCheck \ +// RUN: --check-prefix=CHECK-FOO %s // expected-no-diagnostics diff --git a/clang/test/Modules/cxx20-partition-redeclarations.cpp b/clang/test/Modules/cxx20-partition-redeclarations.cpp index f99ef009a79af891a43bb32e12291e5cc5e66a6d..03658ba92534d322ed848a23ae82565e3fb42c9e 100644 --- a/clang/test/Modules/cxx20-partition-redeclarations.cpp +++ b/clang/test/Modules/cxx20-partition-redeclarations.cpp @@ -7,10 +7,10 @@ // RUN: %clang_cc1 -std=c++20 A-interface.cpp -emit-module-interface \ // RUN: -fmodule-file=A-PubPart.pcm -o A.pcm -// RUN: %clang_cc1 -std=c++20 A-impl-top.cpp -fsyntax-only -fmodule-file=A.pcm -// RUN: %clang_cc1 -std=c++20 A-impl-part.cpp -fsyntax-only -fmodule-file=A.pcm -// RUN: %clang_cc1 -std=c++20 A-impl-1.cpp -fsyntax-only -fmodule-file=A.pcm -// RUN: %clang_cc1 -std=c++20 A-impl-2.cpp -fsyntax-only -fmodule-file=A.pcm +// RUN: %clang_cc1 -std=c++20 A-impl-top.cpp -fsyntax-only -fprebuilt-module-path=%t +// RUN: %clang_cc1 -std=c++20 A-impl-part.cpp -fsyntax-only -fprebuilt-module-path=%t +// RUN: %clang_cc1 -std=c++20 A-impl-1.cpp -fsyntax-only -fprebuilt-module-path=%t +// RUN: %clang_cc1 -std=c++20 A-impl-2.cpp -fsyntax-only -fprebuilt-module-path=%t //--- A-interface.cpp export module A; diff --git a/clang/test/Modules/eagerly-load-cxx-named-modules.cppm b/clang/test/Modules/eagerly-load-cxx-named-modules.cppm index febda6ef0f5730533307319b5bfe5a2e8a272518..ab2ac891fb400c4dd7557e154cd72daa99538cd4 100644 --- a/clang/test/Modules/eagerly-load-cxx-named-modules.cppm +++ b/clang/test/Modules/eagerly-load-cxx-named-modules.cppm @@ -7,8 +7,8 @@ // RUN: 2>&1 | FileCheck %t/user.cpp // RUN: %clang_cc1 -std=c++20 %t/b.cppm -emit-module-interface -o %t/b.pcm \ // RUN: -fprebuilt-module-path=%t -// RUN: %clang_cc1 -std=c++20 %t/b.pcm -Wno-read-modules-implicitly -S \ -// RUN: -emit-llvm 2>&1 -o - | FileCheck %t/b.cppm +// RUN: %clang_cc1 -std=c++20 %t/b.pcm -S \ +// RUN: -fprebuilt-module-path=%t -emit-llvm 2>&1 -o - | FileCheck %t/b.cppm //--- a.cppm export module a; diff --git a/clang/test/Modules/explicit-specializations.cppm b/clang/test/Modules/explicit-specializations.cppm new file mode 100644 index 0000000000000000000000000000000000000000..914144018e880869f83dd7df3d6cfe27d87c536e --- /dev/null +++ b/clang/test/Modules/explicit-specializations.cppm @@ -0,0 +1,133 @@ +// Testing that the compiler can select the correct template specialization +// from different template aliasing. +// +// RUN: rm -rf %t +// RUN: split-file %s %t +// RUN: cd %t +// +// RUN: %clang_cc1 -std=c++20 %t/a.cppm -emit-module-interface -o %t/a.pcm +// RUN: %clang_cc1 -std=c++20 %t/b.cpp -fprebuilt-module-path=%t \ +// RUN: -fsyntax-only -verify + +//--- a.cppm + +// For template type parameters +export module a; +export template +struct S { + static constexpr bool selected = false; +}; + +export struct A {}; + +export template <> +struct S { + static constexpr bool selected = true; +}; + +export using B = A; + +// For template template parameters + +export template typename C> +struct V { + static constexpr bool selected = false; +}; + +export template <> +struct V { + static constexpr bool selected = true; +}; + +// For template non type parameters +export template +struct Numbers { + static constexpr bool selected = false; + static constexpr int value = X; +}; + +export template<> +struct Numbers<43> { + static constexpr bool selected = true; + static constexpr int value = 43; +}; + +export template +struct Pointers { + static constexpr bool selected = false; +}; + +export int IntegralValue = 0; +export template<> +struct Pointers<&IntegralValue> { + static constexpr bool selected = true; +}; + +export template +struct NullPointers { + static constexpr bool selected = false; +}; + +export template<> +struct NullPointers { + static constexpr bool selected = true; +}; + +export template +struct Array { + static constexpr bool selected = false; +}; + +export int array[5]; +export template<> +struct Array { + static constexpr bool selected = true; +}; + +//--- b.cpp +// expected-no-diagnostics +import a; + +// Testing for different qualifiers +static_assert(S::selected); +static_assert(S<::B>::selected); +static_assert(::S::selected); +static_assert(::S<::B>::selected); +typedef A C; +static_assert(S::selected); +static_assert(S<::C>::selected); +static_assert(::S::selected); +static_assert(::S<::C>::selected); + +namespace D { + C getAType(); + typedef C E; +} + +static_assert(S::selected); +static_assert(S::selected); + +// Testing we can select the correct specialization for different +// template template argument alising. + +static_assert(V::selected); +static_assert(V<::S>::selected); +static_assert(::V::selected); +static_assert(::V<::S>::selected); + +// Testing for template non type parameters +static_assert(Numbers<43>::selected); +static_assert(Numbers<21 * 2 + 1>::selected); +static_assert(Numbers<42 + 1>::selected); +static_assert(Numbers<44 - 1>::selected); +static_assert(Numbers::value>::selected); +static_assert(!Numbers<44>::selected); + +static_assert(Pointers<&IntegralValue>::selected); +static_assert(!Pointers::selected); +static_assert(NullPointers::selected); +static_assert(!NullPointers<(void*)&IntegralValue>::selected); + +static_assert(Array::selected); +int another_array[5]; +static_assert(!Array::selected); diff --git a/clang/test/Modules/implicit-module-with-missing-path.cpp b/clang/test/Modules/implicit-module-with-missing-path.cpp index 851a4401df0b6c7f011c5f82d0b22f71648b3d9f..d167f742e7b21ec823eb95106084f8c0c887adc5 100644 --- a/clang/test/Modules/implicit-module-with-missing-path.cpp +++ b/clang/test/Modules/implicit-module-with-missing-path.cpp @@ -6,7 +6,7 @@ // RUN: echo -e "export module B;\nimport C;" >> %t/B.cppm // RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/subdir/C.cppm -o %t/subdir/C.pcm // RUN: %clang_cc1 -std=c++20 -emit-module-interface -fprebuilt-module-path=%t/subdir %t/B.cppm -o %t/B.pcm -// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %s -fsyntax-only -verify -Wno-read-modules-implicitly +// RUN: %clang_cc1 -std=c++20 -fmodule-file=B=%t/B.pcm %s -fsyntax-only -verify -import B; -import C; // expected-error {{module 'C' is needed but has not been provided, and implicit use of module files is disabled}} +import B; // expected-error {{failed to find module file for module 'C'}} +import C; // expected-error {{module 'C' not found}} diff --git a/clang/test/Modules/module-init-duplicated-import.cppm b/clang/test/Modules/module-init-duplicated-import.cppm index de0ce1962f10082c8556a6c48e32d194ac59f0aa..7adce11779566e1f784cdda853bb38721b1f88e4 100644 --- a/clang/test/Modules/module-init-duplicated-import.cppm +++ b/clang/test/Modules/module-init-duplicated-import.cppm @@ -7,7 +7,7 @@ // RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 %t/m.cppm \ // RUN: -emit-module-interface -fmodule-file=a=%t/a.pcm -o %t/m.pcm // RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 %t/m.pcm \ -// RUN: -S -emit-llvm -o - | FileCheck %t/m.cppm +// RUN: -fmodule-file=a=%t/a.pcm -S -emit-llvm -o - | FileCheck %t/m.cppm //--- a.cppm export module a; diff --git a/clang/test/Modules/no-duplicate-codegen-in-GMF.cppm b/clang/test/Modules/no-duplicate-codegen-in-GMF.cppm index e4d06415fabd453c35305b842742428c3ecb1f39..a743b64cb18d6e21c44bdea6f22d6e12c2461be0 100644 --- a/clang/test/Modules/no-duplicate-codegen-in-GMF.cppm +++ b/clang/test/Modules/no-duplicate-codegen-in-GMF.cppm @@ -7,7 +7,8 @@ // RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/A.cppm -emit-module-interface -o %t/A.pcm // RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/B.cppm -emit-module-interface -o %t/B.pcm \ // RUN: -fprebuilt-module-path=%t -// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/B.pcm -S -emit-llvm -o - | FileCheck %t/B.cppm +// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/B.pcm -S -emit-llvm -o - \ +// RUN: -fprebuilt-module-path=%t | FileCheck %t/B.cppm //--- foo.h diff --git a/clang/test/Modules/no-implicit-std-cxx-module.cppm b/clang/test/Modules/no-implicit-std-cxx-module.cppm index 0432159fed1801858d258ade8088a65d0a25dfde..2df8b5cf5d84844dc2cf51080826219804af87ed 100644 --- a/clang/test/Modules/no-implicit-std-cxx-module.cppm +++ b/clang/test/Modules/no-implicit-std-cxx-module.cppm @@ -6,21 +6,6 @@ // RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/a.cppm -fmodule-file=b=%t/b.pcm \ // RUN: -o %t/a.pcm // RUN: %clang_cc1 -std=c++20 %t/user.cpp -fmodule-file=a=%t/a.pcm -verify -fsyntax-only -// RUN: %clang_cc1 -std=c++20 %t/user.cpp -fmodule-file=a=%t/a.pcm -verify -fsyntax-only \ -// RUN: -Wno-read-modules-implicitly -DNO_DIAG -// RUN: %clang_cc1 -std=c++20 %t/user.cpp -fmodule-file=a=%t/a.pcm -fmodule-file=b=%t/b.pcm \ -// RUN: -DNO_DIAG -verify -fsyntax-only -// -// RUN: %clang_cc1 -std=c++20 %t/a.pcm -S -emit-llvm -o - 2>&1 | FileCheck %t/a.cppm -// RUN: %clang_cc1 -std=c++20 %t/a.pcm -fmodule-file=b=%t/b.pcm -S -emit-llvm -o - 2>&1 \ -// RUN: | FileCheck %t/a.cppm -check-prefix=CHECK-CORRECT -// -// RUN: mkdir -p %t/tmp -// RUN: mv %t/b.pcm %t/tmp/b.pcm -// RUN: not %clang_cc1 -std=c++20 %t/a.pcm -S -emit-llvm -o - 2>&1 \ -// RUN: | FileCheck %t/a.cppm -check-prefix=CHECK-ERROR -// RUN: %clang_cc1 -std=c++20 %t/a.pcm -S -emit-llvm -o - 2>&1 -fmodule-file=b=%t/tmp/b.pcm \ -// RUN: | FileCheck %t/a.cppm -check-prefix=CHECK-CORRECT //--- b.cppm export module b; @@ -35,21 +20,8 @@ export int a() { return b() + 43; } -// CHECK: it is deprecated to read module 'b' implicitly; - -// CHECK-CORRECT-NOT: warning -// CHECK-CORRECT-NOT: error - -// CHECK-ERROR: error: module file{{.*}}not found: module file not found - - //--- user.cpp -#ifdef NO_DIAG -// expected-no-diagnostics -#else - // expected-warning@+2 {{it is deprecated to read module 'b' implicitly;}} -#endif -import a; +import a; // expected-error {{failed to find module file for module 'b'}} int use() { - return a(); + return a(); // expected-error {{use of undeclared identifier 'a'}} } diff --git a/clang/test/Modules/no-import-func-body.cppm b/clang/test/Modules/no-import-func-body.cppm index 6c7292b1e469bdf9d88fcf685995d743e73a81d0..af7c3a3ad84b36d9fa9b0619c40ef4447e536a3c 100644 --- a/clang/test/Modules/no-import-func-body.cppm +++ b/clang/test/Modules/no-import-func-body.cppm @@ -9,7 +9,8 @@ // RUN: %clang_cc1 -std=c++20 -O1 -triple %itanium_abi_triple %t/c.cppm \ // RUN: -emit-module-interface -fprebuilt-module-path=%t -o %t/c.pcm // RUN: %clang_cc1 -std=c++20 -O1 -triple %itanium_abi_triple %t/c.pcm -S \ -// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %t/c.cppm +// RUN: -fprebuilt-module-path=%t -emit-llvm -disable-llvm-passes -o - \ +// RUN: | FileCheck %t/c.cppm //--- a.cppm export module a; diff --git a/clang/test/Modules/pr61067.cppm b/clang/test/Modules/pr61067.cppm index 8469a1db1f1c8d0e6afc1f00080c0e85d9f85c84..baee4b83de5660d658941dd96111d8355df944a8 100644 --- a/clang/test/Modules/pr61067.cppm +++ b/clang/test/Modules/pr61067.cppm @@ -8,7 +8,7 @@ // RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/b.cppm \ // RUN: -emit-module-interface -fmodule-file=a=%t/a.pcm -o %t/b.pcm // RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/b.pcm -S \ -// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %t/b.cppm +// RUN: -emit-llvm -fmodule-file=a=%t/a.pcm -disable-llvm-passes -o - | FileCheck %t/b.cppm // RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/c.cpp -fmodule-file=a=%t/a.pcm \ // RUN: -S -emit-llvm -disable-llvm-passes -o - | FileCheck %t/c.cpp diff --git a/clang/test/Modules/pr62705.cppm b/clang/test/Modules/pr62705.cppm index a09bdf2563e84b2942ef7af51b4dd2fb051af640..00769d2277f4f101d6abfd23af1a1c0596b30683 100644 --- a/clang/test/Modules/pr62705.cppm +++ b/clang/test/Modules/pr62705.cppm @@ -8,7 +8,7 @@ // RUN: -emit-module-interface -o %t/b.pcm \ // RUN: -fmodule-file=a=%t/a.pcm // RUN: %clang_cc1 %t/b.pcm -std=c++20 -triple %itanium_abi_triple \ -// RUN: -emit-llvm -o - | FileCheck %t/b.cppm +// RUN: -fmodule-file=a=%t/a.pcm -emit-llvm -o - | FileCheck %t/b.cppm //--- foo.h namespace n { diff --git a/clang/test/Modules/pr67893.cppm b/clang/test/Modules/pr67893.cppm index 7d4e4c1dc5d843c88c94661a79b157a8fc782a58..00b024ecc2eb11f6132d6dedb9ccae8b7e5c5550 100644 --- a/clang/test/Modules/pr67893.cppm +++ b/clang/test/Modules/pr67893.cppm @@ -5,9 +5,9 @@ // RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 %t/a.cppm \ // RUN: -emit-module-interface -o %t/a.pcm // RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 %t/m.cppm \ -// RUN: -emit-module-interface -fmodule-file=a=%t/a.pcm -o %t/m.pcm +// RUN: -emit-module-interface -fprebuilt-module-path=%t // RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 %t/m.pcm \ -// RUN: -S -emit-llvm -o - | FileCheck %t/m.cppm +// RUN: -fprebuilt-module-path=%t -S -emit-llvm -o - | FileCheck %t/m.cppm //--- a.cppm export module a; diff --git a/clang/test/Modules/templates.mm b/clang/test/Modules/templates.mm index 0e66c9843cc09f8e29c78a364433575c053ff6a5..d7b7d5af030a7af3f1820a2a06e6ef7b21c95bcd 100644 --- a/clang/test/Modules/templates.mm +++ b/clang/test/Modules/templates.mm @@ -125,7 +125,7 @@ void testWithAttributes() { // Check that returnNonTrivial doesn't return Class0 directly in registers. -// CHECK: declare void @_Z16returnNonTrivialv(ptr sret(%struct.Class0) align 8) +// CHECK: declare void @_Z16returnNonTrivialv(ptr dead_on_unwind writable sret(%struct.Class0) align 8) @import template_nontrivial0; @import template_nontrivial1; diff --git a/clang/test/OpenMP/irbuilder_for_iterator.cpp b/clang/test/OpenMP/irbuilder_for_iterator.cpp index 91bbb6fc18ddb126d2721edb18f29449bd7ca470..b88416b36c4fa633e49edeb84451b8cf1700ad65 100644 --- a/clang/test/OpenMP/irbuilder_for_iterator.cpp +++ b/clang/test/OpenMP/irbuilder_for_iterator.cpp @@ -159,7 +159,7 @@ extern "C" void workshareloop_iterator(float *a, float *b, float *c) { // CHECK-NEXT: [[TMP2:%.*]] = load i64, ptr [[LOGICAL_ADDR]], align 8 // CHECK-NEXT: [[MUL:%.*]] = mul i64 1, [[TMP2]] // CHECK-NEXT: [[CONV:%.*]] = trunc i64 [[MUL]] to i32 -// CHECK-NEXT: call void @_ZNK10MyIteratorplEj(ptr sret([[STRUCT_MYITERATOR]]) align 1 [[REF_TMP]], ptr noundef nonnull align 1 dereferenceable(1) [[TMP1]], i32 noundef [[CONV]]) +// CHECK-NEXT: call void @_ZNK10MyIteratorplEj(ptr dead_on_unwind writable sret([[STRUCT_MYITERATOR]]) align 1 [[REF_TMP]], ptr noundef nonnull align 1 dereferenceable(1) [[TMP1]], i32 noundef [[CONV]]) // CHECK-NEXT: [[TMP3:%.*]] = load ptr, ptr [[LOOPVAR_ADDR]], align 8 // CHECK-NEXT: [[CALL:%.*]] = call noundef nonnull align 1 dereferenceable(1) ptr @_ZN10MyIteratoraSERKS_(ptr noundef nonnull align 1 dereferenceable(1) [[TMP3]], ptr noundef nonnull align 1 dereferenceable(1) [[REF_TMP]]) // CHECK-NEXT: ret void diff --git a/clang/test/OpenMP/irbuilder_for_rangefor.cpp b/clang/test/OpenMP/irbuilder_for_rangefor.cpp index 3b952d43eb257b47d50bf437bccbc1de4a194fda..6bf91bfda138afa08b4bc2ada48767eb99ef840d 100644 --- a/clang/test/OpenMP/irbuilder_for_rangefor.cpp +++ b/clang/test/OpenMP/irbuilder_for_rangefor.cpp @@ -57,9 +57,9 @@ extern "C" void workshareloop_rangefor(float *a, float *b, float *c) { // CHECK-NEXT: call void @_ZN7MyRangeC1Ei(ptr noundef nonnull align 1 dereferenceable(1) [[REF_TMP]], i32 noundef 42) // CHECK-NEXT: store ptr [[REF_TMP]], ptr [[__RANGE2]], align 8 // CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[__RANGE2]], align 8 -// CHECK-NEXT: call void @_ZN7MyRange5beginEv(ptr sret([[STRUCT_MYITERATOR]]) align 1 [[__BEGIN2]], ptr noundef nonnull align 1 dereferenceable(1) [[TMP0]]) +// CHECK-NEXT: call void @_ZN7MyRange5beginEv(ptr dead_on_unwind writable sret([[STRUCT_MYITERATOR]]) align 1 [[__BEGIN2]], ptr noundef nonnull align 1 dereferenceable(1) [[TMP0]]) // CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[__RANGE2]], align 8 -// CHECK-NEXT: call void @_ZN7MyRange3endEv(ptr sret([[STRUCT_MYITERATOR]]) align 1 [[__END2]], ptr noundef nonnull align 1 dereferenceable(1) [[TMP1]]) +// CHECK-NEXT: call void @_ZN7MyRange3endEv(ptr dead_on_unwind writable sret([[STRUCT_MYITERATOR]]) align 1 [[__END2]], ptr noundef nonnull align 1 dereferenceable(1) [[TMP1]]) // CHECK-NEXT: [[CALL:%.*]] = call noundef i32 @_ZNK10MyIteratordeEv(ptr noundef nonnull align 1 dereferenceable(1) [[__BEGIN2]]) // CHECK-NEXT: store i32 [[CALL]], ptr [[I]], align 4 // CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT_ANON]], ptr [[AGG_CAPTURED]], i32 0, i32 0 @@ -177,7 +177,7 @@ extern "C" void workshareloop_rangefor(float *a, float *b, float *c) { // CHECK-NEXT: [[TMP2:%.*]] = load i64, ptr [[LOGICAL_ADDR]], align 8 // CHECK-NEXT: [[MUL:%.*]] = mul i64 1, [[TMP2]] // CHECK-NEXT: [[CONV:%.*]] = trunc i64 [[MUL]] to i32 -// CHECK-NEXT: call void @_ZNK10MyIteratorplEj(ptr sret([[STRUCT_MYITERATOR]]) align 1 [[REF_TMP]], ptr noundef nonnull align 1 dereferenceable(1) [[TMP1]], i32 noundef [[CONV]]) +// CHECK-NEXT: call void @_ZNK10MyIteratorplEj(ptr dead_on_unwind writable sret([[STRUCT_MYITERATOR]]) align 1 [[REF_TMP]], ptr noundef nonnull align 1 dereferenceable(1) [[TMP1]], i32 noundef [[CONV]]) // CHECK-NEXT: [[CALL:%.*]] = call noundef i32 @_ZNK10MyIteratordeEv(ptr noundef nonnull align 1 dereferenceable(1) [[REF_TMP]]) // CHECK-NEXT: [[TMP3:%.*]] = load ptr, ptr [[LOOPVAR_ADDR]], align 8 // CHECK-NEXT: store i32 [[CALL]], ptr [[TMP3]], align 4 diff --git a/clang/test/OpenMP/loop_bind_messages.cpp b/clang/test/OpenMP/loop_bind_messages.cpp index f7fdf289714328927e126fccdecee6cba75f5cea..becd1f40c0c0474ca1ea014af38cfe7280334024 100644 --- a/clang/test/OpenMP/loop_bind_messages.cpp +++ b/clang/test/OpenMP/loop_bind_messages.cpp @@ -4,6 +4,7 @@ #define NNN 50 int aaa[NNN]; +int aaa2[NNN][NNN]; void parallel_loop() { #pragma omp parallel @@ -13,10 +14,82 @@ void parallel_loop() { aaa[j] = j*NNN; } } + + #pragma omp parallel for + for (int i = 0 ; i < NNN ; i++) { + #pragma omp loop bind(parallel) // expected-error{{region cannot be closely nested inside 'parallel for' region; perhaps you forget to enclose 'omp loop' directive into a parallel region?}} + for (int j = 0 ; j < NNN ; j++) { + aaa2[i][j] = i+j; + } + } + + #pragma omp parallel + #pragma omp for nowait + for (int i = 0 ; i < NNN ; i++) { + #pragma omp loop bind(parallel) // expected-error{{region cannot be closely nested inside 'for' region; perhaps you forget to enclose 'omp loop' directive into a parallel region?}} + for (int j = 0 ; j < NNN ; j++) { + aaa2[i][j] = i+j; + } + } + + #pragma omp parallel for + for (int i = 0 ; i < NNN ; i++) { + #pragma omp nothing + #pragma omp loop + for (int j = 0 ; j < NNN ; j++) { + aaa2[i][j] = i+j; + } + } + + #pragma omp target teams distribute parallel for + for (int i = 0 ; i < NNN ; i++) { + #pragma omp loop bind(parallel) // expected-error{{region cannot be closely nested inside 'target teams distribute parallel for' region; perhaps you forget to enclose 'omp loop' directive into a parallel region?}} + for (int j = 0 ; j < NNN ; j++) { + aaa2[i][j] = i+j; + } + } + + #pragma omp target parallel + for (int i = 0 ; i < NNN ; i++) { + #pragma omp loop bind(parallel) + for (int j = 0 ; j < NNN ; j++) { + aaa2[i][j] = i+j; + } + } + + #pragma omp parallel for + for (int i = 0; i < 100; ++i) { + #pragma omp loop bind(parallel) // expected-error{{region cannot be closely nested inside 'parallel for' region; perhaps you forget to enclose 'omp loop' directive into a parallel region?}} + for (int i = 0 ; i < NNN ; i++) { + #pragma omp loop bind(parallel) // expected-error{{region cannot be closely nested inside 'loop' region; perhaps you forget to enclose 'omp loop' directive into a parallel region?}} + for (int j = 0 ; j < NNN ; j++) { + aaa[j] = j*NNN; + } + } + } + + #pragma omp parallel + { + #pragma omp sections + { + for (int i = 0 ; i < NNN ; i++) { + #pragma omp loop bind(parallel) // expected-error{{region cannot be closely nested inside 'sections' region; perhaps you forget to enclose 'omp loop' directive into a parallel region?}} + for (int j = 0 ; j < NNN ; j++) { + aaa2[i][j] = i+j; + } + } + + #pragma omp section + { + aaa[NNN-1] = NNN; + } + } + } } void teams_loop() { - int var1, var2; + int var1; + int total = 0; #pragma omp teams { @@ -32,24 +105,22 @@ void teams_loop() { } } } -} -void orphan_loop_with_bind() { - #pragma omp loop bind(parallel) - for (int j = 0 ; j < NNN ; j++) { - aaa[j] = j*NNN; + #pragma omp target teams + for (int i = 0 ; i < NNN ; i++) { + #pragma omp loop bind(teams) + for (int j = 0 ; j < NNN ; j++) { + aaa2[i][j] = i+j; + } } -} -void orphan_loop_no_bind() { - #pragma omp loop // expected-error{{expected 'bind' clause for 'loop' construct without an enclosing OpenMP construct}} - for (int j = 0 ; j < NNN ; j++) { - aaa[j] = j*NNN; + #pragma omp target teams distribute parallel for + for (int i = 0 ; i < NNN ; i++) { + #pragma omp loop bind(teams) // expected-error{{region cannot be closely nested inside 'target teams distribute parallel for' region; perhaps you forget to enclose 'omp loop' directive into a teams region?}} + for (int j = 0 ; j < NNN ; j++) { + aaa2[i][j] = i+j; + } } -} - -void teams_loop_reduction() { - int total = 0; #pragma omp teams { @@ -63,14 +134,98 @@ void teams_loop_reduction() { total+=aaa[j]; } } + + #pragma omp teams num_teams(8) thread_limit(256) + #pragma omp distribute parallel for dist_schedule(static, 1024) \ + schedule(static, 64) + for (int i = 0; i < NNN; i++) { + #pragma omp loop bind(teams) // expected-error{{'distribute parallel for' region; perhaps you forget to enclose 'omp loop' directive into a teams region?}} + for (int j = 0; j < NNN; j++) { + aaa2[i][j] = i+j; + } + } + + #pragma omp teams + for (int i = 0; i < NNN; i++) { + #pragma omp loop bind(thread) + for (int j = 0 ; j < NNN ; j++) { + aaa[i] = i+i*NNN; + } + } + + #pragma omp teams loop + for (int i = 0; i < NNN; i++) { + #pragma omp loop + for (int j = 0 ; j < NNN ; j++) { + aaa[i] = i+i*NNN; + } + } + + #pragma omp teams loop + for (int i = 0; i < NNN; i++) { + #pragma omp loop bind(teams) // expected-error{{region cannot be closely nested inside 'teams loop' region; perhaps you forget to enclose 'omp loop' directive into a teams region?}} + for (int j = 0 ; j < NNN ; j++) { + aaa[i] = i+i*NNN; + } + } +} + +void thread_loop() { + #pragma omp parallel + for (int i = 0; i < NNN; i++) { + #pragma omp loop bind(thread) + for (int j = 0 ; j < NNN ; j++) { + aaa[i] = i+i*NNN; + } + } + + #pragma omp teams + for (int i = 0; i < NNN; i++) { + #pragma omp loop bind(thread) + for (int j = 0 ; j < NNN ; j++) { + aaa[i] = i+i*NNN; + } + } +} + +void parallel_for_with_loop_teams_bind(){ + #pragma omp parallel for + for (int i = 0; i < NNN; i++) { + #pragma omp loop bind(teams) // expected-error{{region cannot be closely nested inside 'parallel for' region; perhaps you forget to enclose 'omp loop' directive into a teams region?}} + for (int j = 0 ; j < NNN ; j++) { + aaa[i] = i+i*NNN; + } + } +} + +void orphan_loops() { + #pragma omp loop // expected-error{{expected 'bind' clause for 'loop' construct without an enclosing OpenMP construct}} + for (int j = 0 ; j < NNN ; j++) { + aaa[j] = j*NNN; + } + + #pragma omp loop bind(parallel) + for (int j = 0 ; j < NNN ; j++) { + aaa[j] = j*NNN; + } + + #pragma omp loop bind(teams) + for (int i = 0; i < NNN; i++) { + aaa[i] = i+i*NNN; + } + + #pragma omp loop bind(thread) + for (int i = 0; i < NNN; i++) { + aaa[i] = i+i*NNN; + } } int main(int argc, char *argv[]) { parallel_loop(); teams_loop(); - orphan_loop_with_bind(); - orphan_loop_no_bind(); - teams_loop_reduction(); + thread_loop(); + parallel_for_with_loop_teams_bind(); + orphan_loops(); } #endif diff --git a/clang/test/OpenMP/master_taskloop_in_reduction_codegen.cpp b/clang/test/OpenMP/master_taskloop_in_reduction_codegen.cpp index 7afaf035988f08d5dcd1c4a54935703b4197a956..41c086c7e1d0631a274c66d2e6fe1bfbebae3f30 100644 --- a/clang/test/OpenMP/master_taskloop_in_reduction_codegen.cpp +++ b/clang/test/OpenMP/master_taskloop_in_reduction_codegen.cpp @@ -339,7 +339,7 @@ int main(int argc, char **argv) { // CHECK1: omp.arraycpy.body: // CHECK1-NEXT: [[OMP_ARRAYCPY_SRCELEMENTPAST:%.*]] = phi ptr [ [[TMP3]], [[ENTRY:%.*]] ], [ [[OMP_ARRAYCPY_SRC_ELEMENT:%.*]], [[OMP_ARRAYCPY_BODY]] ] // CHECK1-NEXT: [[OMP_ARRAYCPY_DESTELEMENTPAST:%.*]] = phi ptr [ [[TMP2]], [[ENTRY]] ], [ [[OMP_ARRAYCPY_DEST_ELEMENT:%.*]], [[OMP_ARRAYCPY_BODY]] ] -// CHECK1-NEXT: call void @_ZplRK1SS1_(ptr sret([[STRUCT_S]]) align 4 [[REF_TMP]], ptr nonnull align 4 dereferenceable(4) [[OMP_ARRAYCPY_DESTELEMENTPAST]], ptr nonnull align 4 dereferenceable(4) [[OMP_ARRAYCPY_SRCELEMENTPAST]]) +// CHECK1-NEXT: call void @_ZplRK1SS1_(ptr dead_on_unwind writable sret([[STRUCT_S]]) align 4 [[REF_TMP]], ptr nonnull align 4 dereferenceable(4) [[OMP_ARRAYCPY_DESTELEMENTPAST]], ptr nonnull align 4 dereferenceable(4) [[OMP_ARRAYCPY_SRCELEMENTPAST]]) // CHECK1-NEXT: [[CALL:%.*]] = call nonnull align 4 dereferenceable(4) ptr @_ZN1SaSERKS_(ptr nonnull align 4 dereferenceable(4) [[OMP_ARRAYCPY_DESTELEMENTPAST]], ptr nonnull align 4 dereferenceable(4) [[REF_TMP]]) // CHECK1-NEXT: call void @_ZN1SD1Ev(ptr nonnull align 4 dereferenceable(4) [[REF_TMP]]) #[[ATTR3]] // CHECK1-NEXT: [[OMP_ARRAYCPY_DEST_ELEMENT]] = getelementptr [[STRUCT_S]], ptr [[OMP_ARRAYCPY_DESTELEMENTPAST]], i32 1 @@ -351,7 +351,7 @@ int main(int argc, char **argv) { // // // CHECK1-LABEL: define {{[^@]+}}@_ZplRK1SS1_ -// CHECK1-SAME: (ptr noalias sret([[STRUCT_S:%.*]]) align 4 [[AGG_RESULT:%.*]], ptr nonnull align 4 dereferenceable(4) [[A:%.*]], ptr nonnull align 4 dereferenceable(4) [[B:%.*]]) #[[ATTR1]] { +// CHECK1-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_S:%.*]]) align 4 [[AGG_RESULT:%.*]], ptr nonnull align 4 dereferenceable(4) [[A:%.*]], ptr nonnull align 4 dereferenceable(4) [[B:%.*]]) #[[ATTR1]] { // CHECK1-NEXT: entry: // CHECK1-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 8 // CHECK1-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 8 diff --git a/clang/test/OpenMP/master_taskloop_simd_in_reduction_codegen.cpp b/clang/test/OpenMP/master_taskloop_simd_in_reduction_codegen.cpp index 5d6404cd3e54b3774318beda533d3576f0bf5e69..f25fe346c835e37ad61806c86e391191cd847c7e 100644 --- a/clang/test/OpenMP/master_taskloop_simd_in_reduction_codegen.cpp +++ b/clang/test/OpenMP/master_taskloop_simd_in_reduction_codegen.cpp @@ -339,7 +339,7 @@ int main(int argc, char **argv) { // CHECK1: omp.arraycpy.body: // CHECK1-NEXT: [[OMP_ARRAYCPY_SRCELEMENTPAST:%.*]] = phi ptr [ [[TMP3]], [[ENTRY:%.*]] ], [ [[OMP_ARRAYCPY_SRC_ELEMENT:%.*]], [[OMP_ARRAYCPY_BODY]] ] // CHECK1-NEXT: [[OMP_ARRAYCPY_DESTELEMENTPAST:%.*]] = phi ptr [ [[TMP2]], [[ENTRY]] ], [ [[OMP_ARRAYCPY_DEST_ELEMENT:%.*]], [[OMP_ARRAYCPY_BODY]] ] -// CHECK1-NEXT: call void @_ZplRK1SS1_(ptr sret([[STRUCT_S]]) align 4 [[REF_TMP]], ptr nonnull align 4 dereferenceable(4) [[OMP_ARRAYCPY_DESTELEMENTPAST]], ptr nonnull align 4 dereferenceable(4) [[OMP_ARRAYCPY_SRCELEMENTPAST]]) +// CHECK1-NEXT: call void @_ZplRK1SS1_(ptr dead_on_unwind writable sret([[STRUCT_S]]) align 4 [[REF_TMP]], ptr nonnull align 4 dereferenceable(4) [[OMP_ARRAYCPY_DESTELEMENTPAST]], ptr nonnull align 4 dereferenceable(4) [[OMP_ARRAYCPY_SRCELEMENTPAST]]) // CHECK1-NEXT: [[CALL:%.*]] = call nonnull align 4 dereferenceable(4) ptr @_ZN1SaSERKS_(ptr nonnull align 4 dereferenceable(4) [[OMP_ARRAYCPY_DESTELEMENTPAST]], ptr nonnull align 4 dereferenceable(4) [[REF_TMP]]) // CHECK1-NEXT: call void @_ZN1SD1Ev(ptr nonnull align 4 dereferenceable(4) [[REF_TMP]]) #[[ATTR3]] // CHECK1-NEXT: [[OMP_ARRAYCPY_DEST_ELEMENT]] = getelementptr [[STRUCT_S]], ptr [[OMP_ARRAYCPY_DESTELEMENTPAST]], i32 1 @@ -351,7 +351,7 @@ int main(int argc, char **argv) { // // // CHECK1-LABEL: define {{[^@]+}}@_ZplRK1SS1_ -// CHECK1-SAME: (ptr noalias sret([[STRUCT_S:%.*]]) align 4 [[AGG_RESULT:%.*]], ptr nonnull align 4 dereferenceable(4) [[A:%.*]], ptr nonnull align 4 dereferenceable(4) [[B:%.*]]) #[[ATTR1]] { +// CHECK1-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_S:%.*]]) align 4 [[AGG_RESULT:%.*]], ptr nonnull align 4 dereferenceable(4) [[A:%.*]], ptr nonnull align 4 dereferenceable(4) [[B:%.*]]) #[[ATTR1]] { // CHECK1-NEXT: entry: // CHECK1-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 8 // CHECK1-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 8 diff --git a/clang/test/OpenMP/target_in_reduction_codegen.cpp b/clang/test/OpenMP/target_in_reduction_codegen.cpp index 2eb6058461244a35acac33d98c6e71e8634607a3..c6b8afba52ee5a03b54d71b3d6498d2669c1db99 100644 --- a/clang/test/OpenMP/target_in_reduction_codegen.cpp +++ b/clang/test/OpenMP/target_in_reduction_codegen.cpp @@ -333,7 +333,7 @@ int main(int argc, char **argv) { // CHECK1: omp.arraycpy.body: // CHECK1-NEXT: [[OMP_ARRAYCPY_SRCELEMENTPAST:%.*]] = phi ptr [ [[TMP5]], [[ENTRY:%.*]] ], [ [[OMP_ARRAYCPY_SRC_ELEMENT:%.*]], [[OMP_ARRAYCPY_BODY]] ] // CHECK1-NEXT: [[OMP_ARRAYCPY_DESTELEMENTPAST:%.*]] = phi ptr [ [[TMP3]], [[ENTRY]] ], [ [[OMP_ARRAYCPY_DEST_ELEMENT:%.*]], [[OMP_ARRAYCPY_BODY]] ] -// CHECK1-NEXT: call void @_ZplRK1SS1_(ptr sret([[STRUCT_S]]) align 4 [[REF_TMP]], ptr nonnull align 4 dereferenceable(4) [[OMP_ARRAYCPY_DESTELEMENTPAST]], ptr nonnull align 4 dereferenceable(4) [[OMP_ARRAYCPY_SRCELEMENTPAST]]) +// CHECK1-NEXT: call void @_ZplRK1SS1_(ptr dead_on_unwind writable sret([[STRUCT_S]]) align 4 [[REF_TMP]], ptr nonnull align 4 dereferenceable(4) [[OMP_ARRAYCPY_DESTELEMENTPAST]], ptr nonnull align 4 dereferenceable(4) [[OMP_ARRAYCPY_SRCELEMENTPAST]]) // CHECK1-NEXT: [[CALL:%.*]] = call nonnull align 4 dereferenceable(4) ptr @_ZN1SaSERKS_(ptr nonnull align 4 dereferenceable(4) [[OMP_ARRAYCPY_DESTELEMENTPAST]], ptr nonnull align 4 dereferenceable(4) [[REF_TMP]]) // CHECK1-NEXT: call void @_ZN1SD1Ev(ptr nonnull align 4 dereferenceable(4) [[REF_TMP]]) #3 // CHECK1-NEXT: [[OMP_ARRAYCPY_DEST_ELEMENT]] = getelementptr [[STRUCT_S]], ptr [[OMP_ARRAYCPY_DESTELEMENTPAST]], i32 1 @@ -345,7 +345,7 @@ int main(int argc, char **argv) { // // // CHECK1-LABEL: define {{[^@]+}}@_ZplRK1SS1_ -// CHECK1-SAME: (ptr noalias sret([[STRUCT_S:%.*]]) align 4 [[AGG_RESULT:%.*]], ptr nonnull align 4 dereferenceable(4) [[A:%.*]], ptr nonnull align 4 dereferenceable(4) [[B:%.*]]) #[[ATTR7:[0-9]+]] { +// CHECK1-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_S:%.*]]) align 4 [[AGG_RESULT:%.*]], ptr nonnull align 4 dereferenceable(4) [[A:%.*]], ptr nonnull align 4 dereferenceable(4) [[B:%.*]]) #[[ATTR7:[0-9]+]] { // CHECK1-NEXT: entry: // CHECK1-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 8 // CHECK1-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 8 diff --git a/clang/test/OpenMP/task_in_reduction_codegen.cpp b/clang/test/OpenMP/task_in_reduction_codegen.cpp index 82d2038943646f2a90abc27d14b302043da454ec..348bd7bea3b4a54dbe201d2d752921c7bf63b1f3 100644 --- a/clang/test/OpenMP/task_in_reduction_codegen.cpp +++ b/clang/test/OpenMP/task_in_reduction_codegen.cpp @@ -361,7 +361,7 @@ int main(int argc, char **argv) { // CHECK1: omp.arraycpy.body: // CHECK1-NEXT: [[OMP_ARRAYCPY_SRCELEMENTPAST:%.*]] = phi ptr [ [[TMP3]], [[ENTRY:%.*]] ], [ [[OMP_ARRAYCPY_SRC_ELEMENT:%.*]], [[OMP_ARRAYCPY_BODY]] ] // CHECK1-NEXT: [[OMP_ARRAYCPY_DESTELEMENTPAST:%.*]] = phi ptr [ [[TMP2]], [[ENTRY]] ], [ [[OMP_ARRAYCPY_DEST_ELEMENT:%.*]], [[OMP_ARRAYCPY_BODY]] ] -// CHECK1-NEXT: call void @_ZplRK1SS1_(ptr sret([[STRUCT_S]]) align 4 [[REF_TMP]], ptr nonnull align 4 dereferenceable(4) [[OMP_ARRAYCPY_DESTELEMENTPAST]], ptr nonnull align 4 dereferenceable(4) [[OMP_ARRAYCPY_SRCELEMENTPAST]]) +// CHECK1-NEXT: call void @_ZplRK1SS1_(ptr dead_on_unwind writable sret([[STRUCT_S]]) align 4 [[REF_TMP]], ptr nonnull align 4 dereferenceable(4) [[OMP_ARRAYCPY_DESTELEMENTPAST]], ptr nonnull align 4 dereferenceable(4) [[OMP_ARRAYCPY_SRCELEMENTPAST]]) // CHECK1-NEXT: [[CALL:%.*]] = call nonnull align 4 dereferenceable(4) ptr @_ZN1SaSERKS_(ptr nonnull align 4 dereferenceable(4) [[OMP_ARRAYCPY_DESTELEMENTPAST]], ptr nonnull align 4 dereferenceable(4) [[REF_TMP]]) // CHECK1-NEXT: call void @_ZN1SD1Ev(ptr nonnull align 4 dereferenceable(4) [[REF_TMP]]) #[[ATTR3]] // CHECK1-NEXT: [[OMP_ARRAYCPY_DEST_ELEMENT]] = getelementptr [[STRUCT_S]], ptr [[OMP_ARRAYCPY_DESTELEMENTPAST]], i32 1 @@ -373,7 +373,7 @@ int main(int argc, char **argv) { // // // CHECK1-LABEL: define {{[^@]+}}@_ZplRK1SS1_ -// CHECK1-SAME: (ptr noalias sret([[STRUCT_S:%.*]]) align 4 [[AGG_RESULT:%.*]], ptr nonnull align 4 dereferenceable(4) [[A:%.*]], ptr nonnull align 4 dereferenceable(4) [[B:%.*]]) #[[ATTR1]] { +// CHECK1-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_S:%.*]]) align 4 [[AGG_RESULT:%.*]], ptr nonnull align 4 dereferenceable(4) [[A:%.*]], ptr nonnull align 4 dereferenceable(4) [[B:%.*]]) #[[ATTR1]] { // CHECK1-NEXT: entry: // CHECK1-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 8 // CHECK1-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 8 diff --git a/clang/test/OpenMP/taskloop_in_reduction_codegen.cpp b/clang/test/OpenMP/taskloop_in_reduction_codegen.cpp index e48035a71eea99379dd20143d0770bf04d2fed75..abf9164b789d3cee736f5b02954d7a0a767e833c 100644 --- a/clang/test/OpenMP/taskloop_in_reduction_codegen.cpp +++ b/clang/test/OpenMP/taskloop_in_reduction_codegen.cpp @@ -339,7 +339,7 @@ int main(int argc, char **argv) { // CHECK1: omp.arraycpy.body: // CHECK1-NEXT: [[OMP_ARRAYCPY_SRCELEMENTPAST:%.*]] = phi ptr [ [[TMP3]], [[ENTRY:%.*]] ], [ [[OMP_ARRAYCPY_SRC_ELEMENT:%.*]], [[OMP_ARRAYCPY_BODY]] ] // CHECK1-NEXT: [[OMP_ARRAYCPY_DESTELEMENTPAST:%.*]] = phi ptr [ [[TMP2]], [[ENTRY]] ], [ [[OMP_ARRAYCPY_DEST_ELEMENT:%.*]], [[OMP_ARRAYCPY_BODY]] ] -// CHECK1-NEXT: call void @_ZplRK1SS1_(ptr sret([[STRUCT_S]]) align 4 [[REF_TMP]], ptr nonnull align 4 dereferenceable(4) [[OMP_ARRAYCPY_DESTELEMENTPAST]], ptr nonnull align 4 dereferenceable(4) [[OMP_ARRAYCPY_SRCELEMENTPAST]]) +// CHECK1-NEXT: call void @_ZplRK1SS1_(ptr dead_on_unwind writable sret([[STRUCT_S]]) align 4 [[REF_TMP]], ptr nonnull align 4 dereferenceable(4) [[OMP_ARRAYCPY_DESTELEMENTPAST]], ptr nonnull align 4 dereferenceable(4) [[OMP_ARRAYCPY_SRCELEMENTPAST]]) // CHECK1-NEXT: [[CALL:%.*]] = call nonnull align 4 dereferenceable(4) ptr @_ZN1SaSERKS_(ptr nonnull align 4 dereferenceable(4) [[OMP_ARRAYCPY_DESTELEMENTPAST]], ptr nonnull align 4 dereferenceable(4) [[REF_TMP]]) // CHECK1-NEXT: call void @_ZN1SD1Ev(ptr nonnull align 4 dereferenceable(4) [[REF_TMP]]) #[[ATTR3]] // CHECK1-NEXT: [[OMP_ARRAYCPY_DEST_ELEMENT]] = getelementptr [[STRUCT_S]], ptr [[OMP_ARRAYCPY_DESTELEMENTPAST]], i32 1 @@ -351,7 +351,7 @@ int main(int argc, char **argv) { // // // CHECK1-LABEL: define {{[^@]+}}@_ZplRK1SS1_ -// CHECK1-SAME: (ptr noalias sret([[STRUCT_S:%.*]]) align 4 [[AGG_RESULT:%.*]], ptr nonnull align 4 dereferenceable(4) [[A:%.*]], ptr nonnull align 4 dereferenceable(4) [[B:%.*]]) #[[ATTR1]] { +// CHECK1-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_S:%.*]]) align 4 [[AGG_RESULT:%.*]], ptr nonnull align 4 dereferenceable(4) [[A:%.*]], ptr nonnull align 4 dereferenceable(4) [[B:%.*]]) #[[ATTR1]] { // CHECK1-NEXT: entry: // CHECK1-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 8 // CHECK1-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 8 diff --git a/clang/test/OpenMP/taskloop_simd_in_reduction_codegen.cpp b/clang/test/OpenMP/taskloop_simd_in_reduction_codegen.cpp index e4d24fa4824400be914ba172a6797cccd4c58a7e..f279596401a8e7d2a187fa0c0fee10d2149d3cb3 100644 --- a/clang/test/OpenMP/taskloop_simd_in_reduction_codegen.cpp +++ b/clang/test/OpenMP/taskloop_simd_in_reduction_codegen.cpp @@ -339,7 +339,7 @@ int main(int argc, char **argv) { // CHECK1: omp.arraycpy.body: // CHECK1-NEXT: [[OMP_ARRAYCPY_SRCELEMENTPAST:%.*]] = phi ptr [ [[TMP3]], [[ENTRY:%.*]] ], [ [[OMP_ARRAYCPY_SRC_ELEMENT:%.*]], [[OMP_ARRAYCPY_BODY]] ] // CHECK1-NEXT: [[OMP_ARRAYCPY_DESTELEMENTPAST:%.*]] = phi ptr [ [[TMP2]], [[ENTRY]] ], [ [[OMP_ARRAYCPY_DEST_ELEMENT:%.*]], [[OMP_ARRAYCPY_BODY]] ] -// CHECK1-NEXT: call void @_ZplRK1SS1_(ptr sret([[STRUCT_S]]) align 4 [[REF_TMP]], ptr nonnull align 4 dereferenceable(4) [[OMP_ARRAYCPY_DESTELEMENTPAST]], ptr nonnull align 4 dereferenceable(4) [[OMP_ARRAYCPY_SRCELEMENTPAST]]) +// CHECK1-NEXT: call void @_ZplRK1SS1_(ptr dead_on_unwind writable sret([[STRUCT_S]]) align 4 [[REF_TMP]], ptr nonnull align 4 dereferenceable(4) [[OMP_ARRAYCPY_DESTELEMENTPAST]], ptr nonnull align 4 dereferenceable(4) [[OMP_ARRAYCPY_SRCELEMENTPAST]]) // CHECK1-NEXT: [[CALL:%.*]] = call nonnull align 4 dereferenceable(4) ptr @_ZN1SaSERKS_(ptr nonnull align 4 dereferenceable(4) [[OMP_ARRAYCPY_DESTELEMENTPAST]], ptr nonnull align 4 dereferenceable(4) [[REF_TMP]]) // CHECK1-NEXT: call void @_ZN1SD1Ev(ptr nonnull align 4 dereferenceable(4) [[REF_TMP]]) #[[ATTR3]] // CHECK1-NEXT: [[OMP_ARRAYCPY_DEST_ELEMENT]] = getelementptr [[STRUCT_S]], ptr [[OMP_ARRAYCPY_DESTELEMENTPAST]], i32 1 @@ -351,7 +351,7 @@ int main(int argc, char **argv) { // // // CHECK1-LABEL: define {{[^@]+}}@_ZplRK1SS1_ -// CHECK1-SAME: (ptr noalias sret([[STRUCT_S:%.*]]) align 4 [[AGG_RESULT:%.*]], ptr nonnull align 4 dereferenceable(4) [[A:%.*]], ptr nonnull align 4 dereferenceable(4) [[B:%.*]]) #[[ATTR1]] { +// CHECK1-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_S:%.*]]) align 4 [[AGG_RESULT:%.*]], ptr nonnull align 4 dereferenceable(4) [[A:%.*]], ptr nonnull align 4 dereferenceable(4) [[B:%.*]]) #[[ATTR1]] { // CHECK1-NEXT: entry: // CHECK1-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 8 // CHECK1-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 8 diff --git a/clang/test/PCH/pragma-loop.cpp b/clang/test/PCH/pragma-loop.cpp index f5de630ffc91206b4bf3b59cf481994a6eaefb9b..a3c6871041c0eec0863d27bbeef3b5fd360e23dd 100644 --- a/clang/test/PCH/pragma-loop.cpp +++ b/clang/test/PCH/pragma-loop.cpp @@ -116,9 +116,13 @@ public: inline void run10(int *List, int Length) { int i = 0; -#pragma omp loop bind(teams) + int j = 0; + #pragma omp teams for (int i = 0; i < Length; i++) { - List[i] = i; + #pragma omp loop bind(teams) + for (int j = 0; j < Length; j++) { + List[i] = i+j; + } } } diff --git a/clang/test/Parser/gh30908-scope-balance-on-invalid-var-direct-init-1.cpp b/clang/test/Parser/gh30908-scope-balance-on-invalid-var-direct-init-1.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1a692fe8ff1e72f7479a9eeac0a05354aad1a364 --- /dev/null +++ b/clang/test/Parser/gh30908-scope-balance-on-invalid-var-direct-init-1.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -ferror-limit 2 -fsyntax-only -verify %s + +// expected-error@* {{too many errors emitted}} + +namespace llvm { +namespace Hexagon {} +} +void set() { + Hexagon::NoRegister; + // expected-error@-1 {{use of undeclared identifier}} + // expected-note@-5 {{declared here}} + // expected-error@-3 {{no member named 'NoRegister' in namespace}} +} +template struct pair { pair(int, int); }; +struct HexagonMCChecker { + static pair Unconditional; + void checkRegisters(); +}; +pair HexagonMCChecker::Unconditional(Hexagon::NoRegister, 0); +void HexagonMCChecker::checkRegisters() {} diff --git a/clang/test/Parser/gh30908-scope-balance-on-invalid-var-direct-init-2.cpp b/clang/test/Parser/gh30908-scope-balance-on-invalid-var-direct-init-2.cpp new file mode 100644 index 0000000000000000000000000000000000000000..02200ce4f34a7516ae98189f852f63ae7f1c314e --- /dev/null +++ b/clang/test/Parser/gh30908-scope-balance-on-invalid-var-direct-init-2.cpp @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +#include // expected-error {{file not found}} + +class S {}; + +template +class E { +public: + E(S* scope) {} + S &getS(); +}; + +class Z { + private: + static E e; + static S& s(); +}; + +E Z::e(&__UNKNOWN_ID__); + +S& Z::s() { return Z::e.getS(); } diff --git a/clang/test/ParserOpenACC/parse-cache-construct.c b/clang/test/ParserOpenACC/parse-cache-construct.c index 560f45423bc2b9a7bfdd201fdb12ed32a320eb0a..d54632fc8f466ae6ed30c9d6969d53400d9ceff0 100644 --- a/clang/test/ParserOpenACC/parse-cache-construct.c +++ b/clang/test/ParserOpenACC/parse-cache-construct.c @@ -1,10 +1,15 @@ // RUN: %clang_cc1 %s -verify -fopenacc +struct S { + int foo; + char Array[1]; +}; char *getArrayPtr(); void func() { char Array[10]; char *ArrayPtr = getArrayPtr(); int *readonly; + struct S s; for (int i = 0; i < 10; ++i) { // expected-error@+2{{expected '('}} @@ -46,7 +51,6 @@ void func() { } for (int i = 0; i < 10; ++i) { - // expected-error@+4{{expected '['}} // expected-error@+3{{expected ')'}} // expected-note@+2{{to match this '('}} // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} @@ -60,13 +64,14 @@ void func() { } for (int i = 0; i < 10; ++i) { - // expected-error@+2{{expected '['}} // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} #pragma acc cache(ArrayPtr) } for (int i = 0; i < 10; ++i) { - // expected-error@+4{{expected expression}} + // expected-error@+6{{expected expression}} + // expected-error@+5{{expected ']'}} + // expected-note@+4{{to match this '['}} // expected-error@+3{{expected ')'}} // expected-note@+2{{to match this '('}} // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} @@ -74,13 +79,17 @@ void func() { } for (int i = 0; i < 10; ++i) { - // expected-error@+2{{expected expression}} + // expected-error@+4{{expected expression}} + // expected-error@+3{{expected ']'}} + // expected-note@+2{{to match this '['}} // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} #pragma acc cache(ArrayPtr[, 5) } for (int i = 0; i < 10; ++i) { - // expected-error@+2{{expected expression}} + // expected-error@+4{{expected expression}} + // expected-error@+3{{expected ']'}} + // expected-note@+2{{to match this '['}} // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} #pragma acc cache(Array[) } @@ -91,7 +100,9 @@ void func() { } for (int i = 0; i < 10; ++i) { - // expected-error@+4{{expected expression}} + // expected-error@+6{{expected expression}} + // expected-error@+5{{expected ']'}} + // expected-note@+4{{to match this '['}} // expected-error@+3{{expected ')'}} // expected-note@+2{{to match this '('}} // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} @@ -99,13 +110,11 @@ void func() { } for (int i = 0; i < 10; ++i) { - // expected-error@+2{{expected '['}} // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} #pragma acc cache(readonly) } for (int i = 0; i < 10; ++i) { - // expected-error@+2{{expected '['}} // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} #pragma acc cache(readonly:ArrayPtr) } @@ -122,7 +131,6 @@ void func() { } for (int i = 0; i < 10; ++i) { - // expected-error@+2{{expected '['}} // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} #pragma acc cache(readonly:ArrayPtr[5:*readonly], Array) } @@ -138,7 +146,7 @@ void func() { } for (int i = 0; i < 10; ++i) { - // expected-error@+4{{expected identifier}} + // expected-error@+4{{expected expression}} // expected-error@+3{{expected ')'}} // expected-note@+2{{to match this '('}} // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} @@ -146,7 +154,7 @@ void func() { } for (int i = 0; i < 10; ++i) { - // expected-error@+2{{expected identifier}} + // expected-error@+2{{expected expression}} // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} #pragma acc cache(readonly:ArrayPtr[5:*readonly],) } @@ -163,4 +171,14 @@ void func() { #pragma acc cache(readonly:ArrayPtr[5:3, *readonly], ArrayPtr[0]) } + for (int i = 0; i < 10; ++i) { + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc cache(readonly:s.foo) + } + + for (int i = 0; i < 10; ++i) { + // expected-warning@+2{{left operand of comma operator has no effect}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc cache(readonly:s.Array[1,2]) + } } diff --git a/clang/test/ParserOpenACC/parse-cache-construct.cpp b/clang/test/ParserOpenACC/parse-cache-construct.cpp index 3b2230cabae32fd0824708b53bcdfee4d87a2428..affe43d4b0f0babf044abe2c9f05afb7e10056dc 100644 --- a/clang/test/ParserOpenACC/parse-cache-construct.cpp +++ b/clang/test/ParserOpenACC/parse-cache-construct.cpp @@ -46,6 +46,71 @@ struct S { static constexpr char array[] ={1,2,3,4,5}; }; +struct Members { + int value = 5; + char array[5] ={1,2,3,4,5}; +}; +struct HasMembersArray { + Members MemArr[4]; +}; + + void use() { + + Members s; + for (int i = 0; i < 10; ++i) { + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc cache(s.array[s.value]) + } + HasMembersArray Arrs; + for (int i = 0; i < 10; ++i) { + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc cache(Arrs.MemArr[3].array[4]) + } + for (int i = 0; i < 10; ++i) { + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc cache(Arrs.MemArr[3].array[1:4]) + } + for (int i = 0; i < 10; ++i) { + // FIXME: Once we have a new array-section type to represent OpenACC as + // well, change this error message. + // expected-error@+2{{OpenMP array section is not allowed here}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc cache(Arrs.MemArr[3:4].array[1:4]) + } + for (int i = 0; i < 10; ++i) { + // expected-error@+2{{OpenMP array section is not allowed here}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc cache(Arrs.MemArr[3:4].array[4]) + } + for (int i = 0; i < 10; ++i) { + // expected-error@+3{{expected ']'}} + // expected-note@+2{{to match this '['}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc cache(Arrs.MemArr[3:4:].array[4]) + } + for (int i = 0; i < 10; ++i) { + // expected-error@+2{{expected expression}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc cache(Arrs.MemArr[:].array[4]) + } + for (int i = 0; i < 10; ++i) { + // expected-error@+2{{expected unqualified-id}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc cache(Arrs.MemArr[::].array[4]) + } + for (int i = 0; i < 10; ++i) { + // expected-error@+4{{expected expression}} + // expected-error@+3{{expected ']'}} + // expected-note@+2{{to match this '['}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc cache(Arrs.MemArr[: :].array[4]) + } + for (int i = 0; i < 10; ++i) { + // expected-error@+2{{expected expression}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc cache(Arrs.MemArr[3:].array[4]) + } func(); } + diff --git a/clang/test/ParserOpenACC/parse-clauses.c b/clang/test/ParserOpenACC/parse-clauses.c index aedf0c711ad15b29728b0304dc3dc23d6406a62f..053d007839dc71eb66a7bb0cb5988a828bc567ed 100644 --- a/clang/test/ParserOpenACC/parse-clauses.c +++ b/clang/test/ParserOpenACC/parse-clauses.c @@ -148,7 +148,354 @@ void DefaultClause() { // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} #pragma acc serial default(present), seq for(;;){} +} + +void IfClause() { + // expected-error@+2{{expected '('}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial loop if + for(;;){} + + // expected-error@+2{{expected '('}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial if seq + for(;;){} + + // expected-error@+2{{expected '('}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial if, seq + for(;;){} + + // expected-error@+2{{expected expression}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial if( + for(;;){} + + // expected-error@+2{{use of undeclared identifier 'seq'}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial if( seq + for(;;){} + + // expected-error@+3{{expected expression}} + // expected-error@+2{{use of undeclared identifier 'seq'}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial if(, seq + for(;;){} + + // expected-error@+3{{expected '('}} + // expected-error@+2{{expected identifier}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial if) + for(;;){} + + // expected-error@+3{{expected '('}} + // expected-error@+2{{expected identifier}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial if) seq + for(;;){} + + // expected-error@+3{{expected '('}} + // expected-error@+2{{expected identifier}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial if), seq + for(;;){} + + // expected-error@+2{{expected expression}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial if() + for(;;){} + + // expected-error@+2{{expected expression}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial if() seq + for(;;){} + + // expected-error@+2{{expected expression}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial if(), seq + for(;;){} + + // expected-error@+2{{use of undeclared identifier 'invalid_expr'}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial if(invalid_expr) + for(;;){} + + // expected-error@+2{{expected expression}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial if() seq + for(;;){} + + int i, j; + + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial if(i > j) + for(;;){} + + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial if(1+5>3), seq + for(;;){} +} + +void SyncClause() { + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial loop self + for(;;){} + + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial loop self, seq + for(;;){} + + // expected-error@+2{{expected expression}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial loop self( + for(;;){} + + // expected-error@+2{{use of undeclared identifier 'seq'}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial loop self( seq + for(;;){} + + // expected-error@+3{{expected expression}} + // expected-error@+2{{use of undeclared identifier 'seq'}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial loop self(, seq + for(;;){} + + // expected-error@+2{{expected identifier}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial loop self) + for(;;){} + + // expected-error@+2{{expected identifier}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial loop self) seq + for(;;){} + + // expected-error@+2{{expected identifier}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial loop self), seq + for(;;){} + + + // expected-error@+2{{expected expression}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial loop self(), seq + for(;;){} + + // expected-error@+3{{expected expression}} + // expected-error@+2{{expected expression}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial loop self(,), seq + for(;;){} + + // expected-error@+2{{use of undeclared identifier 'invalid_expr'}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial loop self(invalid_expr), seq + for(;;){} + + int i, j; + + // expected-error@+3{{expected ')'}} + // expected-note@+2{{to match this '('}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial self(i > j + for(;;){} + + // expected-error@+2{{use of undeclared identifier 'seq'}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial self(i > j, seq + for(;;){} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial self(i > j) + for(;;){} + + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial self(1+5>3), seq + for(;;){} +} + +struct Members { + int value; + char array[5]; +}; +struct HasMembersArray { + struct Members MemArr[4]; +}; + +void VarListClauses() { + // expected-error@+2{{expected '('}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial copy + + // expected-error@+2{{expected '('}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial copy, seq + + // expected-error@+3{{expected '('}} + // expected-error@+2{{expected identifier}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial copy) + + // expected-error@+3{{expected '('}} + // expected-error@+2{{expected identifier}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial copy), seq + + // expected-error@+2{{expected expression}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial copy( + + // expected-error@+2{{expected expression}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial copy(, seq + + // expected-error@+2{{expected expression}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial copy() + + // expected-error@+2{{expected expression}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial copy(), seq + + struct Members s; + struct HasMembersArray HasMem; + + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial copy(s.array[s.value]), seq + + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial copy(s.array[s.value], s.array[s.value :5] ), seq + + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial copy(HasMem.MemArr[3].array[1]), seq + + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial copy(HasMem.MemArr[3].array[1:4]), seq + + // expected-error@+2{{OpenMP array section is not allowed here}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial copy(HasMem.MemArr[1:3].array[1]), seq + + // expected-error@+2{{OpenMP array section is not allowed here}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial copy(HasMem.MemArr[1:3].array[1:2]), seq + + // expected-error@+2{{expected expression}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial copy(HasMem.MemArr[:]), seq + + // expected-error@+2{{expected expression}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial copy(HasMem.MemArr[::]), seq + + // expected-error@+4{{expected expression}} + // expected-error@+3{{expected ']'}} + // expected-note@+2{{to match this '['}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial copy(HasMem.MemArr[: :]), seq + + // expected-error@+2{{expected expression}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial copy(HasMem.MemArr[3:]), seq + + // expected-error@+2{{expected ','}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial use_device(s.array[s.value] s.array[s.value :5] ), seq + + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial use_device(s.array[s.value : 5]), seq + + // expected-error@+2{{expected ','}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial no_create(s.array[s.value] s.array[s.value :5] ), seq + + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial no_create(s.array[s.value : 5], s.value), seq + + // expected-error@+2{{expected ','}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial present(s.array[s.value] s.array[s.value :5] ), seq + + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial present(s.array[s.value : 5], s.value), seq + + // expected-error@+2{{expected ','}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial deviceptr(s.array[s.value] s.array[s.value :5] ), seq + + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial deviceptr(s.array[s.value : 5], s.value), seq + + // expected-error@+2{{expected ','}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial attach(s.array[s.value] s.array[s.value :5] ), seq + + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial attach(s.array[s.value : 5], s.value), seq + + // expected-error@+2{{expected ','}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial detach(s.array[s.value] s.array[s.value :5] ), seq + + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial detach(s.array[s.value : 5], s.value), seq + + // expected-error@+2{{expected ','}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial private(s.array[s.value] s.array[s.value :5] ), seq + + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial private(s.array[s.value : 5], s.value), seq + + // expected-error@+2{{expected ','}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial firstprivate(s.array[s.value] s.array[s.value :5] ), seq + + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial firstprivate(s.array[s.value : 5], s.value), seq + + // expected-error@+2{{expected ','}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial delete(s.array[s.value] s.array[s.value :5] ), seq + + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial delete(s.array[s.value : 5], s.value), seq + + // expected-error@+2{{expected ','}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial use_device(s.array[s.value] s.array[s.value :5] ), seq + + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial use_device(s.array[s.value : 5], s.value), seq + + // expected-error@+2{{expected ','}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial device_resident(s.array[s.value] s.array[s.value :5] ), seq + + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial device_resident(s.array[s.value : 5], s.value), seq + + // expected-error@+2{{expected ','}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial link(s.array[s.value] s.array[s.value :5] ), seq + + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial link(s.array[s.value : 5], s.value), seq + + // expected-error@+2{{expected ','}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial host(s.array[s.value] s.array[s.value :5] ), seq + + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial host(s.array[s.value : 5], s.value), seq + + // expected-error@+2{{expected ','}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial device(s.array[s.value] s.array[s.value :5] ), seq + + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial device(s.array[s.value : 5], s.value), seq } diff --git a/clang/test/Preprocessor/aarch64-target-features.c b/clang/test/Preprocessor/aarch64-target-features.c index b3da54162da04b09b494eb2ccd9cdf2d74558838..80ce5a75c0477901b3b5f88c2c6ad9a77a9b6f08 100644 --- a/clang/test/Preprocessor/aarch64-target-features.c +++ b/clang/test/Preprocessor/aarch64-target-features.c @@ -45,10 +45,12 @@ // CHECK-NOT: __ARM_PCS_VFP 1 // CHECK-NOT: __ARM_SIZEOF_MINIMAL_ENUM 1 // CHECK-NOT: __ARM_SIZEOF_WCHAR_T 2 +// CHECK-NOT: __ARM_FEATURE_COPROC // CHECK-NOT: __ARM_FEATURE_SVE // CHECK-NOT: __ARM_FEATURE_DOTPROD // CHECK-NOT: __ARM_FEATURE_PAC_DEFAULT // CHECK-NOT: __ARM_FEATURE_BTI_DEFAULT +// CHECK-NOT: __ARM_FEATURE_GCS_DEFAULT // CHECK-NOT: __ARM_BF16_FORMAT_ALTERNATIVE 1 // CHECK-NOT: __ARM_FEATURE_BF16 1 // CHECK-NOT: __ARM_FEATURE_BF16_VECTOR_ARITHMETIC 1 @@ -587,6 +589,20 @@ // CHECK-SYS128: __ARM_FEATURE_SYSREG128 1 // CHECK-NOSYS128-NOT: __ARM_FEATURE_SYSREG128 1 +// ================== Check Armv8.9-A/Armv9.4-A Guarded Control Stack (FEAT_GCS) +// RUN: %clang -target aarch64-arm-none-eabi -march=armv8.9-a -x c -E -dM %s -o - | FileCheck --check-prefixes=CHECK-NOGCS,CHECK-NOGCS-DEFAULT %s +// RUN: %clang -target aarch64-arm-none-eabi -march=armv9.4-a -x c -E -dM %s -o - | FileCheck --check-prefixes=CHECK-NOGCS,CHECK-NOGCS-DEFAULT %s +// RUN: %clang -target aarch64-arm-none-eabi -march=armv8.9-a+gcs -x c -E -dM %s -o - | FileCheck --check-prefixes=CHECK-GCS,CHECK-NOGCS-DEFAULT %s +// RUN: %clang -target aarch64-arm-none-eabi -march=armv9.4-a+gcs -x c -E -dM %s -o - | FileCheck --check-prefixes=CHECK-GCS,CHECK-NOGCS-DEFAULT %s +// RUN: %clang -target aarch64-arm-none-eabi -march=armv8.9-a -mbranch-protection=gcs -x c -E -dM %s -o - | FileCheck --check-prefixes=CHECK-NOGCS,CHECK-GCS-DEFAULT %s +// RUN: %clang -target aarch64-arm-none-eabi -march=armv9.4-a -mbranch-protection=gcs -x c -E -dM %s -o - | FileCheck --check-prefixes=CHECK-NOGCS,CHECK-GCS-DEFAULT %s +// RUN: %clang -target aarch64-arm-none-eabi -march=armv8.9-a+gcs -mbranch-protection=gcs -x c -E -dM %s -o - | FileCheck --check-prefixes=CHECK-GCS,CHECK-GCS-DEFAULT %s +// RUN: %clang -target aarch64-arm-none-eabi -march=armv9.4-a+gcs -mbranch-protection=gcs -x c -E -dM %s -o - | FileCheck --check-prefixes=CHECK-GCS,CHECK-GCS-DEFAULT %s +// CHECK-GCS: __ARM_FEATURE_GCS 1 +// CHECK-NOGCS-NOT: __ARM_FEATURE_GCS 1 +// CHECK-GCS-DEFAULT: __ARM_FEATURE_GCS_DEFAULT 1 +// CHECK-NOGCS-DEFAULT-NOT: __ARM_FEATURE_GCS_DEFAULT 1 + // ================== Check default macros for Armv8.1-A and later // RUN: %clang -target aarch64-none-elf -march=armv8.1-a -x c -E -dM %s -o - | FileCheck --check-prefixes=CHECK-V81-OR-LATER,CHECK-BEFORE-V83,CHECK-BEFORE-V85 %s // RUN: %clang -target aarch64-none-elf -march=armv8.2-a -x c -E -dM %s -o - | FileCheck --check-prefixes=CHECK-V81-OR-LATER,CHECK-BEFORE-V83,CHECK-BEFORE-V85 %s diff --git a/clang/test/Sema/aarch64-sve2p1-intrinsics/acle_sve2p1_imm.cpp b/clang/test/Sema/aarch64-sve2p1-intrinsics/acle_sve2p1_imm.cpp index a3ec4c5b8b1bc750edebf9806e74a2056e78992f..a6154daadeeab382f411a130eeaca8993c70e2d3 100644 --- a/clang/test/Sema/aarch64-sve2p1-intrinsics/acle_sve2p1_imm.cpp +++ b/clang/test/Sema/aarch64-sve2p1-intrinsics/acle_sve2p1_imm.cpp @@ -114,9 +114,9 @@ void test_cntp(svcount_t c) { void test_svdot_lane_2way(svint32_t s32, svuint32_t u32, svint16_t s16, svuint16_t u16, svfloat32_t f32, svfloat16_t f16) { - svdot_lane_s32_s16_s16(s32, s16, s16, 4); // expected-error {{argument value 4 is outside the valid range [0, 3]}} - svdot_lane_u32_u16_u16(u32, u16, u16, 4); // expected-error {{argument value 4 is outside the valid range [0, 3]}} - svdot_lane_f32_f16_f16(f32, f16, f16, 4); // expected-error {{argument value 4 is outside the valid range [0, 3]}} + svdot_lane_s32_s16(s32, s16, s16, 4); // expected-error {{argument value 4 is outside the valid range [0, 3]}} + svdot_lane_u32_u16(u32, u16, u16, 4); // expected-error {{argument value 4 is outside the valid range [0, 3]}} + svdot_lane_f32_f16(f32, f16, f16, 4); // expected-error {{argument value 4 is outside the valid range [0, 3]}} } @@ -139,8 +139,8 @@ void test_svbfmul_lane(svbfloat16_t zn, svbfloat16_t zm, uint64_t idx){ __attribute__((target("+sve2p1"))) void test_svextq_lane(svint16_t zn_i16, svint16_t zm_i16, svfloat16_t zn_f16, svfloat16_t zm_f16){ - svextq_lane_s16(zn_i16, zm_i16, -1); // expected-error {{argument value -1 is outside the valid range [0, 15]}} - svextq_lane_f16(zn_f16, zm_f16, 16); // expected-error {{argument value 16 is outside the valid range [0, 15]}} + svextq_s16(zn_i16, zm_i16, -1); // expected-error {{argument value -1 is outside the valid range [0, 15]}} + svextq_f16(zn_f16, zm_f16, 16); // expected-error {{argument value 16 is outside the valid range [0, 15]}} } __attribute__((target("+sve2p1"))) diff --git a/clang/test/Sema/attr-counted-by.c b/clang/test/Sema/attr-counted-by.c new file mode 100644 index 0000000000000000000000000000000000000000..f14da9c77fa8b42bb7d955b67150ffc8d4ffcb22 --- /dev/null +++ b/clang/test/Sema/attr-counted-by.c @@ -0,0 +1,64 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +#define __counted_by(f) __attribute__((counted_by(f))) + +struct bar; + +struct not_found { + int count; + struct bar *fam[] __counted_by(bork); // expected-error {{use of undeclared identifier 'bork'}} +}; + +struct no_found_count_not_in_substruct { + unsigned long flags; + unsigned char count; // expected-note {{field 'count' declared here}} + struct A { + int dummy; + int array[] __counted_by(count); // expected-error {{'counted_by' field 'count' isn't within the same struct as the flexible array}} + } a; +}; + +struct not_found_suggest { + int bork; // expected-note {{'bork' declared here}} + struct bar *fam[] __counted_by(blork); // expected-error {{use of undeclared identifier 'blork'; did you mean 'bork'?}} +}; + +int global; // expected-note {{'global' declared here}} + +struct found_outside_of_struct { + int bork; + struct bar *fam[] __counted_by(global); // expected-error {{field 'global' in 'counted_by' not inside structure}} +}; + +struct self_referrential { + int bork; + struct bar *self[] __counted_by(self); // expected-error {{'counted_by' cannot refer to the flexible array 'self'}} +}; + +struct non_int_count { + double dbl_count; // expected-note {{field 'dbl_count' declared here}} + struct bar *fam[] __counted_by(dbl_count); // expected-error {{field 'dbl_count' in 'counted_by' must be a non-boolean integer type}} +}; + +struct array_of_ints_count { + int integers[2]; // expected-note {{field 'integers' declared here}} + struct bar *fam[] __counted_by(integers); // expected-error {{field 'integers' in 'counted_by' must be a non-boolean integer type}} +}; + +struct not_a_fam { + int count; + struct bar *non_fam __counted_by(count); // expected-error {{'counted_by' only applies to C99 flexible array members}} +}; + +struct not_a_c99_fam { + int count; + struct bar *non_c99_fam[0] __counted_by(count); // expected-error {{'counted_by' only applies to C99 flexible array members}} +}; + +struct annotated_with_anon_struct { + unsigned long flags; + struct { + unsigned char count; // expected-note {{'count' declared here}} + int array[] __counted_by(crount); // expected-error {{use of undeclared identifier 'crount'; did you mean 'count'?}} + }; +}; diff --git a/clang/test/Sema/attr-format-Float16.c b/clang/test/Sema/attr-format-Float16.c new file mode 100644 index 0000000000000000000000000000000000000000..6c3dfe14cec3c78ad78e092455adc4d661ceeba2 --- /dev/null +++ b/clang/test/Sema/attr-format-Float16.c @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -triple i686-linux-pc -target-feature +sse2 %s +// RUN: %clang_cc1 -fsyntax-only -verify -triple x86_64-linux-pc %s +// RUN: %clang_cc1 -fsyntax-only -verify -triple spir-unknown-unknown %s +// RUN: %clang_cc1 -fsyntax-only -verify -triple armv7a-linux-gnu %s +// RUN: %clang_cc1 -fsyntax-only -verify -triple aarch64-linux-gnu %s +// RUN: %clang_cc1 -fsyntax-only -verify -triple riscv32 %s +// RUN: %clang_cc1 -fsyntax-only -verify -triple riscv64 %s + +void a(const char *a, ...) __attribute__((format(printf, 1, 2))); // no-error + +void b(char *a, _Float16 b) __attribute__((format(printf, 1, 2))); // expected-warning {{GCC requires a function with the 'format' attribute to be variadic}} + +void call_no_default_promotion(void) { + a("%f", (_Float16)1.0); // expected-warning{{format specifies type 'double' but the argument has type '_Float16'}} + b("%f", (_Float16)1.0); // expected-warning{{format specifies type 'double' but the argument has type '_Float16'}} +} diff --git a/clang/test/SemaCXX/attr-format-Float16.cpp b/clang/test/SemaCXX/attr-format-Float16.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c61611d6b6a049ed74eb51dbc3c388eb1ee45c8f --- /dev/null +++ b/clang/test/SemaCXX/attr-format-Float16.cpp @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -triple i686-linux-pc -target-feature +sse2 %s +// RUN: %clang_cc1 -fsyntax-only -verify -triple x86_64-linux-pc %s +// RUN: %clang_cc1 -fsyntax-only -verify -triple spir-unknown-unknown %s +// RUN: %clang_cc1 -fsyntax-only -verify -triple armv7a-linux-gnu %s +// RUN: %clang_cc1 -fsyntax-only -verify -triple aarch64-linux-gnu %s +// RUN: %clang_cc1 -fsyntax-only -verify -triple riscv32 %s +// RUN: %clang_cc1 -fsyntax-only -verify -triple riscv64 %s + +template +__attribute__((format(printf, 1, 2))) +void format(const char *fmt, Args &&...args); // expected-warning{{GCC requires a function with the 'format' attribute to be variadic}} + +template +__attribute__((format(scanf, 1, 2))) +int scan(const char *fmt, Args &&...args); // expected-warning{{GCC requires a function with the 'format' attribute to be variadic}} + +void do_format() { + format("%f", (_Float16)123.f); // expected-warning{{format specifies type 'double' but the argument has type '_Float16'}} + + _Float16 Float16; + scan("%f", &Float16); // expected-warning{{format specifies type 'float *' but the argument has type '_Float16 *'}} + scan("%lf", &Float16); // expected-warning{{format specifies type 'double *' but the argument has type '_Float16 *'}} + scan("%Lf", &Float16); // expected-warning{{format specifies type 'long double *' but the argument has type '_Float16 *'}} +} diff --git a/clang/test/SemaCXX/conversion-function.cpp b/clang/test/SemaCXX/conversion-function.cpp index b6e6142d17906657307ae398d378180ff95147e7..749e2fc1b452b6a91e5a46b70380453c941c977b 100644 --- a/clang/test/SemaCXX/conversion-function.cpp +++ b/clang/test/SemaCXX/conversion-function.cpp @@ -475,13 +475,22 @@ struct S { #if __cplusplus >= 201103L namespace dependent_conversion_function_id_lookup { - template struct A { - operator T(); - }; - template struct B : A { - template using Lookup = decltype(&B::operator U); - }; - using Result = B::Lookup; - using Result = int (A::*)(); +namespace gh77583 { +struct A1 { + operator int(); +}; +template struct C { + template using Lookup = decltype(T{}.operator U()); +}; +C v{}; +} +template struct A2 { + operator T(); +}; +template struct B : A2 { + template using Lookup = decltype(&B::operator U); +}; +using Result = B::Lookup; +using Result = int (A2::*)(); } #endif diff --git a/clang/test/SemaCXX/cxx1z-noexcept-function-type.cpp b/clang/test/SemaCXX/cxx1z-noexcept-function-type.cpp index 11b1093f9064f682028562373455cfad8feee595..5e56f19477d6ca5d0fc08ea59d48abac3dcfc55c 100644 --- a/clang/test/SemaCXX/cxx1z-noexcept-function-type.cpp +++ b/clang/test/SemaCXX/cxx1z-noexcept-function-type.cpp @@ -64,6 +64,21 @@ namespace DependentDefaultCtorExceptionSpec { struct A { multimap Map; } a; static_assert(noexcept(A())); + + template struct NoexceptWithThis { + int ca; + template auto foo(T) noexcept(ca) { return true; } + // expected-error@-1 {{noexcept specifier argument is not a constant expression}} + // expected-note@-2 {{in instantiation of exception specification}} + // expected-note@-3 {{implicit use of 'this' pointer is only allowed within the evaluation of a call to a 'constexpr' member function}} + }; + struct InstantiateFromAnotherClass { + template (&B::foo))> // expected-note {{in instantiation of function template specialization}} + InstantiateFromAnotherClass(B *) {} // expected-note {{in instantiation of default argument}} + }; + NoexceptWithThis f{}; + // Don't crash here. + InstantiateFromAnotherClass b{&f}; // expected-note {{while substituting deduced template arguments into function template}} } #endif diff --git a/clang/test/SemaCXX/warn-range-loop-analysis-trivially-copyable.cpp b/clang/test/SemaCXX/warn-range-loop-analysis-trivially-copyable.cpp index e345ef40aed9ca5f74baf60cbcb8137202be2658..8fa387908c3658eacf7c93b6178b734b49e53f15 100644 --- a/clang/test/SemaCXX/warn-range-loop-analysis-trivially-copyable.cpp +++ b/clang/test/SemaCXX/warn-range-loop-analysis-trivially-copyable.cpp @@ -33,6 +33,17 @@ void test_TriviallyCopyable_64_bytes() { for (const auto r : records) (void)r; } +void test_TriviallyCopyConstructible_64_bytes() { + struct Record { + char a[64]; + Record& operator=(Record const& other){return *this;}; + + }; + + Record records[8]; + for (const auto r : records) + (void)r; +} void test_TriviallyCopyable_65_bytes() { struct Record { @@ -47,6 +58,19 @@ void test_TriviallyCopyable_65_bytes() { (void)r; } +void test_TriviallyCopyConstructible_65_bytes() { + struct Record { + char a[65]; + Record& operator=(Record const& other){return *this;}; + + }; + // expected-warning@+3 {{loop variable 'r' creates a copy from type 'const Record'}} + // expected-note@+2 {{use reference type 'const Record &' to prevent copying}} + Record records[8]; + for (const auto r : records) + (void)r; +} + void test_NonTriviallyCopyable() { struct Record { Record() {} @@ -87,3 +111,4 @@ void test_TrivialABI_65_bytes() { for (const auto r : records) (void)r; } + diff --git a/clang/test/SemaTemplate/GH75426.cpp b/clang/test/SemaTemplate/GH75426.cpp new file mode 100644 index 0000000000000000000000000000000000000000..faf70699f9c5f0fc00a2ec31b9b38e182e088f45 --- /dev/null +++ b/clang/test/SemaTemplate/GH75426.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s +// expected-no-diagnostics + +template concept C = true; + +struct A { + template void f(); +}; + +auto L = []{}; + +template +class Friends { + template friend void A::f(); + template friend void decltype(L)::operator()(); +}; diff --git a/clang/test/SemaTemplate/temp_arg_nontype_cxx20.cpp b/clang/test/SemaTemplate/temp_arg_nontype_cxx20.cpp index 792dc78464b2a879f098ff8f33b0372d3d8b5d1f..982f6ec221570845573a50d564ec864b93ffb0a0 100644 --- a/clang/test/SemaTemplate/temp_arg_nontype_cxx20.cpp +++ b/clang/test/SemaTemplate/temp_arg_nontype_cxx20.cpp @@ -93,6 +93,12 @@ namespace ConvertedConstant { template struct X {}; void f(X<1.0f>) {} void g(X<2>) {} + + struct { + int i : 2; + } b; + template struct Y {}; + void f(Y) {} // expected-error {{reference cannot bind to bit-field in converted constant expression}} } namespace CopyCounting { diff --git a/clang/tools/clang-format/.clang-format b/clang/tools/clang-format/.clang-format index d7331b3c8cf02ef7944e83a4280476627e33b31d..f95602cab0f7fcdf5d34c485d52b65993dbb83d9 100644 --- a/clang/tools/clang-format/.clang-format +++ b/clang/tools/clang-format/.clang-format @@ -1 +1,6 @@ -BasedOnStyle: clang-format +BasedOnStyle: LLVM +InsertBraces: true +InsertNewlineAtEOF: true +LineEnding: LF +RemoveBracesLLVM: true +RemoveParentheses: ReturnStatement diff --git a/clang/tools/clang-format/ClangFormat.cpp b/clang/tools/clang-format/ClangFormat.cpp index be34dbbe886a157ba5c389732e63137c570626b7..49ab7677a3ee9c215a17eba22de62277920bf099 100644 --- a/clang/tools/clang-format/ClangFormat.cpp +++ b/clang/tools/clang-format/ClangFormat.cpp @@ -571,6 +571,11 @@ static int dumpConfig(bool IsSTDIN) { return 0; } +using String = SmallString<128>; +static String IgnoreDir; // Directory of .clang-format-ignore file. +static String PrevDir; // Directory of previous `FilePath`. +static SmallVector Patterns; // Patterns in .clang-format-ignore file. + // Check whether `FilePath` is ignored according to the nearest // .clang-format-ignore file based on the rules below: // - A blank line is skipped. @@ -586,33 +591,50 @@ static bool isIgnored(StringRef FilePath) { if (!is_regular_file(FilePath)) return false; - using namespace llvm::sys::path; - SmallString<128> Path, AbsPath{FilePath}; + String Path; + String AbsPath{FilePath}; + using namespace llvm::sys::path; make_absolute(AbsPath); remove_dots(AbsPath, /*remove_dot_dot=*/true); - StringRef IgnoreDir{AbsPath}; - do { - IgnoreDir = parent_path(IgnoreDir); - if (IgnoreDir.empty()) + if (StringRef Dir{parent_path(AbsPath)}; PrevDir != Dir) { + PrevDir = Dir; + + for (;;) { + Path = Dir; + append(Path, ".clang-format-ignore"); + if (is_regular_file(Path)) + break; + Dir = parent_path(Dir); + if (Dir.empty()) + return false; + } + + IgnoreDir = convert_to_slash(Dir); + + std::ifstream IgnoreFile{Path.c_str()}; + if (!IgnoreFile.good()) return false; - Path = IgnoreDir; - append(Path, ".clang-format-ignore"); - } while (!is_regular_file(Path)); + Patterns.clear(); - std::ifstream IgnoreFile{Path.c_str()}; - if (!IgnoreFile.good()) - return false; + for (std::string Line; std::getline(IgnoreFile, Line);) { + if (const auto Pattern{StringRef{Line}.trim()}; + // Skip empty and comment lines. + !Pattern.empty() && Pattern[0] != '#') { + Patterns.push_back(Pattern); + } + } + } - const auto Pathname = convert_to_slash(AbsPath); - for (std::string Line; std::getline(IgnoreFile, Line);) { - auto Pattern = StringRef(Line).trim(); - if (Pattern.empty() || Pattern[0] == '#') - continue; + if (IgnoreDir.empty()) + return false; - const bool IsNegated = Pattern[0] == '!'; + const auto Pathname{convert_to_slash(AbsPath)}; + for (const auto &Pat : Patterns) { + const bool IsNegated = Pat[0] == '!'; + StringRef Pattern{Pat}; if (IsNegated) Pattern = Pattern.drop_front(); @@ -620,11 +642,14 @@ static bool isIgnored(StringRef FilePath) { continue; Pattern = Pattern.ltrim(); + + // `Pattern` is relative to `IgnoreDir` unless it starts with a slash. + // This doesn't support patterns containing drive names (e.g. `C:`). if (Pattern[0] != '/') { - Path = convert_to_slash(IgnoreDir); + Path = IgnoreDir; append(Path, Style::posix, Pattern); remove_dots(Path, /*remove_dot_dot=*/true, Style::posix); - Pattern = Path.str(); + Pattern = Path; } if (clang::format::matchFilePath(Pattern, Pathname) == !IsNegated) diff --git a/clang/tools/clang-format/clang-format.el b/clang/tools/clang-format/clang-format.el index 30ac7501afcb617febc2b5fc522f69ead9d721aa..f43bf063c6297038165fcb154ecd82e0df9bb139 100644 --- a/clang/tools/clang-format/clang-format.el +++ b/clang/tools/clang-format/clang-format.el @@ -1,5 +1,6 @@ ;;; clang-format.el --- Format code using clang-format -*- lexical-binding: t; -*- +;; Version: 0.1.0 ;; Keywords: tools, c ;; Package-Requires: ((cl-lib "0.3")) ;; SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception diff --git a/clang/tools/clang-rename/clang-rename.el b/clang/tools/clang-rename/clang-rename.el index b6c3ed4c686b76961f0554d65f46a7b86b3dc33d..3f47c11e2c752e2037b784f5a577d1412a8adb54 100644 --- a/clang/tools/clang-rename/clang-rename.el +++ b/clang/tools/clang-rename/clang-rename.el @@ -1,5 +1,6 @@ ;;; clang-rename.el --- Renames every occurrence of a symbol found at . -*- lexical-binding: t; -*- +;; Version: 0.1.0 ;; Keywords: tools, c ;;; Commentary: diff --git a/clang/tools/clang-scan-deps/ClangScanDeps.cpp b/clang/tools/clang-scan-deps/ClangScanDeps.cpp index 75aa4ae97c618c4efc13104eec2ff267a0b18405..fb42dc1085afb395c652da14e29e8ba6dcb0b2de 100644 --- a/clang/tools/clang-scan-deps/ClangScanDeps.cpp +++ b/clang/tools/clang-scan-deps/ClangScanDeps.cpp @@ -20,7 +20,6 @@ #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileUtilities.h" #include "llvm/Support/Format.h" -#include "llvm/Support/InitLLVM.h" #include "llvm/Support/JSON.h" #include "llvm/Support/LLVMDriver.h" #include "llvm/Support/Program.h" @@ -699,7 +698,6 @@ static std::string getModuleCachePath(ArrayRef Args) { // form specified command line after the positional parameter "--". static std::unique_ptr getCompilationDataBase(int argc, char **argv, std::string &ErrorMessage) { - llvm::InitLLVM X(argc, argv); ParseArgs(argc, argv); if (!CompilationDB.empty()) diff --git a/clang/tools/clang-shlib/CMakeLists.txt b/clang/tools/clang-shlib/CMakeLists.txt index aa7fcd1efed45baa9f6cca132ef8638860b36d95..298d3a9d18fec8c7fbedfa926c91a26f9963ca90 100644 --- a/clang/tools/clang-shlib/CMakeLists.txt +++ b/clang/tools/clang-shlib/CMakeLists.txt @@ -50,7 +50,7 @@ add_clang_library(clang-cpp ${_DEPS}) # Optimize function calls for default visibility definitions to avoid PLT and # reduce dynamic relocations. -if (NOT APPLE AND NOT MINGW) +if (NOT APPLE AND NOT MINGW AND NOT LLVM_LINKER_IS_SOLARISLD_ILLUMOS) target_link_options(clang-cpp PRIVATE LINKER:-Bsymbolic-functions) endif() if (MINGW OR CYGWIN) diff --git a/clang/tools/driver/driver.cpp b/clang/tools/driver/driver.cpp index 4adc7f7ad0dac397c26fe126030ea2a3728569c5..a46d5169719bc9d77781db8226dd4d5facbab2b8 100644 --- a/clang/tools/driver/driver.cpp +++ b/clang/tools/driver/driver.cpp @@ -36,7 +36,6 @@ #include "llvm/Support/CrashRecoveryContext.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FileSystem.h" -#include "llvm/Support/InitLLVM.h" #include "llvm/Support/LLVMDriver.h" #include "llvm/Support/Path.h" #include "llvm/Support/PrettyStackTrace.h" @@ -377,7 +376,6 @@ static int ExecuteCC1Tool(SmallVectorImpl &ArgV, int clang_main(int Argc, char **Argv, const llvm::ToolContext &ToolContext) { noteBottomOfStack(); - llvm::InitLLVM X(Argc, Argv); llvm::setBugReportMsg("PLEASE submit a bug report to " BUG_REPORT_URL " and include the crash backtrace, preprocessed " "source, and associated run script.\n"); diff --git a/clang/tools/libclang/CMakeLists.txt b/clang/tools/libclang/CMakeLists.txt index 4f23065a247274614a867b742bba33ac163549ce..1cfc46eb1a52f62cde7db4314654d72ef5b201e5 100644 --- a/clang/tools/libclang/CMakeLists.txt +++ b/clang/tools/libclang/CMakeLists.txt @@ -185,11 +185,22 @@ if(ENABLE_SHARED) endif() endif() if (USE_VERSION_SCRIPT) - target_link_options(libclang PRIVATE "-Wl,--version-script,${CMAKE_CURRENT_SOURCE_DIR}/libclang.map") - # The Solaris 11.4 linker supports a subset of GNU ld version scripts, - # but requires a special option to enable it. if (${CMAKE_SYSTEM_NAME} MATCHES "SunOS") - target_link_options(libclang PRIVATE "-Wl,-z,gnu-version-script-compat") + include(CheckLinkerFlag) + # The Solaris 11.4 linker supports a subset of GNU ld version scripts, + # but requires a special option to enable it. + llvm_check_linker_flag(CXX "-Wl,-z,gnu-version-script-compat" + LINKER_SUPPORTS_Z_GNU_VERSION_SCRIPT_COMPAT) + # Older Solaris (and illumos) linker does not support GNU ld version scripts + # and does not support GNU version script compat. + if (LINKER_SUPPORTS_Z_GNU_VERSION_SCRIPT_COMPAT) + target_link_options(libclang PRIVATE "-Wl,--version-script,${CMAKE_CURRENT_SOURCE_DIR}/libclang.map") + target_link_options(libclang PRIVATE "-Wl,-z,gnu-version-script-compat") + else() + target_link_options(libclang PRIVATE "-Wl,-M,${CMAKE_CURRENT_SOURCE_DIR}/libclang.map") + endif() + else() + target_link_options(libclang PRIVATE "-Wl,--version-script,${CMAKE_CURRENT_SOURCE_DIR}/libclang.map") endif() # Ensure that libclang.so gets rebuilt when the linker script changes. set_property(SOURCE ARCMigrate.cpp APPEND PROPERTY diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp index e4bd0d646cc9dbf6f6582eec045144c6c5e7cb13..37cf14bdff6b33935d6745b7b4baa97b21cfebcb 100644 --- a/clang/unittests/AST/ASTImporterTest.cpp +++ b/clang/unittests/AST/ASTImporterTest.cpp @@ -4540,6 +4540,162 @@ TEST_P(ImportFriendClasses, ImportOfClassDefinitionAndFwdFriendShouldBeLinked) { EXPECT_EQ(ImportedFwd, ImportedDef->getPreviousDecl()); } +TEST_P(ImportFriendClasses, + ImportFriendTemplatesInDependentContext_DefToFriend) { + Decl *ToTU = getToTuDecl( + R"( + template + struct X { + template + friend struct Y; + }; + )", + Lang_CXX03); + auto *ToYFriend = FirstDeclMatcher().match( + ToTU, classTemplateDecl(hasName("Y"))); + Decl *FromTU = getTuDecl( + R"( + template + struct Y {}; + )", + Lang_CXX03, "input0.cc"); + auto *FromYDef = FirstDeclMatcher().match( + FromTU, classTemplateDecl(hasName("Y"))); + auto *ImportedYDef = Import(FromYDef, Lang_CXX03); + EXPECT_TRUE(ImportedYDef); + EXPECT_FALSE(ImportedYDef->getPreviousDecl()); + EXPECT_NE(ImportedYDef, ToYFriend); +} + +TEST_P(ImportFriendClasses, + ImportFriendTemplatesInDependentContext_DefToFriend_NE) { + getToTuDecl( + R"( + template + struct X { + template + friend struct Y; + }; + )", + Lang_CXX03); + Decl *FromTU = getTuDecl( + R"( + template + struct Y {}; + )", + Lang_CXX03, "input0.cc"); + auto *FromYDef = FirstDeclMatcher().match( + FromTU, classTemplateDecl(hasName("Y"))); + auto *ImportedYDef = Import(FromYDef, Lang_CXX03); + EXPECT_FALSE(ImportedYDef); +} + +TEST_P(ImportFriendClasses, + ImportFriendTemplatesInDependentContext_FriendToFriend) { + Decl *ToTU = getToTuDecl( + R"( + template + struct X { + template + friend struct Y; + }; + )", + Lang_CXX03); + auto *ToYFriend = FirstDeclMatcher().match( + ToTU, classTemplateDecl(hasName("Y"))); + Decl *FromTU = getTuDecl( + R"( + template + struct X { + template + friend struct Y; + }; + )", + Lang_CXX03, "input0.cc"); + auto *FromYFriend = FirstDeclMatcher().match( + FromTU, classTemplateDecl(hasName("Y"))); + auto *ImportedYFriend = Import(FromYFriend, Lang_CXX03); + EXPECT_TRUE(ImportedYFriend); + EXPECT_FALSE(ImportedYFriend->getPreviousDecl()); + EXPECT_NE(ImportedYFriend, ToYFriend); +} + +TEST_P(ImportFriendClasses, + ImportFriendTemplatesInDependentContext_FriendToFriend_NE) { + getToTuDecl( + R"( + template + struct X { + template + friend struct Y; + }; + )", + Lang_CXX03); + Decl *FromTU = getTuDecl( + R"( + template + struct X { + template + friend struct Y; + }; + )", + Lang_CXX03, "input0.cc"); + auto *FromYFriend = FirstDeclMatcher().match( + FromTU, classTemplateDecl(hasName("Y"))); + auto *ImportedYFriend = Import(FromYFriend, Lang_CXX03); + EXPECT_FALSE(ImportedYFriend); +} + +TEST_P(ImportFriendClasses, + ImportFriendTemplatesInDependentContext_FriendToDef) { + Decl *ToTU = getToTuDecl( + R"( + template + struct Y {}; + )", + Lang_CXX03); + auto *ToYDef = FirstDeclMatcher().match( + ToTU, classTemplateDecl(hasName("Y"))); + Decl *FromTU = getTuDecl( + R"( + template + struct X { + template + friend struct Y; + }; + )", + Lang_CXX03, "input0.cc"); + auto *FromYFriend = FirstDeclMatcher().match( + FromTU, classTemplateDecl(hasName("Y"))); + auto *ImportedYFriend = Import(FromYFriend, Lang_CXX03); + EXPECT_TRUE(ImportedYFriend); + EXPECT_FALSE(ImportedYFriend->getPreviousDecl()); + EXPECT_NE(ImportedYFriend, ToYDef); +} + +TEST_P(ImportFriendClasses, + ImportFriendTemplatesInDependentContext_FriendToDef_NE) { + getToTuDecl( + R"( + template + struct Y {}; + )", + Lang_CXX03); + Decl *FromTU = getTuDecl( + R"( + template + struct X { + template + friend struct Y; + }; + )", + Lang_CXX03, "input0.cc"); + auto *FromYFriend = FirstDeclMatcher().match( + FromTU, classTemplateDecl(hasName("Y"))); + auto *ImportedYFriend = Import(FromYFriend, Lang_CXX03); + EXPECT_FALSE(ImportedYFriend); +} + TEST_P(ImportFriendClasses, ImportOfRepeatedFriendType) { const char *Code = R"( diff --git a/clang/unittests/Format/.clang-format b/clang/unittests/Format/.clang-format index d7331b3c8cf02ef7944e83a4280476627e33b31d..f95602cab0f7fcdf5d34c485d52b65993dbb83d9 100644 --- a/clang/unittests/Format/.clang-format +++ b/clang/unittests/Format/.clang-format @@ -1 +1,6 @@ -BasedOnStyle: clang-format +BasedOnStyle: LLVM +InsertBraces: true +InsertNewlineAtEOF: true +LineEnding: LF +RemoveBracesLLVM: true +RemoveParentheses: ReturnStatement diff --git a/clang/unittests/Format/ConfigParseTest.cpp b/clang/unittests/Format/ConfigParseTest.cpp index 0c9f68f303d865341d6792798d1cbd9a1fc8c8bd..18ecba270e3455a1fcafda0007098ad43951aac6 100644 --- a/clang/unittests/Format/ConfigParseTest.cpp +++ b/clang/unittests/Format/ConfigParseTest.cpp @@ -289,37 +289,43 @@ TEST(ConfigParseTest, ParsesConfiguration) { #define CHECK_ALIGN_CONSECUTIVE(FIELD) \ do { \ Style.FIELD.Enabled = true; \ - CHECK_PARSE(#FIELD ": None", FIELD, \ - FormatStyle::AlignConsecutiveStyle( \ - {/*Enabled=*/false, /*AcrossEmptyLines=*/false, \ - /*AcrossComments=*/false, /*AlignCompound=*/false, \ - /*PadOperators=*/true})); \ - CHECK_PARSE(#FIELD ": Consecutive", FIELD, \ - FormatStyle::AlignConsecutiveStyle( \ - {/*Enabled=*/true, /*AcrossEmptyLines=*/false, \ - /*AcrossComments=*/false, /*AlignCompound=*/false, \ - /*PadOperators=*/true})); \ - CHECK_PARSE(#FIELD ": AcrossEmptyLines", FIELD, \ - FormatStyle::AlignConsecutiveStyle( \ - {/*Enabled=*/true, /*AcrossEmptyLines=*/true, \ - /*AcrossComments=*/false, /*AlignCompound=*/false, \ - /*PadOperators=*/true})); \ - CHECK_PARSE(#FIELD ": AcrossEmptyLinesAndComments", FIELD, \ - FormatStyle::AlignConsecutiveStyle( \ - {/*Enabled=*/true, /*AcrossEmptyLines=*/true, \ - /*AcrossComments=*/true, /*AlignCompound=*/false, \ - /*PadOperators=*/true})); \ + CHECK_PARSE( \ + #FIELD ": None", FIELD, \ + FormatStyle::AlignConsecutiveStyle( \ + {/*Enabled=*/false, /*AcrossEmptyLines=*/false, \ + /*AcrossComments=*/false, /*AlignCompound=*/false, \ + /*AlignFunctionPointers=*/false, /*PadOperators=*/true})); \ + CHECK_PARSE( \ + #FIELD ": Consecutive", FIELD, \ + FormatStyle::AlignConsecutiveStyle( \ + {/*Enabled=*/true, /*AcrossEmptyLines=*/false, \ + /*AcrossComments=*/false, /*AlignCompound=*/false, \ + /*AlignFunctionPointers=*/false, /*PadOperators=*/true})); \ + CHECK_PARSE( \ + #FIELD ": AcrossEmptyLines", FIELD, \ + FormatStyle::AlignConsecutiveStyle( \ + {/*Enabled=*/true, /*AcrossEmptyLines=*/true, \ + /*AcrossComments=*/false, /*AlignCompound=*/false, \ + /*AlignFunctionPointers=*/false, /*PadOperators=*/true})); \ + CHECK_PARSE( \ + #FIELD ": AcrossEmptyLinesAndComments", FIELD, \ + FormatStyle::AlignConsecutiveStyle( \ + {/*Enabled=*/true, /*AcrossEmptyLines=*/true, \ + /*AcrossComments=*/true, /*AlignCompound=*/false, \ + /*AlignFunctionPointers=*/false, /*PadOperators=*/true})); \ /* For backwards compability, false / true should still parse */ \ - CHECK_PARSE(#FIELD ": false", FIELD, \ - FormatStyle::AlignConsecutiveStyle( \ - {/*Enabled=*/false, /*AcrossEmptyLines=*/false, \ - /*AcrossComments=*/false, /*AlignCompound=*/false, \ - /*PadOperators=*/true})); \ - CHECK_PARSE(#FIELD ": true", FIELD, \ - FormatStyle::AlignConsecutiveStyle( \ - {/*Enabled=*/true, /*AcrossEmptyLines=*/false, \ - /*AcrossComments=*/false, /*AlignCompound=*/false, \ - /*PadOperators=*/true})); \ + CHECK_PARSE( \ + #FIELD ": false", FIELD, \ + FormatStyle::AlignConsecutiveStyle( \ + {/*Enabled=*/false, /*AcrossEmptyLines=*/false, \ + /*AcrossComments=*/false, /*AlignCompound=*/false, \ + /*AlignFunctionPointers=*/false, /*PadOperators=*/true})); \ + CHECK_PARSE( \ + #FIELD ": true", FIELD, \ + FormatStyle::AlignConsecutiveStyle( \ + {/*Enabled=*/true, /*AcrossEmptyLines=*/false, \ + /*AcrossComments=*/false, /*AlignCompound=*/false, \ + /*AlignFunctionPointers=*/false, /*PadOperators=*/true})); \ \ CHECK_PARSE_NESTED_BOOL(FIELD, Enabled); \ CHECK_PARSE_NESTED_BOOL(FIELD, AcrossEmptyLines); \ diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index 881993ede17c3dc153070c3fa282beeb26289352..340ae39cb22b0365025434eabc8346199c09109c 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -2046,13 +2046,26 @@ TEST_F(FormatTest, SeparatePointerReferenceAlignment) { Style); Style.AlignConsecutiveDeclarations.Enabled = true; + Style.AlignConsecutiveDeclarations.AlignFunctionPointers = true; verifyFormat("Const unsigned int *c;\n" "const unsigned int *d;\n" "Const unsigned int &e;\n" "const unsigned int &f;\n" + "int *f1(int *a, int &b, int &&c);\n" + "double *(*f2)(int *a, double &&b);\n" "const unsigned &&g;\n" "Const unsigned h;", Style); + Style.AlignConsecutiveDeclarations.AlignFunctionPointers = false; + verifyFormat("Const unsigned int *c;\n" + "const unsigned int *d;\n" + "Const unsigned int &e;\n" + "const unsigned int &f;\n" + "int *f1(int *a, int &b, int &&c);\n" + "double *(*f2)(int *a, double &&b);\n" + "const unsigned &&g;\n" + "Const unsigned h;", + Style); Style.PointerAlignment = FormatStyle::PAS_Left; Style.ReferenceAlignment = FormatStyle::RAS_Pointer; @@ -2091,13 +2104,26 @@ TEST_F(FormatTest, SeparatePointerReferenceAlignment) { Style); Style.AlignConsecutiveDeclarations.Enabled = true; + Style.AlignConsecutiveDeclarations.AlignFunctionPointers = true; verifyFormat("Const unsigned int* c;\n" "const unsigned int* d;\n" "Const unsigned int& e;\n" "const unsigned int& f;\n" + "int* f1(int* a, int& b, int&& c);\n" + "double* (*f2)(int* a, double&& b);\n" "const unsigned&& g;\n" "Const unsigned h;", Style); + Style.AlignConsecutiveDeclarations.AlignFunctionPointers = false; + verifyFormat("Const unsigned int* c;\n" + "const unsigned int* d;\n" + "Const unsigned int& e;\n" + "const unsigned int& f;\n" + "int* f1(int* a, int& b, int&& c);\n" + "double* (*f2)(int* a, double&& b);\n" + "const unsigned&& g;\n" + "Const unsigned h;", + Style); Style.PointerAlignment = FormatStyle::PAS_Right; Style.ReferenceAlignment = FormatStyle::RAS_Left; @@ -2116,13 +2142,26 @@ TEST_F(FormatTest, SeparatePointerReferenceAlignment) { verifyFormat("for (int a = 0, b++; const Foo *c : {1, 2, 3})", Style); Style.AlignConsecutiveDeclarations.Enabled = true; + Style.AlignConsecutiveDeclarations.AlignFunctionPointers = true; verifyFormat("Const unsigned int *c;\n" "const unsigned int *d;\n" "Const unsigned int& e;\n" "const unsigned int& f;\n" - "const unsigned g;\n" + "int *f1(int *a, int& b, int&& c);\n" + "double *(*f2)(int *a, double&& b);\n" + "const unsigned&& g;\n" "Const unsigned h;", Style); + Style.AlignConsecutiveDeclarations.AlignFunctionPointers = false; + verifyFormat("Const unsigned int *c;\n" + "const unsigned int *d;\n" + "Const unsigned int& e;\n" + "const unsigned int& f;\n" + "int *f1(int *a, int& b, int&& c);\n" + "double *(*f2)(int *a, double&& b);\n" + "const unsigned&& g;\n" + "Const unsigned h;", + Style); Style.PointerAlignment = FormatStyle::PAS_Left; Style.ReferenceAlignment = FormatStyle::RAS_Middle; @@ -2156,13 +2195,26 @@ TEST_F(FormatTest, SeparatePointerReferenceAlignment) { Style); Style.AlignConsecutiveDeclarations.Enabled = true; + Style.AlignConsecutiveDeclarations.AlignFunctionPointers = true; verifyFormat("Const unsigned int* c;\n" "const unsigned int* d;\n" "Const unsigned int & e;\n" "const unsigned int & f;\n" + "int* f1(int* a, int & b, int && c);\n" + "double* (*f2)(int* a, double && b);\n" "const unsigned && g;\n" "Const unsigned h;", Style); + Style.AlignConsecutiveDeclarations.AlignFunctionPointers = false; + verifyFormat("Const unsigned int* c;\n" + "const unsigned int* d;\n" + "Const unsigned int & e;\n" + "const unsigned int & f;\n" + "int* f1(int* a, int & b, int && c);\n" + "double* (*f2)(int* a, double && b);\n" + "const unsigned && g;\n" + "Const unsigned h;", + Style); Style.PointerAlignment = FormatStyle::PAS_Middle; Style.ReferenceAlignment = FormatStyle::RAS_Right; @@ -2181,13 +2233,26 @@ TEST_F(FormatTest, SeparatePointerReferenceAlignment) { verifyFormat("for (int a = 0, b++; const Foo * c : {1, 2, 3})", Style); Style.AlignConsecutiveDeclarations.Enabled = true; + Style.AlignConsecutiveDeclarations.AlignFunctionPointers = true; verifyFormat("Const unsigned int * c;\n" "const unsigned int * d;\n" "Const unsigned int &e;\n" "const unsigned int &f;\n" + "int * f1(int * a, int &b, int &&c);\n" + "double * (*f2)(int * a, double &&b);\n" "const unsigned &&g;\n" "Const unsigned h;", Style); + Style.AlignConsecutiveDeclarations.AlignFunctionPointers = false; + verifyFormat("Const unsigned int * c;\n" + "const unsigned int * d;\n" + "Const unsigned int &e;\n" + "const unsigned int &f;\n" + "int * f1(int * a, int &b, int &&c);\n" + "double * (*f2)(int * a, double &&b);\n" + "const unsigned &&g;\n" + "Const unsigned h;", + Style); // FIXME: we don't handle this yet, so output may be arbitrary until it's // specifically handled @@ -13875,6 +13940,21 @@ TEST_F(FormatTest, FormatsBracedListsInColumnLayout) { getLLVMStyleWithColumns(35)); verifyFormat("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaa, {},\n" " aaaaaaaaaaaaaaaaaaaaaaa);"); + + // No possible column formats, don't want the optimal paths penalized. + verifyFormat( + "waarudo::unit desk = {\n" + " .s = \"desk\", .p = p, .b = [] { return w::r{3, 10} * w::m; }};"); + verifyFormat("SomeType something1([](const Input &i) -> Output { return " + "Output{1, 2}; },\n" + " [](const Input &i) -> Output { return " + "Output{1, 2}; });"); + FormatStyle NoBinPacking = getLLVMStyle(); + NoBinPacking.BinPackParameters = false; + verifyFormat("waarudo::unit desk = {\n" + " .s = \"desk\", .p = p, .b = [] { return w::r{3, 10, 1, 1, " + "1, 1} * w::m; }};", + NoBinPacking); } TEST_F(FormatTest, PullTrivialFunctionDefinitionsIntoSingleLine) { @@ -18918,6 +18998,15 @@ TEST_F(FormatTest, AlignConsecutiveDeclarations) { " \"bb\"};\n" "int bbbbbbb = 0;", Alignment); + // http://llvm.org/PR68079 + verifyFormat("using Fn = int (A::*)();\n" + "using RFn = int (A::*)() &;\n" + "using RRFn = int (A::*)() &&;", + Alignment); + verifyFormat("using Fn = int (A::*)();\n" + "using RFn = int *(A::*)() &;\n" + "using RRFn = double (A::*)() &&;", + Alignment); // PAS_Right verifyFormat("void SomeFunction(int parameter = 0) {\n" @@ -19570,7 +19659,7 @@ TEST_F(FormatTest, AlignWithLineBreaks) { FormatStyle::AlignConsecutiveStyle( {/*Enabled=*/false, /*AcrossEmptyLines=*/false, /*AcrossComments=*/false, /*AlignCompound=*/false, - /*PadOperators=*/true})); + /*AlignFunctionPointers=*/false, /*PadOperators=*/true})); EXPECT_EQ(Style.AlignConsecutiveDeclarations, FormatStyle::AlignConsecutiveStyle({})); verifyFormat("void foo() {\n" @@ -20842,6 +20931,17 @@ TEST_F(FormatTest, CatchAlignArrayOfStructuresRightAlignment) { "};", Style); + verifyNoCrash("Foo f[] = {\n" + " [0] = { 1, },\n" + " [i] { 1, },\n" + "};", + Style); + verifyNoCrash("Foo foo[] = {\n" + " [0] = {1, 1},\n" + " [1] { 1, 1, },\n" + " [2] { 1, 1, },\n" + "};"); + verifyFormat("return GradForUnaryCwise(g, {\n" " {{\"sign\"}, \"Sign\", " " {\"x\", \"dy\"}},\n" @@ -21084,6 +21184,17 @@ TEST_F(FormatTest, CatchAlignArrayOfStructuresLeftAlignment) { "};", Style); + verifyNoCrash("Foo f[] = {\n" + " [0] = { 1, },\n" + " [i] { 1, },\n" + "};", + Style); + verifyNoCrash("Foo foo[] = {\n" + " [0] = {1, 1},\n" + " [1] { 1, 1, },\n" + " [2] { 1, 1, },\n" + "};"); + verifyFormat("return GradForUnaryCwise(g, {\n" " {{\"sign\"}, \"Sign\", {\"x\", " "\"dy\"} },\n" @@ -26708,6 +26819,8 @@ TEST_F(FormatTest, PPBranchesInBracedInit) { TEST_F(FormatTest, StreamOutputOperator) { verifyFormat("std::cout << \"foo\" << \"bar\" << baz;"); + verifyFormat("std::cout << \"foo\\n\"\n" + " << \"bar\";"); } TEST_F(FormatTest, BreakAdjacentStringLiterals) { diff --git a/clang/unittests/Format/FormatTestJava.cpp b/clang/unittests/Format/FormatTestJava.cpp index 202d603d0577909f967bd7c821a16b4a8477d237..6da5f4fa254331dc3a2d37503095d5f4f0ad54cd 100644 --- a/clang/unittests/Format/FormatTestJava.cpp +++ b/clang/unittests/Format/FormatTestJava.cpp @@ -603,6 +603,21 @@ TEST_F(FormatTestJava, ShortFunctions) { Style); } +TEST_F(FormatTestJava, ConfigurableSpacesInSquareBrackets) { + FormatStyle Spaces = getLLVMStyle(FormatStyle::LK_Java); + + verifyFormat("Object[] arguments", Spaces); + verifyFormat("final Class[] types = new Class[numElements];", Spaces); + verifyFormat("types[i] = arguments[i].getClass();", Spaces); + + Spaces.SpacesInSquareBrackets = true; + + verifyFormat("Object[ ] arguments", Spaces); + verifyFormat("final Class[ ] types = new Class[ numElements ];", + Spaces); + verifyFormat("types[ i ] = arguments[ i ].getClass();", Spaces); +} + } // namespace } // namespace test } // namespace format diff --git a/clang/unittests/Format/FormatTestMacroExpansion.cpp b/clang/unittests/Format/FormatTestMacroExpansion.cpp index 68250234f4201ef7941c5f4145826031a09bf2e3..653ec2a94c64da58c6dd72ed673328cce59c7a1f 100644 --- a/clang/unittests/Format/FormatTestMacroExpansion.cpp +++ b/clang/unittests/Format/FormatTestMacroExpansion.cpp @@ -255,6 +255,38 @@ TEST_F(FormatTestMacroExpansion, Style); } +TEST_F(FormatTestMacroExpansion, CommaAsOperator) { + FormatStyle Style = getGoogleStyleWithColumns(42); + Style.Macros.push_back("MACRO(a, b, c)=a=(b); if(x) c"); + verifyFormat("MACRO(auto a,\n" + " looooongfunction(first, second,\n" + " third),\n" + " fourth);", + Style); +} + +TEST_F(FormatTestMacroExpansion, ForcedBreakDiffers) { + FormatStyle Style = getGoogleStyleWithColumns(40); + Style.Macros.push_back("MACRO(a, b)=a=(b)"); + verifyFormat("//\n" + "MACRO(const type variable,\n" + " functtioncall(\n" + " first, longsecondarg, third));", + Style); +} + +TEST_F(FormatTestMacroExpansion, + PreferNotBreakingBetweenReturnTypeAndFunction) { + FormatStyle Style = getGoogleStyleWithColumns(22); + Style.Macros.push_back("MOCK_METHOD(r, n, a)=r n a"); + // In the expanded code, we parse a full function signature, and afterwards + // know that we prefer not to break before the function name. + verifyFormat("MOCK_METHOD(\n" + " type, variable,\n" + " (type));", + Style); +} + } // namespace } // namespace test } // namespace format diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp index 2cafc0438ffb46ae93f4fbd1e7e2137de9f5fe49..92f57a77cdaf01dcebf5cf10faa8ae6ed678a4d6 100644 --- a/clang/unittests/Format/TokenAnnotatorTest.cpp +++ b/clang/unittests/Format/TokenAnnotatorTest.cpp @@ -1066,6 +1066,11 @@ TEST_F(TokenAnnotatorTest, UnderstandsRequiresClausesAndConcepts) { EXPECT_EQ(Tokens.size(), 17u) << Tokens; EXPECT_TOKEN(Tokens[4], tok::amp, TT_PointerOrReference); EXPECT_TOKEN(Tokens[5], tok::kw_requires, TT_RequiresClause); + + Tokens = annotate("template \n" + "concept C = (!Foo) && Bar;"); + ASSERT_EQ(Tokens.size(), 19u) << Tokens; + EXPECT_TOKEN(Tokens[15], tok::ampamp, TT_BinaryOperator); } TEST_F(TokenAnnotatorTest, UnderstandsRequiresExpressions) { @@ -2172,6 +2177,24 @@ TEST_F(TokenAnnotatorTest, UnderstandsVerilogOperators) { EXPECT_TOKEN(Tokens[4], tok::string_literal, TT_Unknown); } +TEST_F(TokenAnnotatorTest, UnderstandTableGenTokens) { + auto Style = getLLVMStyle(FormatStyle::LK_TableGen); + ASSERT_TRUE(Style.isTableGen()); + + TestLexer Lexer(Allocator, Buffers, Style); + AdditionalKeywords Keywords(Lexer.IdentTable); + auto Annotate = [&Lexer](llvm::StringRef Code) { + return Lexer.annotate(Code); + }; + + // Additional keywords representation test. + auto Tokens = Annotate("def foo : Bar<1>;"); + ASSERT_TRUE(Keywords.isTableGenKeyword(*Tokens[0])); + ASSERT_TRUE(Keywords.isTableGenDefinition(*Tokens[0])); + ASSERT_TRUE(Tokens[0]->is(Keywords.kw_def)); + ASSERT_TRUE(Tokens[1]->is(TT_StartOfName)); +} + TEST_F(TokenAnnotatorTest, UnderstandConstructors) { auto Tokens = annotate("Class::Class() : BaseClass(), Member() {}"); @@ -2324,6 +2347,11 @@ TEST_F(TokenAnnotatorTest, UnderstandDesignatedInitializers) { EXPECT_BRACE_KIND(Tokens[1], BK_BracedInit); EXPECT_TOKEN(Tokens[6], tok::period, TT_DesignatedInitializerPeriod); EXPECT_TOKEN(Tokens[13], tok::period, TT_DesignatedInitializerPeriod); + + Tokens = annotate("Foo foo[] = {[0]{}};"); + ASSERT_EQ(Tokens.size(), 14u) << Tokens; + EXPECT_TOKEN(Tokens[6], tok::l_square, TT_DesignatedInitializerLSquare); + EXPECT_BRACE_KIND(Tokens[9], BK_BracedInit); } TEST_F(TokenAnnotatorTest, UnderstandsJavaScript) { @@ -2499,6 +2527,15 @@ TEST_F(TokenAnnotatorTest, BraceKind) { EXPECT_BRACE_KIND(Tokens[6], BK_Block); } +TEST_F(TokenAnnotatorTest, StreamOperator) { + auto Tokens = annotate("\"foo\\n\" << aux << \"foo\\n\" << \"foo\";"); + ASSERT_EQ(Tokens.size(), 9u) << Tokens; + EXPECT_FALSE(Tokens[1]->MustBreakBefore); + EXPECT_FALSE(Tokens[3]->MustBreakBefore); + // Only break between string literals if the former ends with \n. + EXPECT_TRUE(Tokens[5]->MustBreakBefore); +} + } // namespace } // namespace format } // namespace clang diff --git a/clang/www/c_dr_status.html b/clang/www/c_dr_status.html index 4fe088e2977505fd35d31ba4627c90514e4503e1..fa2ceb1be58bdc469006940ee74c949e37806ae0 100644 --- a/clang/www/c_dr_status.html +++ b/clang/www/c_dr_status.html @@ -12,7 +12,7 @@ .unreleased { background-color: #FFFF99 } .full { background-color: #CCFF99 } .na { background-color: #DDDDDD } - .unknown { background-color: #FF55FF } + .unknown { background-color: #EBCAFE } .open * { color: #AAAAAA } //.open { filter: opacity(0.2) } tr:target { background-color: #FFFFBB } @@ -35,7 +35,7 @@

The implementation status for defect reports against the C Standard are currently under investigation. Any defect report whose status in Clang is -currently unknown will be marked in magenta.

+currently unknown will be marked in purple.

The LLVM bug tracker uses the "c", "c99", "c11", "c17", and "c23" labels to track known bugs with Clang's language diff --git a/clang/www/c_status.html b/clang/www/c_status.html index 47acb1f87b8e3d76448e4918ad87ed5859d22274..b9e0650ddca2429b7b6ef9dbac409f09dd79569a 100644 --- a/clang/www/c_status.html +++ b/clang/www/c_status.html @@ -9,7 +9,7 @@ .none { background-color: #FFCCCC } .partial { background-color: #FFE0B0 } .unreleased { background-color: #FFFF99 } - .unknown { background-color: #FF55FF } + .unknown { background-color: #EBCAFE } .full { background-color: #CCFF99 } .na { background-color: #DDDDDD } :target { background-color: #FFFFBB; outline: #DDDD55 solid thin; } diff --git a/clang/www/cxx_dr_status.html b/clang/www/cxx_dr_status.html index d09cf616899ad45c1dc6d56ecdebabe77611d0c0..4a3ed19161f9a5f029a3653a49264a503d346dfc 100755 --- a/clang/www/cxx_dr_status.html +++ b/clang/www/cxx_dr_status.html @@ -8,6 +8,7 @@