diff --git a/.ci/generate-buildkite-pipeline-premerge b/.ci/generate-buildkite-pipeline-premerge index f45a4d82150d50..e389df431505bd 100755 --- a/.ci/generate-buildkite-pipeline-premerge +++ b/.ci/generate-buildkite-pipeline-premerge @@ -22,7 +22,7 @@ set -o pipefail # Environment variables script works with: # List of files affected by this commit -: ${MODIFIED_FILES:=$(git diff --name-only main...HEAD)} +: ${MODIFIED_FILES:=$(git diff --name-only HEAD~1)} # Filter rules for generic windows tests : ${WINDOWS_AGENTS:='{"queue": "windows"}'} # Filter rules for generic linux tests diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index ded7d9df068e0d..8fb4c7523a6cb3 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,4 +1,32 @@ +# This file lists reviewers that are auto-assigned when a pull request modifies +# certain files or directories. If you add yourself to this file, you commit to +# reviewing a large fraction of pull requests in the relevant area. +# +# The GitHub "code owners" mechanism is used exclusively to auto-assign +# reviewers and does not carry significance beyond that. It is not necessary +# to receive an approval from a "code owner" in particular -- any LLVM project +# member can approve pull requests. +# +# Note that GitHub's concept of "code owner" is independent from LLVM's own +# "code owner" concept, they merely happen to share terminology. See +# https://llvm.org/docs/DeveloperPolicy.html#code-owners, as well as the +# CODE_OWNERS.txt files in the respective subproject directories. + /libcxx/ @llvm/reviewers-libcxx /libcxxabi/ @llvm/reviewers-libcxxabi /libunwind/ @llvm/reviewers-libunwind /runtimes/ @llvm/reviewers-libcxx + +/llvm/lib/Analysis/BasicAliasAnalysis.cpp @nikic +/llvm/lib/Analysis/InstructionSimplify.cpp @nikic +/llvm/lib/Analysis/LazyValueInfo.cpp @nikic +/llvm/lib/Analysis/ScalarEvolution.cpp @nikic +/llvm/lib/Analysis/ValueTracking.cpp @nikic +/llvm/lib/IR/ConstantRange.cpp @nikic +/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp @nikic +/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp @nikic +/llvm/lib/Transforms/InstCombine/ @nikic + +/clang/test/CXX/drs/ @Endilll +/clang/www/cxx_dr_status.html @Endilll +/clang/www/make_cxx_dr_status @Endilll diff --git a/.github/workflows/llvm-tests.yml b/.github/workflows/llvm-tests.yml index 428235b72fa5ad..cc9855ce182b2b 100644 --- a/.github/workflows/llvm-tests.yml +++ b/.github/workflows/llvm-tests.yml @@ -170,14 +170,17 @@ jobs: uses: actions/download-artifact@v3 with: name: build-baseline + path: build-baseline - name: Download latest uses: actions/download-artifact@v3 with: name: build-latest + path: build-latest - name: Download symbol list uses: actions/download-artifact@v3 with: name: symbol-list + path: symbol-list - name: Install abi-compliance-checker run: sudo apt-get install abi-compliance-checker diff --git a/.github/workflows/release-binaries.yml b/.github/workflows/release-binaries.yml index 90b801b13ed179..e52e52f5d3f36f 100644 --- a/.github/workflows/release-binaries.yml +++ b/.github/workflows/release-binaries.yml @@ -68,7 +68,7 @@ jobs: matrix: target: - triple: x86_64-linux-gnu-ubuntu-22.04 - runs-on: ubuntu-22.04-8x32 + runs-on: ubuntu-22.04-16x64 debian-build-deps: > chrpath gcc-multilib diff --git a/bolt/include/bolt/Core/BinaryContext.h b/bolt/include/bolt/Core/BinaryContext.h index ef57ff3541dc8c..59460105f23137 100644 --- a/bolt/include/bolt/Core/BinaryContext.h +++ b/bolt/include/bolt/Core/BinaryContext.h @@ -871,6 +871,15 @@ class BinaryContext { return nullptr; } + /// Retrieves a reference to ELF's _GLOBAL_OFFSET_TABLE_ symbol, which points + /// at GOT, or null if it is not present in the input binary symtab. + BinaryData *getGOTSymbol(); + + /// Checks if symbol name refers to ELF's _GLOBAL_OFFSET_TABLE_ symbol + bool isGOTSymbol(StringRef SymName) const { + return SymName == "_GLOBAL_OFFSET_TABLE_"; + } + /// Return true if \p SymbolName was generated internally and was not present /// in the input binary. bool isInternalSymbolName(const StringRef Name) { diff --git a/bolt/include/bolt/Core/MCPlus.h b/bolt/include/bolt/Core/MCPlus.h index b4a72ac274fade..31cc9071de76ac 100644 --- a/bolt/include/bolt/Core/MCPlus.h +++ b/bolt/include/bolt/Core/MCPlus.h @@ -66,6 +66,7 @@ class MCAnnotation { kTailCall, /// Tail call. kConditionalTailCall, /// CTC. kOffset, /// Offset in the function. + kLabel, /// MCSymbol pointing to this instruction. kGeneric /// First generic annotation. }; diff --git a/bolt/include/bolt/Core/MCPlusBuilder.h b/bolt/include/bolt/Core/MCPlusBuilder.h index 5e12a4ac14c9e4..c9e0e5d599b1fa 100644 --- a/bolt/include/bolt/Core/MCPlusBuilder.h +++ b/bolt/include/bolt/Core/MCPlusBuilder.h @@ -160,6 +160,7 @@ class MCPlusBuilder { const MCInstrAnalysis *Analysis; const MCInstrInfo *Info; const MCRegisterInfo *RegInfo; + const MCSubtargetInfo *STI; /// Map annotation name into an annotation index. StringMap AnnotationNameIndexMap; @@ -331,8 +332,8 @@ class MCPlusBuilder { public: MCPlusBuilder(const MCInstrAnalysis *Analysis, const MCInstrInfo *Info, - const MCRegisterInfo *RegInfo) - : Analysis(Analysis), Info(Info), RegInfo(RegInfo) { + const MCRegisterInfo *RegInfo, const MCSubtargetInfo *STI) + : Analysis(Analysis), Info(Info), RegInfo(RegInfo), STI(STI) { // Initialize the default annotation allocator with id 0 AnnotationAllocators.emplace(0, AnnotationAllocator()); MaxAllocatorId++; @@ -1179,6 +1180,13 @@ class MCPlusBuilder { /// Remove offset annotation. bool clearOffset(MCInst &Inst); + /// Return the label of \p Inst, if available. + std::optional getLabel(const MCInst &Inst) const; + + /// Set the label of \p Inst. This label will be emitted right before \p Inst + /// is emitted to MCStreamer. + bool setLabel(MCInst &Inst, MCSymbol *Label); + /// Return MCSymbol that represents a target of this instruction at a given /// operand number \p OpNum. If there's no symbol associated with /// the operand - return nullptr. @@ -2079,15 +2087,18 @@ class MCPlusBuilder { MCPlusBuilder *createX86MCPlusBuilder(const MCInstrAnalysis *, const MCInstrInfo *, - const MCRegisterInfo *); + const MCRegisterInfo *, + const MCSubtargetInfo *); MCPlusBuilder *createAArch64MCPlusBuilder(const MCInstrAnalysis *, const MCInstrInfo *, - const MCRegisterInfo *); + const MCRegisterInfo *, + const MCSubtargetInfo *); MCPlusBuilder *createRISCVMCPlusBuilder(const MCInstrAnalysis *, const MCInstrInfo *, - const MCRegisterInfo *); + const MCRegisterInfo *, + const MCSubtargetInfo *); } // namespace bolt } // namespace llvm diff --git a/bolt/include/bolt/Core/Relocation.h b/bolt/include/bolt/Core/Relocation.h index 5ae288a91986e5..bc16d952e7a291 100644 --- a/bolt/include/bolt/Core/Relocation.h +++ b/bolt/include/bolt/Core/Relocation.h @@ -84,6 +84,7 @@ struct Relocation { /// Special relocation type that allows the linker to modify the instruction. static bool isX86GOTPCRELX(uint64_t Type); + static bool isX86GOTPC64(uint64_t Type); /// Return true if relocation type is NONE static bool isNone(uint64_t Type); @@ -97,6 +98,10 @@ struct Relocation { /// Return true if relocation type is for thread local storage. static bool isTLS(uint64_t Type); + /// Return true of relocation type is for referencing a specific instruction + /// (as opposed to a function, basic block, etc). + static bool isInstructionReference(uint64_t Type); + /// Return code for a NONE relocation static uint64_t getNone(); diff --git a/bolt/include/bolt/Rewrite/RewriteInstance.h b/bolt/include/bolt/Rewrite/RewriteInstance.h index 1dacdc944f9775..329fe356603d0e 100644 --- a/bolt/include/bolt/Rewrite/RewriteInstance.h +++ b/bolt/include/bolt/Rewrite/RewriteInstance.h @@ -584,7 +584,8 @@ class RewriteInstance { MCPlusBuilder *createMCPlusBuilder(const Triple::ArchType Arch, const MCInstrAnalysis *Analysis, const MCInstrInfo *Info, - const MCRegisterInfo *RegInfo); + const MCRegisterInfo *RegInfo, + const MCSubtargetInfo *STI); } // namespace bolt } // namespace llvm diff --git a/bolt/lib/Core/BinaryContext.cpp b/bolt/lib/Core/BinaryContext.cpp index 8132e5c213af44..b5514228d7a254 100644 --- a/bolt/lib/Core/BinaryContext.cpp +++ b/bolt/lib/Core/BinaryContext.cpp @@ -1026,6 +1026,31 @@ BinaryContext::getBinaryDataContainingAddressImpl(uint64_t Address) const { return nullptr; } +BinaryData *BinaryContext::getGOTSymbol() { + // First tries to find a global symbol with that name + BinaryData *GOTSymBD = getBinaryDataByName("_GLOBAL_OFFSET_TABLE_"); + if (GOTSymBD) + return GOTSymBD; + + // This symbol might be hidden from run-time link, so fetch the local + // definition if available. + GOTSymBD = getBinaryDataByName("_GLOBAL_OFFSET_TABLE_/1"); + if (!GOTSymBD) + return nullptr; + + // If the local symbol is not unique, fail + unsigned Index = 2; + SmallString<30> Storage; + while (const BinaryData *BD = + getBinaryDataByName(Twine("_GLOBAL_OFFSET_TABLE_/") + .concat(Twine(Index++)) + .toStringRef(Storage))) + if (BD->getAddress() != GOTSymBD->getAddress()) + return nullptr; + + return GOTSymBD; +} + bool BinaryContext::setBinaryDataSize(uint64_t Address, uint64_t Size) { auto NI = BinaryDataMap.find(Address); assert(NI != BinaryDataMap.end()); @@ -1863,6 +1888,8 @@ void BinaryContext::printInstruction(raw_ostream &OS, const MCInst &Instruction, } if (std::optional Offset = MIB->getOffset(Instruction)) OS << " # Offset: " << *Offset; + if (auto Label = MIB->getLabel(Instruction)) + OS << " # Label: " << **Label; MIB->printAnnotations(Instruction, OS); diff --git a/bolt/lib/Core/BinaryEmitter.cpp b/bolt/lib/Core/BinaryEmitter.cpp index 95ab63521c06a5..b1ee6cc221d716 100644 --- a/bolt/lib/Core/BinaryEmitter.cpp +++ b/bolt/lib/Core/BinaryEmitter.cpp @@ -498,6 +498,9 @@ void BinaryEmitter::emitFunctionBody(BinaryFunction &BF, FunctionFragment &FF, BB->getLocSyms().emplace_back(Offset, LocSym); } + if (auto Label = BC.MIB->getLabel(Instr)) + Streamer.emitLabel(*Label); + Streamer.emitInstruction(Instr, *BC.STI); LastIsPrefix = BC.MIB->isPrefix(Instr); } diff --git a/bolt/lib/Core/BinaryFunction.cpp b/bolt/lib/Core/BinaryFunction.cpp index 6cf1cfb50a9c12..c475e4f9035fe0 100644 --- a/bolt/lib/Core/BinaryFunction.cpp +++ b/bolt/lib/Core/BinaryFunction.cpp @@ -1173,6 +1173,13 @@ bool BinaryFunction::disassemble() { // basic block. Labels[0] = Ctx->createNamedTempSymbol("BB0"); + // Map offsets in the function to a label that should always point to the + // corresponding instruction. This is used for labels that shouldn't point to + // the start of a basic block but always to a specific instruction. This is + // used, for example, on RISC-V where %pcrel_lo relocations point to the + // corresponding %pcrel_hi. + LabelsMapType InstructionLabels; + uint64_t Size = 0; // instruction size for (uint64_t Offset = 0; Offset < getSize(); Offset += Size) { MCInst Instruction; @@ -1329,9 +1336,23 @@ bool BinaryFunction::disassemble() { ItrE = Relocations.lower_bound(Offset + Size); Itr != ItrE; ++Itr) { const Relocation &Relocation = Itr->second; + MCSymbol *Symbol = Relocation.Symbol; + + if (Relocation::isInstructionReference(Relocation.Type)) { + uint64_t RefOffset = Relocation.Value - getAddress(); + LabelsMapType::iterator LI = InstructionLabels.find(RefOffset); + + if (LI == InstructionLabels.end()) { + Symbol = BC.Ctx->createNamedTempSymbol(); + InstructionLabels.emplace(RefOffset, Symbol); + } else { + Symbol = LI->second; + } + } + int64_t Value = Relocation.Value; const bool Result = BC.MIB->replaceImmWithSymbolRef( - Instruction, Relocation.Symbol, Relocation.Addend, Ctx.get(), Value, + Instruction, Symbol, Relocation.Addend, Ctx.get(), Value, Relocation.Type); (void)Result; assert(Result && "cannot replace immediate with relocation"); @@ -1366,6 +1387,13 @@ bool BinaryFunction::disassemble() { addInstruction(Offset, std::move(Instruction)); } + for (auto [Offset, Label] : InstructionLabels) { + InstrMapType::iterator II = Instructions.find(Offset); + assert(II != Instructions.end() && "reference to non-existing instruction"); + + BC.MIB->setLabel(II->second, Label); + } + // Reset symbolizer for the disassembler. BC.SymbolicDisAsm->setSymbolizer(nullptr); @@ -1761,7 +1789,8 @@ bool BinaryFunction::postProcessIndirectBranches( uint64_t LastJT = 0; uint16_t LastJTIndexReg = BC.MIB->getNoRegister(); for (BinaryBasicBlock &BB : blocks()) { - for (MCInst &Instr : BB) { + for (BinaryBasicBlock::iterator II = BB.begin(); II != BB.end(); ++II) { + MCInst &Instr = *II; if (!BC.MIB->isIndirectBranch(Instr)) continue; @@ -1789,7 +1818,7 @@ bool BinaryFunction::postProcessIndirectBranches( const MCExpr *DispExpr; MCInst *PCRelBaseInstr; IndirectBranchType Type = BC.MIB->analyzeIndirectBranch( - Instr, BB.begin(), BB.end(), PtrSize, MemLocInstr, BaseRegNum, + Instr, BB.begin(), II, PtrSize, MemLocInstr, BaseRegNum, IndexRegNum, DispValue, DispExpr, PCRelBaseInstr); if (Type != IndirectBranchType::UNKNOWN || MemLocInstr != nullptr) continue; @@ -4488,7 +4517,7 @@ void BinaryFunction::addRelocation(uint64_t Address, MCSymbol *Symbol, uint64_t Offset = Address - getAddress(); LLVM_DEBUG(dbgs() << "BOLT-DEBUG: addRelocation in " << formatv("{0}@{1:x} against {2}\n", *this, Offset, - Symbol->getName())); + (Symbol ? Symbol->getName() : ""))); bool IsCI = BC.isAArch64() && isInConstantIsland(Address); std::map &Rels = IsCI ? Islands->Relocations : Relocations; diff --git a/bolt/lib/Core/DebugData.cpp b/bolt/lib/Core/DebugData.cpp index 8d24c9281b8f2a..22ca8c5acccf12 100644 --- a/bolt/lib/Core/DebugData.cpp +++ b/bolt/lib/Core/DebugData.cpp @@ -495,7 +495,8 @@ void DebugAddrWriterDwarf5::update(DIEBuilder &DIEBlder, DWARFUnit &CU) { const endianness Endian = BC->DwCtx->isLittleEndian() ? support::little : support::big; const DWARFSection &AddrSec = BC->DwCtx->getDWARFObj().getAddrSection(); - DWARFDataExtractor AddrData(BC->DwCtx->getDWARFObj(), AddrSec, Endian, 0); + DWARFDataExtractor AddrData(BC->DwCtx->getDWARFObj(), AddrSec, + Endian == support::little, 0); DWARFDebugAddrTable AddrTable; DIDumpOptions DumpOpts; constexpr uint32_t HeaderSize = 8; diff --git a/bolt/lib/Core/MCPlusBuilder.cpp b/bolt/lib/Core/MCPlusBuilder.cpp index 027cef1063ee3e..0a5eb44e4876fe 100644 --- a/bolt/lib/Core/MCPlusBuilder.cpp +++ b/bolt/lib/Core/MCPlusBuilder.cpp @@ -268,6 +268,17 @@ bool MCPlusBuilder::clearOffset(MCInst &Inst) { return true; } +std::optional MCPlusBuilder::getLabel(const MCInst &Inst) const { + if (auto Label = tryGetAnnotationAs(Inst, MCAnnotation::kLabel)) + return *Label; + return std::nullopt; +} + +bool MCPlusBuilder::setLabel(MCInst &Inst, MCSymbol *Label) { + getOrCreateAnnotationAs(Inst, MCAnnotation::kLabel) = Label; + return true; +} + bool MCPlusBuilder::hasAnnotation(const MCInst &Inst, unsigned Index) const { const MCInst *AnnotationInst = getAnnotationInst(Inst); if (!AnnotationInst) diff --git a/bolt/lib/Core/Relocation.cpp b/bolt/lib/Core/Relocation.cpp index a73545905c545f..e4d0f26c305f4e 100644 --- a/bolt/lib/Core/Relocation.cpp +++ b/bolt/lib/Core/Relocation.cpp @@ -20,6 +20,13 @@ using namespace llvm; using namespace bolt; +namespace ELFReserved { +enum { + R_RISCV_TPREL_I = 49, + R_RISCV_TPREL_S = 50, +}; +} // namespace ELFReserved + Triple::ArchType Relocation::Arch; static bool isSupportedX86(uint64_t Type) { @@ -35,6 +42,7 @@ static bool isSupportedX86(uint64_t Type) { case ELF::R_X86_64_PC32: case ELF::R_X86_64_PC64: case ELF::R_X86_64_PLT32: + case ELF::R_X86_64_GOTPC64: case ELF::R_X86_64_GOTPCREL: case ELF::R_X86_64_GOTTPOFF: case ELF::R_X86_64_TPOFF32: @@ -110,6 +118,13 @@ static bool isSupportedRISCV(uint64_t Type) { case ELF::R_RISCV_LO12_I: case ELF::R_RISCV_LO12_S: case ELF::R_RISCV_64: + case ELF::R_RISCV_TLS_GOT_HI20: + case ELF::R_RISCV_TPREL_HI20: + case ELF::R_RISCV_TPREL_ADD: + case ELF::R_RISCV_TPREL_LO12_I: + case ELF::R_RISCV_TPREL_LO12_S: + case ELFReserved::R_RISCV_TPREL_I: + case ELFReserved::R_RISCV_TPREL_S: return true; } } @@ -136,6 +151,7 @@ static size_t getSizeForTypeX86(uint64_t Type) { return 4; case ELF::R_X86_64_PC64: case ELF::R_X86_64_64: + case ELF::R_X86_64_GOTPC64: return 8; } } @@ -212,6 +228,7 @@ static size_t getSizeForTypeRISCV(uint64_t Type) { return 4; case ELF::R_RISCV_64: case ELF::R_RISCV_GOT_HI20: + case ELF::R_RISCV_TLS_GOT_HI20: // See extractValueRISCV for why this is necessary. return 8; } @@ -530,6 +547,7 @@ static uint64_t extractValueRISCV(uint64_t Type, uint64_t Contents, case ELF::R_RISCV_BRANCH: return extractBImmRISCV(Contents); case ELF::R_RISCV_GOT_HI20: + case ELF::R_RISCV_TLS_GOT_HI20: // We need to know the exact address of the GOT entry so we extract the // value from both the AUIPC and L[D|W]. We cannot rely on the symbol in the // relocation for this since it simply refers to the object that is stored @@ -598,6 +616,7 @@ static bool isGOTRISCV(uint64_t Type) { default: return false; case ELF::R_RISCV_GOT_HI20: + case ELF::R_RISCV_TLS_GOT_HI20: return true; } } @@ -634,6 +653,14 @@ static bool isTLSRISCV(uint64_t Type) { switch (Type) { default: return false; + case ELF::R_RISCV_TLS_GOT_HI20: + case ELF::R_RISCV_TPREL_HI20: + case ELF::R_RISCV_TPREL_ADD: + case ELF::R_RISCV_TPREL_LO12_I: + case ELF::R_RISCV_TPREL_LO12_S: + case ELFReserved::R_RISCV_TPREL_I: + case ELFReserved::R_RISCV_TPREL_S: + return true; } } @@ -655,6 +682,7 @@ static bool isPCRelativeX86(uint64_t Type) { case ELF::R_X86_64_PLT32: case ELF::R_X86_64_GOTOFF64: case ELF::R_X86_64_GOTPC32: + case ELF::R_X86_64_GOTPC64: case ELF::R_X86_64_GOTTPOFF: case ELF::R_X86_64_GOTPCRELX: case ELF::R_X86_64_REX_GOTPCRELX: @@ -730,6 +758,7 @@ static bool isPCRelativeRISCV(uint64_t Type) { case ELF::R_RISCV_RVC_JUMP: case ELF::R_RISCV_RVC_BRANCH: case ELF::R_RISCV_32_PCREL: + case ELF::R_RISCV_TLS_GOT_HI20: return true; } } @@ -797,6 +826,12 @@ bool Relocation::isX86GOTPCRELX(uint64_t Type) { return Type == ELF::R_X86_64_GOTPCRELX || Type == ELF::R_X86_64_REX_GOTPCRELX; } +bool Relocation::isX86GOTPC64(uint64_t Type) { + if (Arch != Triple::x86_64) + return false; + return Type == ELF::R_X86_64_GOTPC64; +} + bool Relocation::isNone(uint64_t Type) { return Type == getNone(); } bool Relocation::isRelative(uint64_t Type) { @@ -823,6 +858,19 @@ bool Relocation::isTLS(uint64_t Type) { return isTLSX86(Type); } +bool Relocation::isInstructionReference(uint64_t Type) { + if (Arch != Triple::riscv64) + return false; + + switch (Type) { + default: + return false; + case ELF::R_RISCV_PCREL_LO12_I: + case ELF::R_RISCV_PCREL_LO12_S: + return true; + } +} + uint64_t Relocation::getNone() { if (Arch == Triple::aarch64) return ELF::R_AARCH64_NONE; diff --git a/bolt/lib/Passes/BinaryPasses.cpp b/bolt/lib/Passes/BinaryPasses.cpp index bb760ea93ad16e..3ba53d7b2b7988 100644 --- a/bolt/lib/Passes/BinaryPasses.cpp +++ b/bolt/lib/Passes/BinaryPasses.cpp @@ -575,6 +575,7 @@ bool CheckLargeFunctions::shouldOptimize(const BinaryFunction &BF) const { void LowerAnnotations::runOnFunctions(BinaryContext &BC) { std::vector> PreservedOffsetAnnotations; + std::vector> PreservedLabelAnnotations; for (auto &It : BC.getBinaryFunctions()) { BinaryFunction &BF = It.second; @@ -609,6 +610,8 @@ void LowerAnnotations::runOnFunctions(BinaryContext &BC) { if (BF.requiresAddressTranslation() && BC.MIB->getOffset(*II)) PreservedOffsetAnnotations.emplace_back(&(*II), *BC.MIB->getOffset(*II)); + if (auto Label = BC.MIB->getLabel(*II)) + PreservedLabelAnnotations.emplace_back(&*II, *Label); BC.MIB->stripAnnotations(*II); } } @@ -625,6 +628,8 @@ void LowerAnnotations::runOnFunctions(BinaryContext &BC) { // Reinsert preserved annotations we need during code emission. for (const std::pair &Item : PreservedOffsetAnnotations) BC.MIB->setOffset(*Item.first, Item.second); + for (auto [Instr, Label] : PreservedLabelAnnotations) + BC.MIB->setLabel(*Instr, Label); } // Check for dirty state in MCSymbol objects that might be a consequence diff --git a/bolt/lib/Passes/FixRISCVCallsPass.cpp b/bolt/lib/Passes/FixRISCVCallsPass.cpp index 963a8b04cf9db2..e2984deda16dc3 100644 --- a/bolt/lib/Passes/FixRISCVCallsPass.cpp +++ b/bolt/lib/Passes/FixRISCVCallsPass.cpp @@ -43,7 +43,12 @@ void FixRISCVCallsPass::runOnFunction(BinaryFunction &BF) { MCInst OldCall = *NextII; auto L = BC.scopeLock(); - MIB->createCall(*II, Target, Ctx); + + if (MIB->isTailCall(*NextII)) + MIB->createTailCall(*II, Target, Ctx); + else + MIB->createCall(*II, Target, Ctx); + MIB->moveAnnotations(std::move(OldCall), *II); // The original offset was set on the jalr of the auipc+jalr pair. Since diff --git a/bolt/lib/Rewrite/JITLinkLinker.cpp b/bolt/lib/Rewrite/JITLinkLinker.cpp index 1df086a665789d..5e06121f4df271 100644 --- a/bolt/lib/Rewrite/JITLinkLinker.cpp +++ b/bolt/lib/Rewrite/JITLinkLinker.cpp @@ -141,6 +141,19 @@ struct JITLinkLinker::Context : jitlink::JITLinkContext { orc::ExecutorAddr(Address), JITSymbolFlags()); continue; } + + if (Linker.BC.isGOTSymbol(SymName)) { + if (const BinaryData *I = Linker.BC.getGOTSymbol()) { + uint64_t Address = + I->isMoved() ? I->getOutputAddress() : I->getAddress(); + LLVM_DEBUG(dbgs() << "Resolved to address 0x" + << Twine::utohexstr(Address) << "\n"); + AllResults[Symbol.first] = orc::ExecutorSymbolDef( + orc::ExecutorAddr(Address), JITSymbolFlags()); + continue; + } + } + LLVM_DEBUG(dbgs() << "Resolved to address 0x0\n"); AllResults[Symbol.first] = orc::ExecutorSymbolDef(orc::ExecutorAddr(0), JITSymbolFlags()); diff --git a/bolt/lib/Rewrite/MachORewriteInstance.cpp b/bolt/lib/Rewrite/MachORewriteInstance.cpp index b827a196c82653..8be8257f15c1ce 100644 --- a/bolt/lib/Rewrite/MachORewriteInstance.cpp +++ b/bolt/lib/Rewrite/MachORewriteInstance.cpp @@ -56,25 +56,28 @@ namespace bolt { extern MCPlusBuilder *createX86MCPlusBuilder(const MCInstrAnalysis *, const MCInstrInfo *, - const MCRegisterInfo *); + const MCRegisterInfo *, + const MCSubtargetInfo *); extern MCPlusBuilder *createAArch64MCPlusBuilder(const MCInstrAnalysis *, const MCInstrInfo *, - const MCRegisterInfo *); + const MCRegisterInfo *, + const MCSubtargetInfo *); namespace { MCPlusBuilder *createMCPlusBuilder(const Triple::ArchType Arch, const MCInstrAnalysis *Analysis, const MCInstrInfo *Info, - const MCRegisterInfo *RegInfo) { + const MCRegisterInfo *RegInfo, + const MCSubtargetInfo *STI) { #ifdef X86_AVAILABLE if (Arch == Triple::x86_64) - return createX86MCPlusBuilder(Analysis, Info, RegInfo); + return createX86MCPlusBuilder(Analysis, Info, RegInfo, STI); #endif #ifdef AARCH64_AVAILABLE if (Arch == Triple::aarch64) - return createAArch64MCPlusBuilder(Analysis, Info, RegInfo); + return createAArch64MCPlusBuilder(Analysis, Info, RegInfo, STI); #endif llvm_unreachable("architecture unsupported by MCPlusBuilder"); @@ -106,8 +109,9 @@ MachORewriteInstance::MachORewriteInstance(object::MachOObjectFile *InputFile, return; } BC = std::move(BCOrErr.get()); - BC->initializeTarget(std::unique_ptr(createMCPlusBuilder( - BC->TheTriple->getArch(), BC->MIA.get(), BC->MII.get(), BC->MRI.get()))); + BC->initializeTarget(std::unique_ptr( + createMCPlusBuilder(BC->TheTriple->getArch(), BC->MIA.get(), + BC->MII.get(), BC->MRI.get(), BC->STI.get()))); if (opts::Instrument) BC->setRuntimeLibrary(std::make_unique()); } diff --git a/bolt/lib/Rewrite/RewriteInstance.cpp b/bolt/lib/Rewrite/RewriteInstance.cpp index 03cbe0461b2112..8b821eb984b950 100644 --- a/bolt/lib/Rewrite/RewriteInstance.cpp +++ b/bolt/lib/Rewrite/RewriteInstance.cpp @@ -272,20 +272,21 @@ extern const char *BoltRevision; MCPlusBuilder *createMCPlusBuilder(const Triple::ArchType Arch, const MCInstrAnalysis *Analysis, const MCInstrInfo *Info, - const MCRegisterInfo *RegInfo) { + const MCRegisterInfo *RegInfo, + const MCSubtargetInfo *STI) { #ifdef X86_AVAILABLE if (Arch == Triple::x86_64) - return createX86MCPlusBuilder(Analysis, Info, RegInfo); + return createX86MCPlusBuilder(Analysis, Info, RegInfo, STI); #endif #ifdef AARCH64_AVAILABLE if (Arch == Triple::aarch64) - return createAArch64MCPlusBuilder(Analysis, Info, RegInfo); + return createAArch64MCPlusBuilder(Analysis, Info, RegInfo, STI); #endif #ifdef RISCV_AVAILABLE if (Arch == Triple::riscv64) - return createRISCVMCPlusBuilder(Analysis, Info, RegInfo); + return createRISCVMCPlusBuilder(Analysis, Info, RegInfo, STI); #endif llvm_unreachable("architecture unsupported by MCPlusBuilder"); @@ -348,8 +349,9 @@ RewriteInstance::RewriteInstance(ELFObjectFileBase *File, const int Argc, return; } BC = std::move(BCOrErr.get()); - BC->initializeTarget(std::unique_ptr(createMCPlusBuilder( - BC->TheTriple->getArch(), BC->MIA.get(), BC->MII.get(), BC->MRI.get()))); + BC->initializeTarget(std::unique_ptr( + createMCPlusBuilder(BC->TheTriple->getArch(), BC->MIA.get(), + BC->MII.get(), BC->MRI.get(), BC->STI.get()))); BAT = std::make_unique(); @@ -408,8 +410,9 @@ static bool checkOffsets(const typename ELFT::Phdr &Phdr, return true; // Only non-empty sections can be at the end of a segment. - uint64_t SectionSize = Sec.sh_size ? Sec.sh_size : 1; - AddressRange SectionAddressRange(Sec.sh_offset, Sec.sh_offset + SectionSize); + uint64_t SectionSize = Sec.sh_size ? Sec.sh_size : 1ull; + AddressRange SectionAddressRange((uint64_t)Sec.sh_offset, + Sec.sh_offset + SectionSize); AddressRange SegmentAddressRange(Phdr.p_offset, Phdr.p_offset + Phdr.p_filesz); if (SegmentAddressRange.contains(SectionAddressRange)) @@ -425,8 +428,9 @@ template static bool checkVMA(const typename ELFT::Phdr &Phdr, const typename ELFT::Shdr &Sec, bool &Overlap) { // Only non-empty sections can be at the end of a segment. - uint64_t SectionSize = Sec.sh_size ? Sec.sh_size : 1; - AddressRange SectionAddressRange(Sec.sh_addr, Sec.sh_addr + SectionSize); + uint64_t SectionSize = Sec.sh_size ? Sec.sh_size : 1ull; + AddressRange SectionAddressRange((uint64_t)Sec.sh_addr, + Sec.sh_addr + SectionSize); AddressRange SegmentAddressRange(Phdr.p_vaddr, Phdr.p_vaddr + Phdr.p_memsz); if (SegmentAddressRange.contains(SectionAddressRange)) @@ -2332,7 +2336,8 @@ void RewriteInstance::handleRelocation(const SectionRef &RelocatedSection, if (BC->isX86()) return; - // The non-got related TLS relocations on AArch64 also could be skipped. + // The non-got related TLS relocations on AArch64 and RISC-V also could be + // skipped. if (!Relocation::isGOT(RType)) return; } @@ -2394,9 +2399,13 @@ void RewriteInstance::handleRelocation(const SectionRef &RelocatedSection, } MCSymbol *ReferencedSymbol = nullptr; - if (!IsSectionRelocation) + if (!IsSectionRelocation) { if (BinaryData *BD = BC->getBinaryDataByName(SymbolName)) ReferencedSymbol = BD->getSymbol(); + else if (BC->isGOTSymbol(SymbolName)) + if (BinaryData *BD = BC->getGOTSymbol()) + ReferencedSymbol = BD->getSymbol(); + } ErrorOr ReferencedSection{std::errc::bad_address}; symbol_iterator SymbolIter = Rel.getSymbol(); @@ -2537,7 +2546,17 @@ void RewriteInstance::handleRelocation(const SectionRef &RelocatedSection, // Adjust the point of reference to a code location inside a function. if (ReferencedBF->containsAddress(Address, /*UseMaxSize = */ true)) { RefFunctionOffset = Address - ReferencedBF->getAddress(); - if (RefFunctionOffset) { + if (Relocation::isInstructionReference(RType)) { + // Instruction labels are created while disassembling so we just leave + // the symbol empty for now. Since the extracted value is typically + // unrelated to the referenced symbol (e.g., %pcrel_lo in RISC-V + // references an instruction but the patched value references the low + // bits of a data address), we set the extracted value to the symbol + // address in order to be able to correctly reconstruct the reference + // later. + ReferencedSymbol = nullptr; + ExtractedValue = Address; + } else if (RefFunctionOffset) { if (ContainingBF && ContainingBF != ReferencedBF) { ReferencedSymbol = ReferencedBF->addEntryPointAtOffset(RefFunctionOffset); diff --git a/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp b/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp index bf77244102a21b..c2a4607411a49e 100644 --- a/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp +++ b/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp @@ -128,9 +128,7 @@ static InstructionListType createIncMemory(MCPhysReg RegTo, MCPhysReg RegTmp) { } class AArch64MCPlusBuilder : public MCPlusBuilder { public: - AArch64MCPlusBuilder(const MCInstrAnalysis *Analysis, const MCInstrInfo *Info, - const MCRegisterInfo *RegInfo) - : MCPlusBuilder(Analysis, Info, RegInfo) {} + using MCPlusBuilder::MCPlusBuilder; bool equals(const MCTargetExpr &A, const MCTargetExpr &B, CompFuncTy Comp) const override { @@ -1654,8 +1652,9 @@ namespace bolt { MCPlusBuilder *createAArch64MCPlusBuilder(const MCInstrAnalysis *Analysis, const MCInstrInfo *Info, - const MCRegisterInfo *RegInfo) { - return new AArch64MCPlusBuilder(Analysis, Info, RegInfo); + const MCRegisterInfo *RegInfo, + const MCSubtargetInfo *STI) { + return new AArch64MCPlusBuilder(Analysis, Info, RegInfo, STI); } } // namespace bolt diff --git a/bolt/lib/Target/RISCV/RISCVMCPlusBuilder.cpp b/bolt/lib/Target/RISCV/RISCVMCPlusBuilder.cpp index c2e64039a25007..af7645f5684711 100644 --- a/bolt/lib/Target/RISCV/RISCVMCPlusBuilder.cpp +++ b/bolt/lib/Target/RISCV/RISCVMCPlusBuilder.cpp @@ -46,6 +46,7 @@ class RISCVMCPlusBuilder : public MCPlusBuilder { case ELF::R_RISCV_HI20: case ELF::R_RISCV_LO12_I: case ELF::R_RISCV_LO12_S: + case ELF::R_RISCV_TLS_GOT_HI20: return true; default: llvm_unreachable("Unexpected RISCV relocation type in code"); @@ -86,6 +87,7 @@ class RISCVMCPlusBuilder : public MCPlusBuilder { return false; case RISCV::JALR: case RISCV::C_JALR: + case RISCV::C_JR: return true; } } @@ -157,6 +159,17 @@ class RISCVMCPlusBuilder : public MCPlusBuilder { DispValue = 0; DispExpr = nullptr; PCRelBaseOut = nullptr; + + // Check for the following long tail call sequence: + // 1: auipc xi, %pcrel_hi(sym) + // jalr zero, %pcrel_lo(1b)(xi) + if (Instruction.getOpcode() == RISCV::JALR && Begin != End) { + MCInst &PrevInst = *std::prev(End); + if (isRISCVCall(PrevInst, Instruction) && + Instruction.getOperand(0).getReg() == RISCV::X0) + return IndirectBranchType::POSSIBLE_TAIL_CALL; + } + return IndirectBranchType::UNKNOWN; } @@ -396,6 +409,7 @@ class RISCVMCPlusBuilder : public MCPlusBuilder { default: return Expr; case ELF::R_RISCV_GOT_HI20: + case ELF::R_RISCV_TLS_GOT_HI20: // The GOT is reused so no need to create GOT relocations case ELF::R_RISCV_PCREL_HI20: return RISCVMCExpr::create(Expr, RISCVMCExpr::VK_RISCV_PCREL_HI, Ctx); @@ -457,8 +471,9 @@ namespace bolt { MCPlusBuilder *createRISCVMCPlusBuilder(const MCInstrAnalysis *Analysis, const MCInstrInfo *Info, - const MCRegisterInfo *RegInfo) { - return new RISCVMCPlusBuilder(Analysis, Info, RegInfo); + const MCRegisterInfo *RegInfo, + const MCSubtargetInfo *STI) { + return new RISCVMCPlusBuilder(Analysis, Info, RegInfo, STI); } } // namespace bolt diff --git a/bolt/lib/Target/X86/X86MCPlusBuilder.cpp b/bolt/lib/Target/X86/X86MCPlusBuilder.cpp index 4cb9d61710d1da..ce8a4d69148544 100644 --- a/bolt/lib/Target/X86/X86MCPlusBuilder.cpp +++ b/bolt/lib/Target/X86/X86MCPlusBuilder.cpp @@ -87,9 +87,7 @@ static InstructionListType createIncMemory(const MCSymbol *Target, class X86MCPlusBuilder : public MCPlusBuilder { public: - X86MCPlusBuilder(const MCInstrAnalysis *Analysis, const MCInstrInfo *Info, - const MCRegisterInfo *RegInfo) - : MCPlusBuilder(Analysis, Info, RegInfo) {} + using MCPlusBuilder::MCPlusBuilder; std::unique_ptr createTargetSymbolizer(BinaryFunction &Function, @@ -403,6 +401,7 @@ class X86MCPlusBuilder : public MCPlusBuilder { case ELF::R_X86_64_PC8: case ELF::R_X86_64_PC32: case ELF::R_X86_64_PC64: + case ELF::R_X86_64_GOTPC64: case ELF::R_X86_64_GOTPCRELX: case ELF::R_X86_64_REX_GOTPCRELX: return true; @@ -3578,8 +3577,9 @@ namespace bolt { MCPlusBuilder *createX86MCPlusBuilder(const MCInstrAnalysis *Analysis, const MCInstrInfo *Info, - const MCRegisterInfo *RegInfo) { - return new X86MCPlusBuilder(Analysis, Info, RegInfo); + const MCRegisterInfo *RegInfo, + const MCSubtargetInfo *STI) { + return new X86MCPlusBuilder(Analysis, Info, RegInfo, STI); } } // namespace bolt diff --git a/bolt/lib/Target/X86/X86MCSymbolizer.cpp b/bolt/lib/Target/X86/X86MCSymbolizer.cpp index 5eeb18467f84a6..ca7fe137152fd3 100644 --- a/bolt/lib/Target/X86/X86MCSymbolizer.cpp +++ b/bolt/lib/Target/X86/X86MCSymbolizer.cpp @@ -130,6 +130,15 @@ bool X86MCSymbolizer::tryAddingSymbolicOperand( if (!Relocation) return processPCRelOperandNoRel(); + // GOTPC64 is special because the X86 Assembler doesn't know how to emit + // a PC-relative 8-byte fixup, which is what we need to cover this. The + // only way to do this is to use the symbol name _GLOBAL_OFFSET_TABLE_. + if (Relocation::isX86GOTPC64(Relocation->Type)) { + auto [Sym, Addend] = handleGOTPC64(*Relocation, InstAddress); + addOperand(Sym, Addend); + return true; + } + uint64_t SymbolValue = Relocation->Value - Relocation->Addend; if (Relocation->isPCRelative()) SymbolValue += InstAddress + ImmOffset; @@ -149,6 +158,26 @@ bool X86MCSymbolizer::tryAddingSymbolicOperand( return true; } +std::pair +X86MCSymbolizer::handleGOTPC64(const Relocation &R, uint64_t InstrAddr) { + BinaryContext &BC = Function.getBinaryContext(); + const BinaryData *GOTSymBD = BC.getGOTSymbol(); + if (!GOTSymBD || !GOTSymBD->getAddress()) { + errs() << "BOLT-ERROR: R_X86_GOTPC64 relocation is present but we did " + "not detect a valid _GLOBAL_OFFSET_TABLE_ in symbol table\n"; + exit(1); + } + // R_X86_GOTPC64 are not relative to the Reloc nor end of instruction, + // but the start of the MOVABSQ instruction. So the Target Address is + // whatever is encoded in the original operand when we disassembled + // the binary (here, R.Value) plus MOVABSQ address (InstrAddr). + // Here we extract the intended Addend by subtracting the real + // GOT addr. + const int64_t Addend = R.Value + InstrAddr - GOTSymBD->getAddress(); + return std::make_pair(BC.Ctx->getOrCreateSymbol("_GLOBAL_OFFSET_TABLE_"), + Addend); +} + void X86MCSymbolizer::tryAddingPcLoadReferenceComment(raw_ostream &CStream, int64_t Value, uint64_t Address) {} diff --git a/bolt/lib/Target/X86/X86MCSymbolizer.h b/bolt/lib/Target/X86/X86MCSymbolizer.h index 83a039bd70310b..9ed18b69c74ce4 100644 --- a/bolt/lib/Target/X86/X86MCSymbolizer.h +++ b/bolt/lib/Target/X86/X86MCSymbolizer.h @@ -20,6 +20,9 @@ class X86MCSymbolizer : public MCSymbolizer { BinaryFunction &Function; bool CreateNewSymbols{true}; + std::pair handleGOTPC64(const Relocation &R, + uint64_t InstrAddr); + public: X86MCSymbolizer(BinaryFunction &Function, bool CreateNewSymbols = true) : MCSymbolizer(*Function.getBinaryContext().Ctx.get(), nullptr), diff --git a/bolt/test/RISCV/Inputs/tls-le-gnu-ld.yaml b/bolt/test/RISCV/Inputs/tls-le-gnu-ld.yaml new file mode 100644 index 00000000000000..feec407ffdfdaf --- /dev/null +++ b/bolt/test/RISCV/Inputs/tls-le-gnu-ld.yaml @@ -0,0 +1,92 @@ +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_RISCV + Entry: 0x100B0 +ProgramHeaders: + - Type: PT_LOAD + Flags: [ PF_X, PF_R ] + FirstSec: .text + LastSec: .text + VAddr: 0x10000 + Align: 0x1000 + Offset: 0x0 + - Type: PT_TLS + Flags: [ PF_R ] + FirstSec: .tbss + LastSec: .tbss + VAddr: 0x110C0 + Align: 0x8 + Offset: 0xc0 +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + Address: 0x100B0 + AddressAlign: 0x4 + Content: '13000000832202002320520067800000' + - Name: .tbss + Type: SHT_NOBITS + Flags: [ SHF_WRITE, SHF_ALLOC, SHF_TLS ] + Address: 0x110C0 + AddressAlign: 0x8 + Size: 0x8 + - Name: .rela.text + Type: SHT_RELA + Flags: [ SHF_INFO_LINK ] + Link: .symtab + AddressAlign: 0x8 + Info: .text + Relocations: + - Offset: 0x100B4 + Type: R_RISCV_NONE + - Offset: 0x100B4 + Type: R_RISCV_RELAX + - Offset: 0x100B4 + Type: R_RISCV_NONE + - Offset: 0x100B4 + Type: R_RISCV_RELAX + - Offset: 0x100B4 + Symbol: i + Type: 0x31 + - Offset: 0x100B4 + Type: R_RISCV_RELAX + - Offset: 0x100B8 + Symbol: i + Type: 0x32 + - Offset: 0x100B8 + Type: R_RISCV_RELAX + - Type: SectionHeaderTable + Sections: + - Name: .text + - Name: .rela.text + - Name: .tbss + - Name: .symtab + - Name: .strtab + - Name: .shstrtab +Symbols: + - Name: .text + Type: STT_SECTION + Section: .text + Value: 0x100B0 + - Name: .tbss + Type: STT_SECTION + Section: .tbss + Value: 0x110C0 + - Name: '__global_pointer$' + Index: SHN_ABS + Binding: STB_GLOBAL + Value: 0x118C0 + - Name: i + Type: STT_TLS + Section: .tbss + Binding: STB_GLOBAL + Size: 0x8 + - Name: _start + Section: .text + Binding: STB_GLOBAL + Value: 0x100B0 + Size: 0x10 +... diff --git a/bolt/test/RISCV/call-annotations.s b/bolt/test/RISCV/call-annotations.s index e2c5a1040faee1..bc539bb0ec7796 100644 --- a/bolt/test/RISCV/call-annotations.s +++ b/bolt/test/RISCV/call-annotations.s @@ -4,7 +4,7 @@ // RUN: llvm-mc -triple riscv64 -filetype obj -o %t.o %s // RUN: ld.lld --emit-relocs -o %t %t.o // RUN: llvm-bolt --enable-bat --print-cfg --print-fix-riscv-calls \ -// RUN: --print-only=_start -o /dev/null %t | FileCheck %s +// RUN: -o /dev/null %t | FileCheck %s .text .global f @@ -19,11 +19,24 @@ f: // CHECK-NEXT: jal ra, f # Offset: 8 // CHECK-NEXT: jal zero, f # TAILCALL # Offset: 12 +// CHECK-LABEL: Binary Function "long_tail" after building cfg { +// CHECK: auipc t1, f +// CHECK-NEXT: jalr zero, -24(t1) # TAILCALL # Offset: 8 + +// CHECK-LABEL: Binary Function "compressed_tail" after building cfg { +// CHECK: jr a0 # TAILCALL # Offset: 0 + // CHECK-LABEL: Binary Function "_start" after fix-riscv-calls { // CHECK: call f # Offset: 0 // CHECK-NEXT: call f # Offset: 8 // CHECK-NEXT: tail f # TAILCALL # Offset: 12 +// CHECK-LABEL: Binary Function "long_tail" after fix-riscv-calls { +// CHECK: tail f # TAILCALL # Offset: 4 + +// CHECK-LABEL: Binary Function "compressed_tail" after fix-riscv-calls { +// CHECK: jr a0 # TAILCALL # Offset: 0 + .globl _start .p2align 1 _start: @@ -31,3 +44,21 @@ _start: jal f jal zero, f .size _start, .-_start + + .globl long_tail + .p2align 1 +long_tail: + // NOTE: BOLT assumes indirect calls in single-BB functions are tail calls + // so artificially introduce a second BB to force RISC-V-specific analysis + // to get triggered. + beq a0, a1, 1f +1: + tail f + .size long_tail, .-long_tail + + .globl compressed_tail + .p2align 1 + .option rvc +compressed_tail: + c.jr a0 + .size compressed_tail, .-compressed_tail diff --git a/bolt/test/RISCV/reloc-abs.s b/bolt/test/RISCV/reloc-abs.s index 3e4b8b1395e1ff..5b728f092b3c9f 100644 --- a/bolt/test/RISCV/reloc-abs.s +++ b/bolt/test/RISCV/reloc-abs.s @@ -17,8 +17,7 @@ _start: .option push .option norelax 1: -// CHECK: .Ltmp0 -// CHECK: auipc gp, %pcrel_hi(__global_pointer$) +// CHECK: auipc gp, %pcrel_hi(__global_pointer$) # Label: .Ltmp0 // CHECK-NEXT: addi gp, gp, %pcrel_lo(.Ltmp0) auipc gp, %pcrel_hi(__global_pointer$) addi gp, gp, %pcrel_lo(1b) diff --git a/bolt/test/RISCV/reloc-bb-split.s b/bolt/test/RISCV/reloc-bb-split.s new file mode 100644 index 00000000000000..5995562cf130b0 --- /dev/null +++ b/bolt/test/RISCV/reloc-bb-split.s @@ -0,0 +1,42 @@ +// RUN: %clang %cflags -o %t %s +// RUN: llvm-bolt --print-cfg --print-only=_start -o /dev/null %t \ +// RUN: | FileCheck %s + + .data + .globl d + .p2align 3 +d: + .dword 0 + + .text + .globl _start + .p2align 1 +// CHECK-LABEL: Binary Function "_start" after building cfg { +_start: +/// The local label is used for %pcrel_lo as well as a jump target so a new +/// basic block should start there. +// CHECK-LABEL: {{^}}.LBB00 +// CHECK: nop +// CHECK-LABEL: {{^}}.Ltmp0 +// CHECK: auipc t0, %pcrel_hi(d) # Label: .Ltmp1 +// CHECK-NEXT: ld t0, %pcrel_lo(.Ltmp1)(t0) +// CHECK-NEXT: j .Ltmp0 + nop +1: + auipc t0, %pcrel_hi(d) + ld t0, %pcrel_lo(1b)(t0) + j 1b + +/// The local label is used only for %pcrel_lo so no new basic block should +/// start there. +// CHECK-LABEL: {{^}}.LFT0 +// CHECK: nop +// CHECK-NEXT: auipc t0, %pcrel_hi(d) # Label: .Ltmp2 +// CHECK-NEXT: ld t0, %pcrel_lo(.Ltmp2)(t0) +// CHECK-NEXT: ret + nop +1: + auipc t0, %pcrel_hi(d) + ld t0, %pcrel_lo(1b)(t0) + ret + .size _start, .-_start diff --git a/bolt/test/RISCV/reloc-got.s b/bolt/test/RISCV/reloc-got.s index b6cd61be723bfa..dcf9d0ea3ffbf2 100644 --- a/bolt/test/RISCV/reloc-got.s +++ b/bolt/test/RISCV/reloc-got.s @@ -14,8 +14,7 @@ d: // CHECK: Binary Function "_start" after building cfg { _start: nop // Here to not make the _start and .Ltmp0 symbols coincide -// CHECK: .Ltmp0 -// CHECK: auipc t0, %pcrel_hi(__BOLT_got_zero+{{[0-9]+}}) +// CHECK: auipc t0, %pcrel_hi(__BOLT_got_zero+{{[0-9]+}}) # Label: .Ltmp0 // CHECK-NEXT: ld t0, %pcrel_lo(.Ltmp0)(t0) 1: auipc t0, %got_pcrel_hi(d) diff --git a/bolt/test/RISCV/reloc-pcrel.s b/bolt/test/RISCV/reloc-pcrel.s index 36b132727291ec..3ad3015a0a57fa 100644 --- a/bolt/test/RISCV/reloc-pcrel.s +++ b/bolt/test/RISCV/reloc-pcrel.s @@ -14,12 +14,10 @@ d: // CHECK: Binary Function "_start" after building cfg { _start: nop // Here to not make the _start and .Ltmp0 symbols coincide -// CHECK: .Ltmp0 -// CHECK: auipc t0, %pcrel_hi(d) +// CHECK: auipc t0, %pcrel_hi(d) # Label: .Ltmp0 // CHECK-NEXT: ld t0, %pcrel_lo(.Ltmp0)(t0) ld t0, d -// CHECK: .Ltmp1 -// CHECK: auipc t1, %pcrel_hi(d) +// CHECK-NEXT: auipc t1, %pcrel_hi(d) # Label: .Ltmp1 // CHECK-NEXT: sd t0, %pcrel_lo(.Ltmp1)(t1) sd t0, d, t1 ret diff --git a/bolt/test/RISCV/reloc-tls.s b/bolt/test/RISCV/reloc-tls.s new file mode 100644 index 00000000000000..6ced25b8e630a5 --- /dev/null +++ b/bolt/test/RISCV/reloc-tls.s @@ -0,0 +1,44 @@ +// RUN: llvm-mc -triple riscv64 -filetype obj -o %t.o %s +// RUN: ld.lld --emit-relocs -o %t %t.o +// RUN: llvm-bolt --print-cfg --print-only=tls_le,tls_ie -o /dev/null %t \ +// RUN: | FileCheck %s + +// CHECK-LABEL: Binary Function "tls_le{{.*}}" after building cfg { +// CHECK: lui a5, 0 +// CHECK-NEXT: add a5, a5, tp +// CHECK-NEXT: lw t0, 0(a5) +// CHECK-NEXT: sw t0, 0(a5) + +// CHECK-LABEL: Binary Function "tls_ie" after building cfg { +// CHECK-LABEL: .Ltmp0 +// CHECK: auipc a0, %pcrel_hi(__BOLT_got_zero+{{[0-9]+}}) +// CHECK-NEXT: ld a0, %pcrel_lo(.Ltmp0)(a0) + .text + .globl tls_le, _start + .p2align 2 +tls_le: +_start: + nop + lui a5, %tprel_hi(i) + add a5, a5, tp, %tprel_add(i) + lw t0, %tprel_lo(i)(a5) + sw t0, %tprel_lo(i)(a5) + ret + .size _start, .-_start + + .globl tls_ie + .p2align 2 +tls_ie: + nop + la.tls.ie a0, i + ret + .size tls_ie, .-tls_ie + + .section .tbss,"awT",@nobits + .type i,@object + .globl i + .p2align 3 +i: + .quad 0 + .size i, .-i + diff --git a/bolt/test/RISCV/tls-le-gnu-ld.test b/bolt/test/RISCV/tls-le-gnu-ld.test new file mode 100644 index 00000000000000..c3ff08b30ee60d --- /dev/null +++ b/bolt/test/RISCV/tls-le-gnu-ld.test @@ -0,0 +1,11 @@ +// This test checks that the binaries produces with GNU ld TLS le relaxation are +// properly processed by BOLT. GNU ld currently emits two non-standard +// relocations (R_RISCV_TPREL_I and R_RISCV_TPREL_S) in this case. + +// RUN: yaml2obj %p/Inputs/tls-le-gnu-ld.yaml &> %t.exe +// RUN: llvm-bolt %t.exe -o %t.bolt.exe --print-cfg --print-only=_start \ +// RUN: | FileCheck %s + +// CHECK: Binary Function "_start" after building cfg { +// CHECK: lw t0, 0(tp) +// CHECK-NEXT: sw t0, 0(tp) diff --git a/bolt/test/checkvma-large-section.test b/bolt/test/checkvma-large-section.test new file mode 100644 index 00000000000000..36a915951115e1 --- /dev/null +++ b/bolt/test/checkvma-large-section.test @@ -0,0 +1,35 @@ +# This test reproduces the issue with a section which ends at >4G address +REQUIRES: asserts +RUN: split-file %s %t +RUN: yaml2obj %t/yaml -o %t.exe --max-size=0 +RUN: llvm-bolt %t.exe -o /dev/null --allow-stripped +#--- yaml +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +ProgramHeaders: + - Type: PT_LOAD + FirstSec: .a + LastSec: .a + Align: 0x1000 + - Type: PT_LOAD + Flags: [ PF_R, PF_W ] + FirstSec: .large_sec + LastSec: .large_sec + VAddr: 0x4a0279a8 + - Type: PT_GNU_RELRO + Flags: [ PF_R ] +Sections: + - Name: .a + Type: SHT_PROGBITS + Content: 00 + AddressAlign: 0x1 + - Name: .large_sec + Type: SHT_PROGBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + Address: 0x4a0279a8 + Size: 0xdf8bb1a0 +... diff --git a/bolt/test/runtime/X86/gotoff-large-code-model-2.s b/bolt/test/runtime/X86/gotoff-large-code-model-2.s new file mode 100644 index 00000000000000..b7f7bf0527455e --- /dev/null +++ b/bolt/test/runtime/X86/gotoff-large-code-model-2.s @@ -0,0 +1,57 @@ +# A variation of gotoff-large-code-model.s that accesses GOT value +# with a slightly different code sequence. + +# REQUIRES: system-linux + +# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown \ +# RUN: %s -o %t.o +# RUN: %clang %cflags -no-pie %t.o -o %t.exe -Wl,-q + +# RUN: llvm-bolt %t.exe --funcs init_impls --lite \ +# RUN: -o %t.bolted +# RUN: %t.bolted | FileCheck %s + + .section .rodata.str1.1,"aMS",@progbits,1 +.LC2: + .string "Hello, world\n" + .text + .p2align 4 + .globl init_impls + .type init_impls, @function +init_impls: + .cfi_startproc + push %rbp + mov %rsp,%rbp + push %r15 + push %rbx + sub $0x8,%rsp + lea 1f(%rip),%rbx + # R_X86_64_GOTPC64 _GLOBAL_OFFSET_TABLE_+0x2 +1: movabsq $_GLOBAL_OFFSET_TABLE_, %r11 + add %r11,%rbx + # R_X86_64_GOTOFF64 .LC2 + movabs $.LC2@gotoff,%rax + lea (%rbx,%rax,1),%rax + mov %rax,%rdi + mov %rbx,%r15 + # R_X86_64_PLTOFF64 puts + movabs $puts@pltoff,%rax + add %rbx,%rax + call *%rax + add $0x8,%rsp + pop %rbx + pop %r15 + pop %rbp + retq + .cfi_endproc + .size init_impls, .-init_impls + + .globl main + .type main, @function + .p2align 4 +main: + callq init_impls + xorq %rax, %rax + ret + +# CHECK: Hello, world diff --git a/bolt/test/runtime/X86/gotoff-large-code-model.s b/bolt/test/runtime/X86/gotoff-large-code-model.s new file mode 100644 index 00000000000000..6ec61d2380c202 --- /dev/null +++ b/bolt/test/runtime/X86/gotoff-large-code-model.s @@ -0,0 +1,55 @@ +# REQUIRES: system-linux + +# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown \ +# RUN: %s -o %t.o +# RUN: %clang %cflags -no-pie %t.o -o %t.exe -Wl,-q + +# RUN: llvm-bolt %t.exe --funcs init_impls --lite \ +# RUN: -o %t.bolted +# RUN: %t.bolted | FileCheck %s + + .section .rodata.str1.1,"aMS",@progbits,1 +.LC2: + .string "Hello, world\n" + .text + .p2align 4 + .globl init_impls + .type init_impls, @function +init_impls: + .cfi_startproc + push %rbp + mov %rsp,%rbp + push %r15 + push %rbx + sub $0x8,%rsp +1: + lea 1b(%rip),%rbx + # R_X86_64_GOTPC64 _GLOBAL_OFFSET_TABLE_+0x9 + movabsq $_GLOBAL_OFFSET_TABLE_-1b, %r11 + add %r11,%rbx + # R_X86_64_GOTOFF64 .LC2 + movabs $.LC2@gotoff,%rax + lea (%rbx,%rax,1),%rax + mov %rax,%rdi + mov %rbx,%r15 + # R_X86_64_PLTOFF64 puts + movabs $puts@pltoff,%rax + add %rbx,%rax + call *%rax + add $0x8,%rsp + pop %rbx + pop %r15 + pop %rbp + retq + .cfi_endproc + .size init_impls, .-init_impls + + .globl main + .type main, @function + .p2align 4 +main: + callq init_impls + xorq %rax, %rax + ret + +# CHECK: Hello, world diff --git a/bolt/unittests/Core/MCPlusBuilder.cpp b/bolt/unittests/Core/MCPlusBuilder.cpp index 6519ff6934d1f8..b851c756e7960e 100644 --- a/bolt/unittests/Core/MCPlusBuilder.cpp +++ b/bolt/unittests/Core/MCPlusBuilder.cpp @@ -52,8 +52,9 @@ struct MCPlusBuilderTester : public testing::TestWithParam { BC = cantFail(BinaryContext::createBinaryContext( ObjFile.get(), true, DWARFContext::create(*ObjFile.get()))); ASSERT_FALSE(!BC); - BC->initializeTarget(std::unique_ptr(createMCPlusBuilder( - GetParam(), BC->MIA.get(), BC->MII.get(), BC->MRI.get()))); + BC->initializeTarget(std::unique_ptr( + createMCPlusBuilder(GetParam(), BC->MIA.get(), BC->MII.get(), + BC->MRI.get(), BC->STI.get()))); } void testRegAliases(Triple::ArchType Arch, uint64_t Register, diff --git a/clang-tools-extra/clang-change-namespace/tool/ClangChangeNamespace.cpp b/clang-tools-extra/clang-change-namespace/tool/ClangChangeNamespace.cpp index 5f30cbf8fb4773..22d26db0c11bcf 100644 --- a/clang-tools-extra/clang-change-namespace/tool/ClangChangeNamespace.cpp +++ b/clang-tools-extra/clang-change-namespace/tool/ClangChangeNamespace.cpp @@ -152,8 +152,8 @@ int main(int argc, const char **argv) { for (auto I = ChangedFiles.begin(), E = ChangedFiles.end(); I != E; ++I) { OS << " {\n"; OS << " \"FilePath\": \"" << *I << "\",\n"; - const auto Entry = FileMgr.getFile(*I); - auto ID = Sources.getOrCreateFileID(*Entry, SrcMgr::C_User); + auto Entry = llvm::cantFail(FileMgr.getFileRef(*I)); + auto ID = Sources.getOrCreateFileID(Entry, SrcMgr::C_User); std::string Content; llvm::raw_string_ostream ContentStream(Content); Rewrite.getEditBuffer(ID).write(ContentStream); @@ -170,9 +170,9 @@ int main(int argc, const char **argv) { } for (const auto &File : ChangedFiles) { - const auto Entry = FileMgr.getFile(File); + auto Entry = llvm::cantFail(FileMgr.getFileRef(File)); - auto ID = Sources.getOrCreateFileID(*Entry, SrcMgr::C_User); + auto ID = Sources.getOrCreateFileID(Entry, SrcMgr::C_User); outs() << "============== " << File << " ==============\n"; Rewrite.getEditBuffer(ID).write(llvm::outs()); outs() << "\n============================================\n"; diff --git a/clang-tools-extra/clang-move/Move.cpp b/clang-tools-extra/clang-move/Move.cpp index 94ba73ce9ad5a1..404acf55e3aa53 100644 --- a/clang-tools-extra/clang-move/Move.cpp +++ b/clang-tools-extra/clang-move/Move.cpp @@ -843,7 +843,7 @@ void ClangMoveTool::moveDeclsToNewFiles() { // Move all contents from OldFile to NewFile. void ClangMoveTool::moveAll(SourceManager &SM, StringRef OldFile, StringRef NewFile) { - auto FE = SM.getFileManager().getFile(makeAbsolutePath(OldFile)); + auto FE = SM.getFileManager().getOptionalFileRef(makeAbsolutePath(OldFile)); if (!FE) { llvm::errs() << "Failed to get file: " << OldFile << "\n"; return; diff --git a/clang-tools-extra/clang-reorder-fields/tool/ClangReorderFields.cpp b/clang-tools-extra/clang-reorder-fields/tool/ClangReorderFields.cpp index 375306765a52b6..5b77ee7b5738c6 100644 --- a/clang-tools-extra/clang-reorder-fields/tool/ClangReorderFields.cpp +++ b/clang-tools-extra/clang-reorder-fields/tool/ClangReorderFields.cpp @@ -84,8 +84,8 @@ int main(int argc, const char **argv) { Tool.applyAllReplacements(Rewrite); for (const auto &File : Files) { - auto Entry = FileMgr.getFile(File); - const auto ID = Sources.getOrCreateFileID(*Entry, SrcMgr::C_User); + auto Entry = llvm::cantFail(FileMgr.getFileRef(File)); + const auto ID = Sources.getOrCreateFileID(Entry, SrcMgr::C_User); Rewrite.getEditBuffer(ID).write(outs()); } diff --git a/clang-tools-extra/clang-tidy/ClangTidy.cpp b/clang-tools-extra/clang-tidy/ClangTidy.cpp index 695bfd6e2edf7e..4b1a67b6dd98a9 100644 --- a/clang-tools-extra/clang-tidy/ClangTidy.cpp +++ b/clang-tools-extra/clang-tidy/ClangTidy.cpp @@ -243,7 +243,7 @@ class ErrorReporter { if (FilePath.empty()) return {}; - auto File = SourceMgr.getFileManager().getFile(FilePath); + auto File = SourceMgr.getFileManager().getOptionalFileRef(FilePath); if (!File) return {}; diff --git a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp index c1e4437b88949b..b19a84f5dc2157 100644 --- a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp +++ b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp @@ -194,9 +194,9 @@ DiagnosticBuilder ClangTidyContext::diag( DiagnosticBuilder ClangTidyContext::diag(const tooling::Diagnostic &Error) { SourceManager &SM = DiagEngine->getSourceManager(); - llvm::ErrorOr File = - SM.getFileManager().getFile(Error.Message.FilePath); - FileID ID = SM.getOrCreateFileID(*File, SrcMgr::C_User); + FileManager &FM = SM.getFileManager(); + FileEntryRef File = llvm::cantFail(FM.getFileRef(Error.Message.FilePath)); + FileID ID = SM.getOrCreateFileID(File, SrcMgr::C_User); SourceLocation FileStartLoc = SM.getLocForStartOfFile(ID); SourceLocation Loc = FileStartLoc.getLocWithOffset( static_cast(Error.Message.FileOffset)); diff --git a/clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp b/clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp index fed19bdcc29143..e336ba1ee1fa72 100644 --- a/clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp +++ b/clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp @@ -30,6 +30,7 @@ #include "clang/Lex/Preprocessor.h" #include "clang/Tooling/Core/Replacement.h" #include "clang/Tooling/Inclusions/HeaderIncludes.h" +#include "clang/Tooling/Inclusions/StandardLibrary.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" @@ -97,9 +98,12 @@ bool IncludeCleanerCheck::shouldIgnore(const include_cleaner::Header &H) { return llvm::any_of(IgnoreHeadersRegex, [&H](const llvm::Regex &R) { switch (H.kind()) { case include_cleaner::Header::Standard: + // We don't trim angle brackets around standard library headers + // deliberately, so that they are only matched as , otherwise + // having just `.*/vector` might yield false positives. return R.match(H.standard().name()); case include_cleaner::Header::Verbatim: - return R.match(H.verbatim()); + return R.match(H.verbatim().trim("<>\"")); case include_cleaner::Header::Physical: return R.match(H.physical().getFileEntry().tryGetRealPathName()); } @@ -179,12 +183,14 @@ void IncludeCleanerCheck::check(const MatchFinder::MatchResult &Result) { if (getCurrentMainFile().endswith(PHeader)) continue; } - - if (llvm::none_of( - IgnoreHeadersRegex, - [Resolved = (*I.Resolved).getFileEntry().tryGetRealPathName()]( - const llvm::Regex &R) { return R.match(Resolved); })) - Unused.push_back(&I); + auto StdHeader = tooling::stdlib::Header::named( + I.quote(), PP->getLangOpts().CPlusPlus ? tooling::stdlib::Lang::CXX + : tooling::stdlib::Lang::C); + if (StdHeader && shouldIgnore(*StdHeader)) + continue; + if (shouldIgnore(*I.Resolved)) + continue; + Unused.push_back(&I); } llvm::StringRef Code = SM->getBufferData(SM->getMainFileID()); diff --git a/clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp index 22dc9e21cab9d5..e6293ed48bfddb 100644 --- a/clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp @@ -61,7 +61,8 @@ void UseUsingCheck::check(const MatchFinder::MatchResult &Result) { // before the typedef will be the nested one (PR#50990). Therefore, we also // keep track of the parent declaration, so that we can look up the last // TagDecl that is a sibling of the typedef in the AST. - LastTagDeclRanges[ParentDecl] = MatchedTagDecl->getSourceRange(); + if (MatchedTagDecl->isThisDeclarationADefinition()) + LastTagDeclRanges[ParentDecl] = MatchedTagDecl->getSourceRange(); return; } diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 8fc28c09034180..0ecf786e73bc41 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -249,14 +249,12 @@ Changes in existing checks - Improved :doc:`misc-const-correctness ` check to avoid false positive when using pointer to member function. - -- Improved :doc:`misc-include-cleaner - ` check by adding option - `DeduplicateFindings` to output one finding per symbol occurrence. - Improved :doc:`misc-include-cleaner - ` check to avoid fixes insert - same include header multiple times. + ` check by adding option + `DeduplicateFindings` to output one finding per symbol occurrence, avoid + inserting the same header multiple times, fix a bug where `IgnoreHeaders` + option won't work with verbatim/std headers. - Improved :doc:`misc-redundant-expression ` check to ignore @@ -279,8 +277,8 @@ Changes in existing checks fixes for reordering arguments. - Improved :doc:`modernize-use-using - ` check to fix function pointer - ``typedef`` correctly. + ` check to fix function pointer and + forward declared ``typedef`` correctly. - Improved :doc:`performance-faster-string-find ` check to properly escape diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-using.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-using.cpp index f7db0af6434ac4..422abee11a7196 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-using.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-using.cpp @@ -321,3 +321,7 @@ typedef bool (*ISSUE_65055_2)(int); // CHECK-MESSAGES: :[[@LINE-2]]:1: warning: use 'using' instead of 'typedef' // CHECK-FIXES: {{^}}using ISSUE_65055_1 = void (*)(int);{{$}} // CHECK-FIXES: {{^}}using ISSUE_65055_2 = bool (*)(int);{{$}} + +typedef class ISSUE_67529_1 *ISSUE_67529; +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef' +// CHECK-FIXES: using ISSUE_67529 = class ISSUE_67529_1 *; diff --git a/clang-tools-extra/unittests/clang-tidy/IncludeCleanerTest.cpp b/clang-tools-extra/unittests/clang-tidy/IncludeCleanerTest.cpp index 0c29b469b617b7..8da1051a860a8c 100644 --- a/clang-tools-extra/unittests/clang-tidy/IncludeCleanerTest.cpp +++ b/clang-tools-extra/unittests/clang-tidy/IncludeCleanerTest.cpp @@ -59,18 +59,20 @@ TEST(IncludeCleanerCheckTest, SuppressUnusedIncludes) { #include "foo/qux.h" #include "baz/qux/qux.h" #include +#include )"; const char *PostCode = R"( #include "bar.h" #include "foo/qux.h" #include +#include )"; std::vector Errors; ClangTidyOptions Opts; Opts.CheckOptions["IgnoreHeaders"] = llvm::StringRef{llvm::formatv( - "bar.h;{0};{1};vector", + "bar.h;{0};{1};vector;;", llvm::Regex::escape(appendPathFileSystemIndependent({"foo", "qux.h"})), llvm::Regex::escape(appendPathFileSystemIndependent({"baz", "qux"})))}; EXPECT_EQ( @@ -79,6 +81,7 @@ TEST(IncludeCleanerCheckTest, SuppressUnusedIncludes) { PreCode, &Errors, "file.cpp", std::nullopt, Opts, {{"bar.h", "#pragma once"}, {"vector", "#pragma once"}, + {"list", "#pragma once"}, {appendPathFileSystemIndependent({"foo", "qux.h"}), "#pragma once"}, {appendPathFileSystemIndependent({"baz", "qux", "qux.h"}), "#pragma once"}})); @@ -163,11 +166,13 @@ TEST(IncludeCleanerCheckTest, SuppressMissingIncludes) { int BarResult = bar(); int BazResult = baz(); int QuxResult = qux(); +int PrivResult = test(); +std::vector x; )"; ClangTidyOptions Opts; Opts.CheckOptions["IgnoreHeaders"] = llvm::StringRef{ - "baz.h;" + + "public.h;;baz.h;" + llvm::Regex::escape(appendPathFileSystemIndependent({"foo", "qux.h"}))}; std::vector Errors; EXPECT_EQ(PreCode, runCheckOnCode( @@ -175,18 +180,23 @@ int QuxResult = qux(); {{"bar.h", R"(#pragma once #include "baz.h" #include "foo/qux.h" + #include "private.h" int bar(); + namespace std { struct vector {}; } )"}, {"baz.h", R"(#pragma once int baz(); )"}, + {"private.h", R"(#pragma once + // IWYU pragma: private, include "public.h" + int test(); + )"}, {appendPathFileSystemIndependent({"foo", "qux.h"}), R"(#pragma once int qux(); )"}})); } - TEST(IncludeCleanerCheckTest, MultipleTimeMissingInclude) { const char *PreCode = R"( #include "bar.h" diff --git a/clang/cmake/caches/CrossWinToARMLinux.cmake b/clang/cmake/caches/CrossWinToARMLinux.cmake index fd341b182fd656..2a0953af53fadd 100644 --- a/clang/cmake/caches/CrossWinToARMLinux.cmake +++ b/clang/cmake/caches/CrossWinToARMLinux.cmake @@ -151,6 +151,10 @@ set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_LIBCXX_ENABLE_NEW_DELETE_DEFINITIONS find_package(Python3 COMPONENTS Interpreter) +set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_LIBUNWIND_TEST_PARAMS_default "${RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_TEST_PARAMS}") +set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_LIBCXXABI_TEST_PARAMS_default "${RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_TEST_PARAMS}") +set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_LIBCXX_TEST_PARAMS_default "${RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_TEST_PARAMS}") + # Remote test configuration. if(DEFINED REMOTE_TEST_HOST) # Allow override with the custom values. @@ -162,11 +166,15 @@ if(DEFINED REMOTE_TEST_HOST) "\\\"${Python3_EXECUTABLE}\\\" \\\"${LLVM_PROJECT_DIR}/llvm/utils/remote-exec.py\\\" --host=${REMOTE_TEST_USER}@${REMOTE_TEST_HOST}" CACHE STRING "") - set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_LIBUNWIND_TEST_PARAMS "${RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_TEST_PARAMS} 'executor=${DEFAULT_TEST_EXECUTOR}'" CACHE STRING "") - set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_LIBCXXABI_TEST_PARAMS "${RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_TEST_PARAMS} 'executor=${DEFAULT_TEST_EXECUTOR}'" CACHE STRING "") - set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_LIBCXX_TEST_PARAMS "${RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_TEST_PARAMS} 'executor=${DEFAULT_TEST_EXECUTOR}'" CACHE STRING "") + list(APPEND RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_LIBUNWIND_TEST_PARAMS_default "executor=${DEFAULT_TEST_EXECUTOR}") + list(APPEND RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_LIBCXXABI_TEST_PARAMS_default "executor=${DEFAULT_TEST_EXECUTOR}") + list(APPEND RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_LIBCXX_TEST_PARAMS_default "executor=${DEFAULT_TEST_EXECUTOR}") endif() +set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_LIBUNWIND_TEST_PARAMS "${RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_LIBUNWIND_TEST_PARAMS_default}" CACHE INTERNAL "") +set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_LIBCXXABI_TEST_PARAMS "${RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_LIBCXXABI_TEST_PARAMS_default}" CACHE INTERNAL "") +set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_LIBCXX_TEST_PARAMS "${RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_LIBCXX_TEST_PARAMS_default}" CACHE INTERNAL "") + set(LLVM_INSTALL_TOOLCHAIN_ONLY ON CACHE BOOL "") set(LLVM_TOOLCHAIN_TOOLS llvm-ar diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst index 5ebb8c82b30495..c5c72c68ee9b80 100644 --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -5730,7 +5730,7 @@ Examples ======== A style similar to the `Linux Kernel style -`_: +`_: .. code-block:: yaml diff --git a/clang/docs/ClangOffloadBundler.rst b/clang/docs/ClangOffloadBundler.rst index d08bf4b97781fa..1e21d3e7264d5c 100644 --- a/clang/docs/ClangOffloadBundler.rst +++ b/clang/docs/ClangOffloadBundler.rst @@ -309,3 +309,30 @@ target by comparing bundle ID's. Two bundle ID's are considered compatible if: * Their offload kind are the same * Their target triple are the same * Their GPUArch are the same + +Compression and Decompression +============================= + +``clang-offload-bundler`` provides features to compress and decompress the full +bundle, leveraging inherent redundancies within the bundle entries. Use the +`-compress` command-line option to enable this compression capability. + +The compressed offload bundle begins with a header followed by the compressed binary data: + +- **Magic Number (4 bytes)**: + This is a unique identifier to distinguish compressed offload bundles. The value is the string 'CCOB' (Compressed Clang Offload Bundle). + +- **Version Number (16-bit unsigned int)**: + This denotes the version of the compressed offload bundle format. The current version is `1`. + +- **Compression Method (16-bit unsigned int)**: + This field indicates the compression method used. The value corresponds to either `zlib` or `zstd`, represented as a 16-bit unsigned integer cast from the LLVM compression enumeration. + +- **Uncompressed Binary Size (32-bit unsigned int)**: + This is the size (in bytes) of the binary data before it was compressed. + +- **Hash (64-bit unsigned int)**: + This is a 64-bit truncated MD5 hash of the uncompressed binary data. It serves for verification and caching purposes. + +- **Compressed Data**: + The actual compressed binary data follows the header. Its size can be inferred from the total size of the file minus the header size. diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 8f5a67e14c9aba..ae67a783c2fa2d 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -91,6 +91,11 @@ C++20 Feature Support C++23 Feature Support ^^^^^^^^^^^^^^^^^^^^^ +- Implemented `P0847R7: Deducing this `_. Some related core issues were also + implemented (`CWG2553 `_, `CWG2554 `_, + `CWG2653 `_, `CWG2687 `_). Because the + support for this feature is still experimental, the feature test macro ``__cpp_explicit_this_parameter`` + was not set in this version. C++2c Feature Support ^^^^^^^^^^^^^^^^^^^^^ @@ -127,6 +132,11 @@ C Language Changes - ``structs``, ``unions``, and ``arrays`` that are const may now be used as constant expressions. This change is more consistent with the behavior of GCC. +- 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 ^^^^^^^^^^^^^^^^^^^ @@ -135,12 +145,20 @@ C23 Feature Support previous placeholder value. Clang continues to accept ``-std=c2x`` and ``-std=gnu2x`` as aliases for C23 and GNU C23, respectively. - Clang now supports `requires c23` for module maps. +- Clang now supports ``N3007 Type inference for object definitions``. Non-comprehensive list of changes in this release ------------------------------------------------- New Compiler Flags ------------------ +* ``-fverify-intermediate-code`` and its complement ``-fno-verify-intermediate-code``. + Enables or disables verification of the generated LLVM IR. + Users can pass this to turn on extra verification to catch certain types of + compiler bugs at the cost of extra compile time. + Since enabling the verifier adds a non-trivial cost of a few percent impact on + build times, it's disabled by default, unless your LLVM distribution itself is + compiled with runtime checks enabled. Deprecated Compiler Flags ------------------------- @@ -208,6 +226,50 @@ Improvements to Clang's diagnostics (`#54678: `_). - Clang now prints its 'note' diagnostic in cyan instead of black, to be more compatible with terminals with dark background colors. This is also more consistent with GCC. +- The fix-it emitted by ``-Wformat`` for scoped enumerations now take the + enumeration's underlying type into account instead of suggesting a type just + based on the format string specifier being used. +- Clang now displays an improved diagnostic and a note when a defaulted special + member is marked ``constexpr`` in a class with a virtual base class + (`#64843: `_). +- ``-Wfixed-enum-extension`` and ``-Wmicrosoft-fixed-enum`` diagnostics are no longer + emitted when building as C23, since C23 standardizes support for enums with a + fixed underlying type. +- When describing the failure of static assertion of `==` expression, clang prints the integer + representation of the value as well as its character representation when + the user-provided expression is of character type. If the character is + non-printable, clang now shows the escpaed character. + Clang also prints multi-byte characters if the user-provided expression + is of multi-byte character type. + + *Example Code*: + + .. code-block:: c++ + + static_assert("A\n"[1] == U'🌍'); + + *BEFORE*: + + .. code-block:: text + + source:1:15: error: static assertion failed due to requirement '"A\n"[1] == U'\U0001f30d'' + 1 | static_assert("A\n"[1] == U'🌍'); + | ^~~~~~~~~~~~~~~~~ + source:1:24: note: expression evaluates to '' + ' == 127757' + 1 | static_assert("A\n"[1] == U'🌍'); + | ~~~~~~~~~^~~~~~~~ + + *AFTER*: + + .. code-block:: text + + source:1:15: error: static assertion failed due to requirement '"A\n"[1] == U'\U0001f30d'' + 1 | static_assert("A\n"[1] == U'🌍'); + | ^~~~~~~~~~~~~~~~~ + source:1:24: note: expression evaluates to ''\n' (0x0A, 10) == U'🌍' (0x1F30D, 127757)' + 1 | static_assert("A\n"[1] == U'🌍'); + | ~~~~~~~~~^~~~~~~~ Bug Fixes in This Version ------------------------- @@ -274,6 +336,15 @@ Bug Fixes in This Version Fixes (`#67603 `_) - Fixes a crash caused by a multidimensional array being captured by a lambda (`#67722 `_). +- Fixes a crash when instantiating a lambda with requires clause. + (`#64462 `_) +- Fixes a regression where the ``UserDefinedLiteral`` was not properly preserved + while evaluating consteval functions. (`#63898 `_). +- Fix a crash when evaluating value-dependent structured binding + variables at compile time. + Fixes (`#67690 `_) +- Fixes a ``clang-17`` regression where ``LLVM_UNREACHABLE_OPTIMIZE=OFF`` + cannot be used with ``Release`` mode builds. (`#68237 `_). Bug Fixes to Compiler Builtins ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -366,6 +437,9 @@ Bug Fixes to C++ Support - Fix crash caused by a spaceship operator returning a comparision category by reference. Fixes: (`#64162 `_) +- Fix a crash when calling a consteval function in an expression used as + the size of an array. + (`#65520 `_) - Clang no longer tries to capture non-odr-used variables that appear in the enclosing expression of a lambda expression with a noexcept specifier. @@ -378,6 +452,15 @@ Bug Fixes to C++ Support - Fixed a bug causing destructors of constant-evaluated structured bindings initialized by array elements to be called in the wrong evaluation context. +- Fix crash where ill-formed code was being treated as a deduction guide and + we now produce a diagnostic. Fixes: + (`#65522 `_) + +- Fixed a bug where clang incorrectly considered implicitly generated deduction + guides from a non-templated constructor and a templated constructor as ambiguous, + rather than prefer the non-templated constructor as specified in + [standard.group]p3. + Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ - Fixed an import failure of recursive friend class template. @@ -398,6 +481,8 @@ Miscellaneous Clang Crashes Fixed `Issue 64065 `_ - Fixed a crash when check array access on zero-length element. `Issue 64564 `_ +- Fixed a crash when an ObjC ivar has an invalid type. See + (`#68001 `_) Target Specific Changes ----------------------- @@ -533,6 +618,14 @@ Static Analyzer Read the PR for the details. (`#66086 `_) +- A few crashes have been found and fixed using randomized testing related + to the use of ``_BitInt()`` in tidy checks and in clang analysis. See + `#67212 `_, + `#66782 `_, + `#65889 `_, + `#65888 `_, and + `#65887 `_ + .. _release-notes-sanitizers: Sanitizers diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 4ee32c76a95d8e..8ad0514ee2ce22 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -195,20 +195,25 @@ class ASTContext : public RefCountedBase { ConstantArrayTypes; mutable llvm::FoldingSet IncompleteArrayTypes; mutable std::vector VariableArrayTypes; - mutable llvm::FoldingSet DependentSizedArrayTypes; - mutable llvm::FoldingSet - DependentSizedExtVectorTypes; - mutable llvm::FoldingSet + mutable llvm::ContextualFoldingSet + DependentSizedArrayTypes; + mutable llvm::ContextualFoldingSet + DependentSizedExtVectorTypes; + mutable llvm::ContextualFoldingSet DependentAddressSpaceTypes; mutable llvm::FoldingSet VectorTypes; - mutable llvm::FoldingSet DependentVectorTypes; + mutable llvm::ContextualFoldingSet + DependentVectorTypes; mutable llvm::FoldingSet MatrixTypes; - mutable llvm::FoldingSet DependentSizedMatrixTypes; + mutable llvm::ContextualFoldingSet + DependentSizedMatrixTypes; mutable llvm::FoldingSet FunctionNoProtoTypes; mutable llvm::ContextualFoldingSet FunctionProtoTypes; - mutable llvm::FoldingSet DependentTypeOfExprTypes; - mutable llvm::FoldingSet DependentDecltypeTypes; + mutable llvm::ContextualFoldingSet + DependentTypeOfExprTypes; + mutable llvm::ContextualFoldingSet + DependentDecltypeTypes; mutable llvm::FoldingSet TemplateTypeParmTypes; mutable llvm::FoldingSet ObjCTypeParamTypes; mutable llvm::FoldingSet @@ -238,7 +243,8 @@ class ASTContext : public RefCountedBase { mutable llvm::FoldingSet AttributedTypes; mutable llvm::FoldingSet PipeTypes; mutable llvm::FoldingSet BitIntTypes; - mutable llvm::FoldingSet DependentBitIntTypes; + mutable llvm::ContextualFoldingSet + DependentBitIntTypes; llvm::FoldingSet BTFTagAttributedTypes; mutable llvm::FoldingSet QualifiedTemplateNames; diff --git a/clang/include/clang/AST/ASTLambda.h b/clang/include/clang/AST/ASTLambda.h index 230e0c848610fe..646cb574847fe2 100644 --- a/clang/include/clang/AST/ASTLambda.h +++ b/clang/include/clang/AST/ASTLambda.h @@ -35,6 +35,21 @@ inline bool isLambdaCallOperator(const DeclContext *DC) { return isLambdaCallOperator(cast(DC)); } +inline bool isLambdaCallWithExplicitObjectParameter(const DeclContext *DC) { + return isLambdaCallOperator(DC) && + cast(DC)->isExplicitObjectMemberFunction(); +} + +inline bool isLambdaCallWithImplicitObjectParameter(const DeclContext *DC) { + return isLambdaCallOperator(DC) && + // FIXME: Checking for a null type is not great + // but lambdas with invalid captures or whose closure parameter list + // have not fully been parsed may have a call operator whose type is + // null. + !cast(DC)->getType().isNull() && + !cast(DC)->isExplicitObjectMemberFunction(); +} + inline bool isGenericLambdaCallOperatorSpecialization(const CXXMethodDecl *MD) { if (!MD) return false; const CXXRecordDecl *LambdaClass = MD->getParent(); diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index c51b33c9e594a8..2830861add39e7 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -1809,6 +1809,18 @@ class ParmVarDecl : public VarDecl { ParmVarDeclBits.IsKNRPromoted = promoted; } + bool isExplicitObjectParameter() const { + return ExplicitObjectParameterIntroducerLoc.isValid(); + } + + void setExplicitObjectParameterLoc(SourceLocation Loc) { + ExplicitObjectParameterIntroducerLoc = Loc; + } + + SourceLocation getExplicitObjectParamThisLoc() const { + return ExplicitObjectParameterIntroducerLoc; + } + Expr *getDefaultArg(); const Expr *getDefaultArg() const { return const_cast(this)->getDefaultArg(); @@ -1875,7 +1887,10 @@ class ParmVarDecl : public VarDecl { static bool classofKind(Kind K) { return K == ParmVar; } private: + friend class ASTDeclReader; + enum { ParameterIndexSentinel = (1 << NumParameterIndexBits) - 1 }; + SourceLocation ExplicitObjectParameterIntroducerLoc; void setParameterIndex(unsigned parameterIndex) { if (parameterIndex >= ParameterIndexSentinel) { @@ -2640,6 +2655,23 @@ class FunctionDecl : public DeclaratorDecl, /// parameters have default arguments (in C++). unsigned getMinRequiredArguments() const; + /// Returns the minimum number of non-object arguments needed to call this + /// function. This produces the same value as getMinRequiredArguments except + /// it does not count the explicit object argument, if any. + unsigned getMinRequiredExplicitArguments() const; + + bool hasCXXExplicitFunctionObjectParameter() const; + + unsigned getNumNonObjectParams() const; + + const ParmVarDecl *getNonObjectParameter(unsigned I) const { + return getParamDecl(hasCXXExplicitFunctionObjectParameter() ? I + 1 : I); + } + + ParmVarDecl *getNonObjectParameter(unsigned I) { + return getParamDecl(hasCXXExplicitFunctionObjectParameter() ? I + 1 : I); + } + /// Determine whether this function has a single parameter, or multiple /// parameters where all but the first have default arguments. /// @@ -4272,6 +4304,30 @@ class RecordDecl : public TagDecl { return field_begin() == field_end(); } + FieldDecl *getLastField() { + FieldDecl *FD = nullptr; + for (FieldDecl *Field : fields()) + FD = Field; + return FD; + } + const FieldDecl *getLastField() const { + return const_cast(this)->getLastField(); + } + + template + const FieldDecl *findFieldIf(Functor &Pred) const { + for (const Decl *D : decls()) { + if (const auto *FD = dyn_cast(D); FD && Pred(FD)) + return FD; + + if (const auto *RD = dyn_cast(D)) + if (const FieldDecl *FD = RD->findFieldIf(Pred)) + return FD; + } + + return nullptr; + } + /// Note that the definition of this type is now complete. virtual void completeDefinition(); diff --git a/clang/include/clang/AST/DeclBase.h b/clang/include/clang/AST/DeclBase.h index 12137387b676a7..d383e46e22e16f 100644 --- a/clang/include/clang/AST/DeclBase.h +++ b/clang/include/clang/AST/DeclBase.h @@ -18,6 +18,7 @@ #include "clang/AST/DeclarationName.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" @@ -477,6 +478,15 @@ class alignas(8) Decl { // 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 afec8150c2c9c6..aa3e3322faa42e 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -2061,6 +2061,17 @@ class CXXMethodDecl : public FunctionDecl { bool isStatic() const; bool isInstance() const { return !isStatic(); } + /// [C++2b][dcl.fct]/p7 + /// An explicit object member function is a non-static + /// member function with an explicit object parameter. e.g., + /// void func(this SomeType); + bool isExplicitObjectMemberFunction() const; + + /// [C++2b][dcl.fct]/p7 + /// An implicit object member function is a non-static + /// member function without an explicit object parameter. + bool isImplicitObjectMemberFunction() const; + /// Returns true if the given operator is implicitly static in a record /// context. static bool isStaticOverloadedOperator(OverloadedOperatorKind OOK) { @@ -2169,14 +2180,19 @@ class CXXMethodDecl : public FunctionDecl { /// Return the type of the object pointed by \c this. /// /// See getThisType() for usage restriction. - QualType getThisObjectType() const; + + QualType getFunctionObjectParameterReferenceType() const; + QualType getFunctionObjectParameterType() const { + return getFunctionObjectParameterReferenceType().getNonReferenceType(); + } + + unsigned getNumExplicitParams() const { + return getNumParams() - (isExplicitObjectMemberFunction() ? 1 : 0); + } static QualType getThisType(const FunctionProtoType *FPT, const CXXRecordDecl *Decl); - static QualType getThisObjectType(const FunctionProtoType *FPT, - const CXXRecordDecl *Decl); - Qualifiers getMethodQualifiers() const { return getType()->castAs()->getMethodQuals(); } diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index fcda738ef4c552..b69c616b009036 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -1449,6 +1449,16 @@ class DeclRefExpr final DeclRefExprBits.IsImmediateEscalating = Set; } + bool isCapturedByCopyInLambdaWithExplicitObjectParameter() const { + return DeclRefExprBits.CapturedByCopyInLambdaWithExplicitObjectParameter; + } + + void setCapturedByCopyInLambdaWithExplicitObjectParameter( + bool Set, const ASTContext &Context) { + DeclRefExprBits.CapturedByCopyInLambdaWithExplicitObjectParameter = Set; + setDependence(computeDependence(this, Context)); + } + static bool classof(const Stmt *T) { return T->getStmtClass() == DeclRefExprClass; } diff --git a/clang/include/clang/AST/Mangle.h b/clang/include/clang/AST/Mangle.h index c04bcc7f01cb4e..e586b0cec43dfd 100644 --- a/clang/include/clang/AST/Mangle.h +++ b/clang/include/clang/AST/Mangle.h @@ -178,8 +178,8 @@ class MangleContext { /// or type uniquing. /// TODO: Extend this to internal types by generating names that are unique /// across translation units so it can be used with LTO. - virtual void mangleTypeName(QualType T, raw_ostream &, - bool NormalizeIntegers = false) = 0; + virtual void mangleCanonicalTypeName(QualType T, raw_ostream &, + bool NormalizeIntegers = false) = 0; /// @} }; diff --git a/clang/include/clang/AST/OpenMPClause.h b/clang/include/clang/AST/OpenMPClause.h index 31ae3d42e232fc..eeeca1998f9fa9 100644 --- a/clang/include/clang/AST/OpenMPClause.h +++ b/clang/include/clang/AST/OpenMPClause.h @@ -9220,6 +9220,27 @@ class OMPXAttributeClause } }; +/// This represents 'ompx_bare' clause in the '#pragma omp target teams ...' +/// directive. +/// +/// \code +/// #pragma omp target teams ompx_bare +/// \endcode +/// In this example directive '#pragma omp target teams' has a 'ompx_bare' +/// clause. +class OMPXBareClause : public OMPNoChildClause { +public: + /// Build 'ompx_bare' clause. + /// + /// \param StartLoc Starting location of the clause. + /// \param EndLoc Ending location of the clause. + OMPXBareClause(SourceLocation StartLoc, SourceLocation EndLoc) + : OMPNoChildClause(StartLoc, EndLoc) {} + + /// Build an empty clause. + OMPXBareClause() = default; +}; + } // namespace clang #endif // LLVM_CLANG_AST_OPENMPCLAUSE_H diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index d4146d52893ffb..298489e7d4fc41 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -3890,6 +3890,11 @@ bool RecursiveASTVisitor::VisitOMPXAttributeClause( return true; } +template +bool RecursiveASTVisitor::VisitOMPXBareClause(OMPXBareClause *C) { + return true; +} + // FIXME: look at the following tricky-seeming exprs to see if we // need to recurse on anything. These are ones that have methods // returning decls or qualtypes or nestednamespecifier -- though I'm diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h index 87ffebc00d7b79..69a764480ed568 100644 --- a/clang/include/clang/AST/Stmt.h +++ b/clang/include/clang/AST/Stmt.h @@ -383,6 +383,7 @@ class alignas(void *) Stmt { unsigned HasFoundDecl : 1; unsigned HadMultipleCandidates : 1; unsigned RefersToEnclosingVariableOrCapture : 1; + unsigned CapturedByCopyInLambdaWithExplicitObjectParameter : 1; unsigned NonOdrUseReason : 2; unsigned IsImmediateEscalating : 1; diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index 4799f89db82fa7..a78d8f60462b23 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -3289,8 +3289,6 @@ class VariableArrayType : public ArrayType { class DependentSizedArrayType : public ArrayType { friend class ASTContext; // ASTContext creates these. - const ASTContext &Context; - /// An assignment expression that will instantiate to the /// size of the array. /// @@ -3301,8 +3299,8 @@ class DependentSizedArrayType : public ArrayType { /// The range spanned by the left and right array brackets. SourceRange Brackets; - DependentSizedArrayType(const ASTContext &Context, QualType et, QualType can, - Expr *e, ArraySizeModifier sm, unsigned tq, + DependentSizedArrayType(QualType et, QualType can, Expr *e, + ArraySizeModifier sm, unsigned tq, SourceRange brackets); public: @@ -3325,7 +3323,7 @@ class DependentSizedArrayType : public ArrayType { return T->getTypeClass() == DependentSizedArray; } - void Profile(llvm::FoldingSetNodeID &ID) { + void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) { Profile(ID, Context, getElementType(), getSizeModifier(), getIndexTypeCVRQualifiers(), getSizeExpr()); } @@ -3349,14 +3347,12 @@ class DependentSizedArrayType : public ArrayType { class DependentAddressSpaceType : public Type, public llvm::FoldingSetNode { friend class ASTContext; - const ASTContext &Context; Expr *AddrSpaceExpr; QualType PointeeType; SourceLocation loc; - DependentAddressSpaceType(const ASTContext &Context, QualType PointeeType, - QualType can, Expr *AddrSpaceExpr, - SourceLocation loc); + DependentAddressSpaceType(QualType PointeeType, QualType can, + Expr *AddrSpaceExpr, SourceLocation loc); public: Expr *getAddrSpaceExpr() const { return AddrSpaceExpr; } @@ -3370,7 +3366,7 @@ class DependentAddressSpaceType : public Type, public llvm::FoldingSetNode { return T->getTypeClass() == DependentAddressSpace; } - void Profile(llvm::FoldingSetNodeID &ID) { + void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) { Profile(ID, Context, getPointeeType(), getAddrSpaceExpr()); } @@ -3391,7 +3387,6 @@ class DependentAddressSpaceType : public Type, public llvm::FoldingSetNode { class DependentSizedExtVectorType : public Type, public llvm::FoldingSetNode { friend class ASTContext; - const ASTContext &Context; Expr *SizeExpr; /// The element type of the array. @@ -3399,8 +3394,8 @@ class DependentSizedExtVectorType : public Type, public llvm::FoldingSetNode { SourceLocation loc; - DependentSizedExtVectorType(const ASTContext &Context, QualType ElementType, - QualType can, Expr *SizeExpr, SourceLocation loc); + DependentSizedExtVectorType(QualType ElementType, QualType can, + Expr *SizeExpr, SourceLocation loc); public: Expr *getSizeExpr() const { return SizeExpr; } @@ -3414,7 +3409,7 @@ class DependentSizedExtVectorType : public Type, public llvm::FoldingSetNode { return T->getTypeClass() == DependentSizedExtVector; } - void Profile(llvm::FoldingSetNodeID &ID) { + void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) { Profile(ID, Context, getElementType(), getSizeExpr()); } @@ -3513,14 +3508,12 @@ class VectorType : public Type, public llvm::FoldingSetNode { class DependentVectorType : public Type, public llvm::FoldingSetNode { friend class ASTContext; - const ASTContext &Context; QualType ElementType; Expr *SizeExpr; SourceLocation Loc; - DependentVectorType(const ASTContext &Context, QualType ElementType, - QualType CanonType, Expr *SizeExpr, - SourceLocation Loc, VectorType::VectorKind vecKind); + DependentVectorType(QualType ElementType, QualType CanonType, Expr *SizeExpr, + SourceLocation Loc, VectorType::VectorKind vecKind); public: Expr *getSizeExpr() const { return SizeExpr; } @@ -3537,7 +3530,7 @@ class DependentVectorType : public Type, public llvm::FoldingSetNode { return T->getTypeClass() == DependentVector; } - void Profile(llvm::FoldingSetNodeID &ID) { + void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) { Profile(ID, Context, getElementType(), getSizeExpr(), getVectorKind()); } @@ -3719,15 +3712,13 @@ class ConstantMatrixType final : public MatrixType { class DependentSizedMatrixType final : public MatrixType { friend class ASTContext; - const ASTContext &Context; Expr *RowExpr; Expr *ColumnExpr; SourceLocation loc; - DependentSizedMatrixType(const ASTContext &Context, QualType ElementType, - QualType CanonicalType, Expr *RowExpr, - Expr *ColumnExpr, SourceLocation loc); + DependentSizedMatrixType(QualType ElementType, QualType CanonicalType, + Expr *RowExpr, Expr *ColumnExpr, SourceLocation loc); public: Expr *getRowExpr() const { return RowExpr; } @@ -3738,7 +3729,7 @@ class DependentSizedMatrixType final : public MatrixType { return T->getTypeClass() == DependentSizedMatrix; } - void Profile(llvm::FoldingSetNodeID &ID) { + void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) { Profile(ID, Context, getElementType(), getRowExpr(), getColumnExpr()); } @@ -4749,15 +4740,12 @@ class TypeOfExprType : public Type { /// This class is used internally by the ASTContext to manage /// canonical, dependent types, only. Clients will only see instances /// of this class via TypeOfExprType nodes. -class DependentTypeOfExprType - : public TypeOfExprType, public llvm::FoldingSetNode { - const ASTContext &Context; - +class DependentTypeOfExprType : public TypeOfExprType, + public llvm::FoldingSetNode { public: - DependentTypeOfExprType(const ASTContext &Context, Expr *E, TypeOfKind Kind) - : TypeOfExprType(E, Kind), Context(Context) {} + DependentTypeOfExprType(Expr *E, TypeOfKind Kind) : TypeOfExprType(E, Kind) {} - void Profile(llvm::FoldingSetNodeID &ID) { + void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) { Profile(ID, Context, getUnderlyingExpr(), getKind() == TypeOfKind::Unqualified); } @@ -4833,12 +4821,10 @@ class DecltypeType : public Type { /// canonical, dependent types, only. Clients will only see instances /// of this class via DecltypeType nodes. class DependentDecltypeType : public DecltypeType, public llvm::FoldingSetNode { - const ASTContext &Context; - public: - DependentDecltypeType(const ASTContext &Context, Expr *E); + DependentDecltypeType(Expr *E, QualType UnderlyingTpe); - void Profile(llvm::FoldingSetNodeID &ID) { + void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) { Profile(ID, Context, getUnderlyingExpr()); } @@ -6657,12 +6643,10 @@ class BitIntType final : public Type, public llvm::FoldingSetNode { class DependentBitIntType final : public Type, public llvm::FoldingSetNode { friend class ASTContext; - const ASTContext &Context; llvm::PointerIntPair ExprAndUnsigned; protected: - DependentBitIntType(const ASTContext &Context, bool IsUnsigned, - Expr *NumBits); + DependentBitIntType(bool IsUnsigned, Expr *NumBits); public: bool isUnsigned() const; @@ -6672,7 +6656,7 @@ class DependentBitIntType final : public Type, public llvm::FoldingSetNode { bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } - void Profile(llvm::FoldingSetNodeID &ID) { + void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) { Profile(ID, Context, isUnsigned(), getNumBitsExpr()); } static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, diff --git a/clang/include/clang/Analysis/Analyses/ThreadSafety.h b/clang/include/clang/Analysis/Analyses/ThreadSafety.h index 1808d1d71e05d2..0866b09bab2995 100644 --- a/clang/include/clang/Analysis/Analyses/ThreadSafety.h +++ b/clang/include/clang/Analysis/Analyses/ThreadSafety.h @@ -47,7 +47,13 @@ enum ProtectedOperationKind { POK_PassByRef, /// Passing a pt-guarded variable by reference. - POK_PtPassByRef + POK_PtPassByRef, + + /// Returning a guarded variable by reference. + POK_ReturnByRef, + + /// Returning a pt-guarded variable by reference. + POK_PtReturnByRef, }; /// This enum distinguishes between different kinds of lock actions. For diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 7a6ec77ae84b15..5c9eb7b8a98103 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -4246,3 +4246,21 @@ def AvailableOnlyInDefaultEvalMethod : InheritableAttr { let Subjects = SubjectList<[TypedefName], ErrorDiag>; let Documentation = [Undocumented]; } + +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 8d928dcc146b25..9f9991bdae3615 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -7275,3 +7275,69 @@ relative ordering of values is important. For example: attribute, they default to the value ``65535``. }]; } + +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 in +the same structure 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. + +For example, the following code: + +.. code-block:: c + + struct bar; + + struct foo { + size_t count; + char other; + struct bar *array[] __attribute__((counted_by(count))); + }; + +specifies that the flexible array member ``array`` has the number of elements +allocated for it stored in ``count``. This establishes a relationship between +``array`` and ``count``. Specifically, ``p->array`` must have at least +``p->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``, breaking 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) { + p->count += SIZE_INCR + 1; /* 'count' is now larger than the number of elements of 'array'. */ + p->array[index] = 0; /* the sanitizer can't properly check if this is an out-of-bounds access. */ + } + + }]; +} diff --git a/clang/include/clang/Basic/BuiltinsX86.def b/clang/include/clang/Basic/BuiltinsX86.def index 6bbbc4bbdd75c6..e4802f8ab1c156 100644 --- a/clang/include/clang/Basic/BuiltinsX86.def +++ b/clang/include/clang/Basic/BuiltinsX86.def @@ -233,8 +233,6 @@ TARGET_BUILTIN(__builtin_ia32_minps, "V4fV4fV4f", "ncV:128:", "sse") TARGET_BUILTIN(__builtin_ia32_maxps, "V4fV4fV4f", "ncV:128:", "sse") TARGET_BUILTIN(__builtin_ia32_minss, "V4fV4fV4f", "ncV:128:", "sse") TARGET_BUILTIN(__builtin_ia32_maxss, "V4fV4fV4f", "ncV:128:", "sse") -TARGET_BUILTIN(__builtin_ia32_cmpps, "V4fV4fV4fIc", "ncV:128:", "sse") -TARGET_BUILTIN(__builtin_ia32_cmpss, "V4fV4fV4fIc", "ncV:128:", "sse") TARGET_BUILTIN(__builtin_ia32_cmpeqpd, "V2dV2dV2d", "ncV:128:", "sse2") TARGET_BUILTIN(__builtin_ia32_cmpltpd, "V2dV2dV2d", "ncV:128:", "sse2") @@ -252,8 +250,6 @@ TARGET_BUILTIN(__builtin_ia32_cmpneqsd, "V2dV2dV2d", "ncV:128:", "sse2") TARGET_BUILTIN(__builtin_ia32_cmpnltsd, "V2dV2dV2d", "ncV:128:", "sse2") TARGET_BUILTIN(__builtin_ia32_cmpnlesd, "V2dV2dV2d", "ncV:128:", "sse2") TARGET_BUILTIN(__builtin_ia32_cmpordsd, "V2dV2dV2d", "ncV:128:", "sse2") -TARGET_BUILTIN(__builtin_ia32_cmpsd, "V2dV2dV2dIc", "ncV:128:", "sse2") -TARGET_BUILTIN(__builtin_ia32_cmppd, "V2dV2dV2dIc", "ncV:128:", "sse2") TARGET_BUILTIN(__builtin_ia32_minpd, "V2dV2dV2d", "ncV:128:", "sse2") TARGET_BUILTIN(__builtin_ia32_maxpd, "V2dV2dV2d", "ncV:128:", "sse2") TARGET_BUILTIN(__builtin_ia32_minsd, "V2dV2dV2d", "ncV:128:", "sse2") @@ -473,8 +469,12 @@ TARGET_BUILTIN(__builtin_ia32_blendvps256, "V8fV8fV8fV8f", "ncV:256:", "avx") TARGET_BUILTIN(__builtin_ia32_shufpd256, "V4dV4dV4dIi", "ncV:256:", "avx") TARGET_BUILTIN(__builtin_ia32_shufps256, "V8fV8fV8fIi", "ncV:256:", "avx") TARGET_BUILTIN(__builtin_ia32_dpps256, "V8fV8fV8fIc", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_cmppd, "V2dV2dV2dIc", "ncV:128:", "avx") TARGET_BUILTIN(__builtin_ia32_cmppd256, "V4dV4dV4dIc", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_cmpps, "V4fV4fV4fIc", "ncV:128:", "avx") TARGET_BUILTIN(__builtin_ia32_cmpps256, "V8fV8fV8fIc", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_cmpsd, "V2dV2dV2dIc", "ncV:128:", "avx") +TARGET_BUILTIN(__builtin_ia32_cmpss, "V4fV4fV4fIc", "ncV:128:", "avx") TARGET_BUILTIN(__builtin_ia32_vextractf128_pd256, "V2dV4dIi", "ncV:256:", "avx") TARGET_BUILTIN(__builtin_ia32_vextractf128_ps256, "V4fV8fIi", "ncV:256:", "avx") TARGET_BUILTIN(__builtin_ia32_vextractf128_si256, "V4iV8iIi", "ncV:256:", "avx") diff --git a/clang/include/clang/Basic/Diagnostic.h b/clang/include/clang/Basic/Diagnostic.h index 5606a22fe9d68b..3df037b793b394 100644 --- a/clang/include/clang/Basic/Diagnostic.h +++ b/clang/include/clang/Basic/Diagnostic.h @@ -1840,7 +1840,7 @@ const char ToggleHighlight = 127; void ProcessWarningOptions(DiagnosticsEngine &Diags, const DiagnosticOptions &Opts, bool ReportDiags = true); - +void EscapeStringForDiagnostic(StringRef Str, SmallVectorImpl &OutStr); } // namespace clang #endif // LLVM_CLANG_BASIC_DIAGNOSTIC_H diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td index 2a48c063e243ee..91a95def4f80de 100644 --- a/clang/include/clang/Basic/DiagnosticDriverKinds.td +++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -70,6 +70,16 @@ def err_drv_no_rocm_device_lib : Error< def err_drv_no_hip_runtime : Error< "cannot find HIP runtime; provide its path via '--rocm-path', or pass " "'-nogpuinc' to build without HIP runtime">; +def err_drv_no_hipstdpar_lib : Error< + "cannot find HIP Standard Parallelism Acceleration library; provide it via " + "'--hipstdpar-path'">; +def err_drv_no_hipstdpar_thrust_lib : Error< + "cannot find rocThrust, which is required by the HIP Standard Parallelism " + "Acceleration library; provide it via " + "'--hipstdpar-thrust-path'">; +def err_drv_no_hipstdpar_prim_lib : Error< + "cannot find rocPrim, which is required by the HIP Standard Parallelism " + "Acceleration library; provide it via '--hipstdpar-prim-path'">; def err_drv_no_hipspv_device_lib : Error< "cannot find HIP device library%select{| for %1}0; provide its path via " diff --git a/clang/include/clang/Basic/DiagnosticIDs.h b/clang/include/clang/Basic/DiagnosticIDs.h index bf4995175ef196..06ef1c6904c31d 100644 --- a/clang/include/clang/Basic/DiagnosticIDs.h +++ b/clang/include/clang/Basic/DiagnosticIDs.h @@ -31,7 +31,7 @@ namespace clang { // Size of each of the diagnostic categories. enum { DIAG_SIZE_COMMON = 300, - DIAG_SIZE_DRIVER = 300, + DIAG_SIZE_DRIVER = 400, DIAG_SIZE_FRONTEND = 150, DIAG_SIZE_SERIALIZATION = 120, DIAG_SIZE_LEX = 400, diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index 178761bdcf4d5e..43a5f000eda6cb 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -1360,6 +1360,8 @@ def warn_clause_expected_string : Warning< "expected string literal in 'clause %0' - ignoring">, InGroup; def err_omp_unexpected_clause : Error< "unexpected OpenMP clause '%0' in directive '#pragma omp %1'">; +def err_omp_unexpected_clause_extension_only : Error< + "OpenMP clause '%0' is only available as extension, use '-fopenmp-extensions'">; def err_omp_immediate_directive : Error< "'#pragma omp %0' %select{|with '%2' clause }1cannot be an immediate substatement">; def err_omp_expected_identifier_for_critical : Error< @@ -1452,6 +1454,8 @@ def warn_unknown_declare_variant_isa_trait "spelling or consider restricting the context selector with the " "'arch' selector further">, InGroup; +def note_ompx_bare_clause : Note< + "OpenMP extension clause '%0' only allowed with '#pragma omp %1'">; def note_omp_declare_variant_ctx_options : Note<"context %select{set|selector|property}0 options are: %1">; def warn_omp_declare_variant_expected diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 29362df6836535..e3cd49bcc9ecc6 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -240,6 +240,10 @@ def ext_imaginary_constant : Extension< "imaginary constants are a GNU extension">, InGroup; def ext_integer_complex : Extension< "complex integer types are a GNU extension">, InGroup; +def ext_c23_auto_non_plain_identifier : Extension< + "type inference of a declaration other than a plain identifier with optional " + "trailing attributes is a Clang extension">, + InGroup>; def err_invalid_saturation_spec : Error<"'_Sat' specifier is only valid on " "'_Fract' or '_Accum', not '%0'">; @@ -2388,7 +2392,8 @@ def err_auto_not_allowed : Error< "|in conversion function type|here|in lambda parameter" "|in type allocated by 'new'|in K&R-style function parameter" "|in template parameter|in friend declaration|in function prototype that is " - "not a function declaration|in requires expression parameter}1">; + "not a function declaration|in requires expression parameter" + "|in array declaration}1">; def err_dependent_deduced_tst : Error< "typename specifier refers to " "%select{class template|function template|variable template|alias template|" @@ -2461,7 +2466,8 @@ def err_implied_std_initializer_list_not_found : Error< def err_malformed_std_initializer_list : Error< "std::initializer_list must be a class template with a single type parameter">; def err_auto_init_list_from_c : Error< - "cannot use __auto_type with initializer list in C">; + "cannot use %select{'auto'||'__auto_type'}0 with " + "%select{initializer list|array}1 in C">; def err_auto_bitfield : Error< "cannot pass bit-field as __auto_type initializer in C">; @@ -3858,7 +3864,7 @@ def warn_fun_requires_negative_cap : Warning< "calling function %0 requires negative capability '%1'">, InGroup, DefaultIgnore; -// Thread safety warnings on pass by reference +// Thread safety warnings on pass/return by reference def warn_guarded_pass_by_reference : Warning< "passing variable %1 by reference requires holding %0 " "%select{'%2'|'%2' exclusively}3">, @@ -3867,6 +3873,14 @@ def warn_pt_guarded_pass_by_reference : Warning< "passing the value that %1 points to by reference requires holding %0 " "%select{'%2'|'%2' exclusively}3">, InGroup, DefaultIgnore; +def warn_guarded_return_by_reference : Warning< + "returning variable %1 by reference requires holding %0 " + "%select{'%2'|'%2' exclusively}3">, + InGroup, DefaultIgnore; +def warn_pt_guarded_return_by_reference : Warning< + "returning the value that %1 points to by reference requires holding %0 " + "%select{'%2'|'%2' exclusively}3">, + InGroup, DefaultIgnore; // Imprecise thread safety warnings def warn_variable_requires_lock : Warning< @@ -4681,12 +4695,14 @@ def note_ovl_candidate_non_deduced_mismatch_qualified : Note< // Note that we don't treat templates differently for this diagnostic. def note_ovl_candidate_arity : Note<"candidate " "%sub{select_ovl_candidate_kind}0,1,2 not viable: " - "requires%select{ at least| at most|}3 %4 argument%s4, but %5 " + "requires%select{ at least| at most|}3 %4 " + "%select{|non-object }6argument%s4, but %5 " "%plural{1:was|:were}5 provided">; def note_ovl_candidate_arity_one : Note<"candidate " "%sub{select_ovl_candidate_kind}0,1,2 not viable: " "%select{requires at least|allows at most single|requires single}3 " + "%select{|non-object }6" "argument %4, but %plural{0:no|:%5}5 arguments were provided">; def note_ovl_candidate_deleted : Note< @@ -4869,7 +4885,7 @@ def err_ovl_deleted_object_call : Error< "call to deleted function call operator in type %0">; def note_ovl_surrogate_cand : Note<"conversion candidate of type %0">; def err_member_call_without_object : Error< - "call to non-static member function without an object argument">; + "call to %select{non-static|explicit}0 member function without an object argument">; // C++ Address of Overloaded Function def err_addr_ovl_no_viable : Error< @@ -5414,6 +5430,8 @@ def note_constraint_normalization_here : Note< def note_parameter_mapping_substitution_here : Note< "while substituting into concept arguments here; substitution failures not " "allowed in concept arguments">; +def note_building_deduction_guide_here : Note< + "while building implicit deduction guide first needed here">; def note_lambda_substitution_here : Note< "while substituting into a lambda expression here">; def note_instantiation_contexts_suppressed : Note< @@ -6379,6 +6397,21 @@ 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_counted_by_attr_not_on_flexible_array_member : Error< + "'counted_by' only applies to flexible array members">; +def err_flexible_array_counted_by_attr_field_not_found : Error< + "field %0 in 'counted_by' not found">; +def err_flexible_array_counted_by_attr_field_not_found_suggest : Error< + "field %0 in 'counted_by' not found; did you mean %1?">; +def err_flexible_array_counted_by_attr_field_not_found_in_struct : Error< + "field %0 in 'counted_by' is not found in struct">; +def err_flexible_array_counted_by_attr_refers_to_self : Error< + "field %0 in 'counted_by' cannot refer to the flexible array">; +def err_flexible_array_counted_by_attr_field_not_integer : Error< + "field %0 in 'counted_by' is not 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. @@ -6645,8 +6678,8 @@ def err_func_def_incomplete_result : Error< def err_atomic_specifier_bad_type : Error<"_Atomic cannot be applied to " "%select{incomplete |array |function |reference |atomic |qualified " - "|sizeless ||integer }0type " - "%1 %select{|||||||which is not trivially copyable|}0">; + "|sizeless ||integer |}0type " + "%1 %select{|||||||which is not trivially copyable||in C23}0">; def warn_atomic_member_access : Warning< "accessing a member of an atomic structure or union is undefined behavior">, InGroup>, DefaultError; @@ -7289,14 +7322,16 @@ def note_logical_not_silence_with_parens : Note< "add parentheses around left hand side expression to silence this warning">; def err_invalid_this_use : Error< - "invalid use of 'this' outside of a non-static member function">; + "invalid use of 'this' %select{outside of a non-static member function" + "|in a function with an explicit object parameter}0">; def err_this_static_member_func : Error< "'this' cannot be%select{| implicitly}0 used in a static member function " "declaration">; -def err_invalid_member_use_in_static_method : Error< - "invalid use of member %0 in static member function">; +def err_invalid_member_use_in_method : Error< + "invalid use of member %0 in %select{static|explicit object}1 member function">; + def err_invalid_qualified_function_type : Error< - "%select{non-member function|static member function|deduction guide}0 " + "%select{non-member function|static member function|explicit object member function|deduction guide}0 " "%select{of type %2 |}1cannot have '%3' qualifier">; def err_compound_qualified_function_type : Error< "%select{block pointer|pointer|reference}0 to function type %select{%2 |}1" @@ -7304,6 +7339,26 @@ def err_compound_qualified_function_type : Error< def err_qualified_function_typeid : Error< "type operand %0 of 'typeid' cannot have '%1' qualifier">; +def err_cxx20_deducing_this : Error< + "explicit object parameters are incompatible with C++ standards before C++2b">; +def err_explicit_object_default_arg: Error< + "the explicit object parameter cannot have a default argument">; +def err_explicit_object_parameter_pack: Error< + "the explicit object parameter cannot be a function parameter pack">; +def err_explicit_object_parameter_must_be_first: Error< + "an explicit object parameter can only appear as the first parameter " + "of the %select{function|lambda}0">; +def err_explicit_object_parameter_nonmember: Error< + "an explicit object parameter cannot appear in a " + "%select{static|virtual|non-member}0 %select{function|lambda}1">; +def err_explicit_object_parameter_constructor: Error< + "an explicit object parameter cannot appear in a %select{constructor|destructor}0">; +def err_explicit_object_parameter_mutable: Error< + "a lambda with an explicit object parameter cannot be mutable">; +def err_invalid_explicit_object_type_in_lambda: Error< + "invalid explicit object parameter type %0 in lambda with capture; " + "the type must be the same as, or derived from, the lambda">; + def err_ref_qualifier_overload : Error< "cannot overload a member function %select{without a ref-qualifier|with " "ref-qualifier '&'|with ref-qualifier '&&'}0 with a member function %select{" @@ -8525,53 +8580,65 @@ def err_call_function_incomplete_return : Error< def err_call_incomplete_argument : Error< "argument type %0 is incomplete">; def err_typecheck_call_too_few_args : Error< - "too few %select{|||execution configuration }0arguments to " + "too few %select{|||execution configuration }0" + "%select{|non-object }3arguments to " "%select{function|block|method|kernel function}0 call, " "expected %1, have %2">; def err_typecheck_call_too_few_args_one : Error< - "too few %select{|||execution configuration }0arguments to " + "too few %select{|||execution configuration }0" + "%select{|non-object }2arguments to " "%select{function|block|method|kernel function}0 call, " "single argument %1 was not specified">; def err_typecheck_call_too_few_args_at_least : Error< - "too few %select{|||execution configuration }0arguments to " + "too few %select{|||execution configuration }0" + "%select{|non-object }3arguments to " "%select{function|block|method|kernel function}0 call, " "expected at least %1, have %2">; def err_typecheck_call_too_few_args_at_least_one : Error< - "too few %select{|||execution configuration }0arguments to " + "too few %select{|||execution configuration }0" + "%select{|non-object }2arguments to " "%select{function|block|method|kernel function}0 call, " "at least argument %1 must be specified">; def err_typecheck_call_too_few_args_suggest : Error< - "too few %select{|||execution configuration }0arguments to " + "too few %select{|||execution configuration }0" + "%select{|non-object }3arguments to " "%select{function|block|method|kernel function}0 call, " - "expected %1, have %2; did you mean %3?">; + "expected %1, have %2; did you mean %4?">; def err_typecheck_call_too_few_args_at_least_suggest : Error< - "too few %select{|||execution configuration }0arguments to " + "too few %select{|||execution configuration }0" + "%select{|non-object }3arguments to " "%select{function|block|method|kernel function}0 call, " - "expected at least %1, have %2; did you mean %3?">; + "expected at least %1, have %2; did you mean %4?">; def err_typecheck_call_too_many_args : Error< - "too many %select{|||execution configuration }0arguments to " + "too many %select{|||execution configuration }0" + "%select{|non-object }3arguments to " "%select{function|block|method|kernel function}0 call, " "expected %1, have %2">; def err_typecheck_call_too_many_args_one : Error< - "too many %select{|||execution configuration }0arguments to " + "too many %select{|||execution configuration }0" + "%select{|non-object }3arguments to " "%select{function|block|method|kernel function}0 call, " "expected single argument %1, have %2 arguments">; def err_typecheck_call_too_many_args_at_most : Error< - "too many %select{|||execution configuration }0arguments to " + "too many %select{|||execution configuration }0" + "%select{|non-object }3arguments to " "%select{function|block|method|kernel function}0 call, " "expected at most %1, have %2">; def err_typecheck_call_too_many_args_at_most_one : Error< "too many %select{|||execution configuration }0arguments to " "%select{function|block|method|kernel function}0 call, " - "expected at most single argument %1, have %2 arguments">; + "expected at most single %select{|non-object }3argument %1, " + "have %2%select{|non-object}3 arguments">; def err_typecheck_call_too_many_args_suggest : Error< - "too many %select{|||execution configuration }0arguments to " + "too many %select{|||execution configuration }0" + "%select{|non-object }3arguments to " "%select{function|block|method|kernel function}0 call, " - "expected %1, have %2; did you mean %3?">; + "expected %1, have %2; did you mean %4?">; def err_typecheck_call_too_many_args_at_most_suggest : Error< - "too many %select{|||execution configuration }0arguments to " + "too many %select{|||execution configuration }0" + "%select{|non-object }3arguments to " "%select{function|block|method|kernel function}0 call, " - "expected at most %1, have %2; did you mean %3?">; + "expected at most %1, have %2; did you mean %4?">; def err_arc_typecheck_convert_incompatible_pointer : Error< "incompatible pointer types passing retainable parameter of type %0" @@ -9389,10 +9456,10 @@ def warn_cxx98_compat_explicit_conversion_functions : Warning< // C++11 defaulted functions def err_defaulted_special_member_params : Error< - "an explicitly-defaulted %select{|copy |move }0constructor cannot " + "an explicitly-defaulted %sub{select_special_member_kind}0 cannot " "have default arguments">; def err_defaulted_special_member_variadic : Error< - "an explicitly-defaulted %select{|copy |move }0constructor cannot " + "an explicitly-defaulted %sub{select_special_member_kind}0 cannot " "be variadic">; def err_defaulted_special_member_return_type : Error< "explicitly-defaulted %select{copy|move}0 assignment operator must " @@ -9416,6 +9483,8 @@ def err_defaulted_copy_assign_not_ref : Error< def err_incorrect_defaulted_constexpr : Error< "defaulted definition of %sub{select_special_member_kind}0 " "is not constexpr">; +def err_incorrect_defaulted_constexpr_with_vb: Error< + "%sub{select_special_member_kind}0 cannot be 'constexpr' in a class with virtual base class">; def err_incorrect_defaulted_consteval : Error< "defaulted declaration of %sub{select_special_member_kind}0 " "cannot be consteval because implicit definition is not constexpr">; @@ -9455,7 +9524,7 @@ def err_defaulted_comparison_template : Error< "comparison operator template cannot be defaulted">; def err_defaulted_comparison_num_args : Error< "%select{non-member|member}0 %sub{select_defaulted_comparison_kind}1" - " comparison operator must have %select{2|1}0 parameters">; + " must have %select{2|1}0 parameters">; def err_defaulted_comparison_param : Error< "invalid parameter type for defaulted %sub{select_defaulted_comparison_kind}0" "; found %1, expected %2%select{| or %4}3">; diff --git a/clang/include/clang/Basic/FileEntry.h b/clang/include/clang/Basic/FileEntry.h index c377aba2c1d2eb..23237a9326f84b 100644 --- a/clang/include/clang/Basic/FileEntry.h +++ b/clang/include/clang/Basic/FileEntry.h @@ -426,7 +426,6 @@ class FileEntry { public: ~FileEntry(); StringRef getName() const { return LastRef->getName(); } - FileEntryRef getLastRef() const { return *LastRef; } StringRef tryGetRealPathName() const { return RealPathName; } off_t getSize() const { return Size; } diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def index 28c9bcec3ee60f..c0ea4ecb9806a5 100644 --- a/clang/include/clang/Basic/LangOptions.def +++ b/clang/include/clang/Basic/LangOptions.def @@ -280,6 +280,8 @@ ENUM_LANGOPT(SYCLVersion , SYCLMajorVersion, 2, SYCL_None, "Version of the SYCL LANGOPT(HIPUseNewLaunchAPI, 1, 0, "Use new kernel launching API for HIP") LANGOPT(OffloadUniformBlock, 1, 0, "Assume that kernels are launched with uniform block sizes (default true for CUDA/HIP and false otherwise)") +LANGOPT(HIPStdPar, 1, 0, "Enable Standard Parallel Algorithm Acceleration for HIP (experimental)") +LANGOPT(HIPStdParInterposeAlloc, 1, 0, "Replace allocations / deallocations with HIP RT calls when Standard Parallel Algorithm Acceleration for HIP is enabled (Experimental)") LANGOPT(SizedDeallocation , 1, 0, "sized deallocation") LANGOPT(AlignedAllocation , 1, 0, "aligned allocation") diff --git a/clang/include/clang/Basic/ObjCRuntime.h b/clang/include/clang/Basic/ObjCRuntime.h index 0f714ed3ad603a..d783154c3f9f13 100644 --- a/clang/include/clang/Basic/ObjCRuntime.h +++ b/clang/include/clang/Basic/ObjCRuntime.h @@ -483,7 +483,7 @@ class ObjCRuntime { } template - friend void addHash(llvm::HashBuilderImpl &HBuilder, + friend void addHash(llvm::HashBuilder &HBuilder, const ObjCRuntime &OCR) { HBuilder.add(OCR.getKind(), OCR.getVersion()); } diff --git a/clang/include/clang/Basic/Sanitizers.h b/clang/include/clang/Basic/Sanitizers.h index 4659e45c788341..090a3a7fa90762 100644 --- a/clang/include/clang/Basic/Sanitizers.h +++ b/clang/include/clang/Basic/Sanitizers.h @@ -78,7 +78,7 @@ class SanitizerMask { llvm::hash_code hash_value() const; template - friend void addHash(llvm::HashBuilderImpl &HBuilder, + friend void addHash(llvm::HashBuilder &HBuilder, const SanitizerMask &SM) { HBuilder.addRange(&SM.maskLoToHigh[0], &SM.maskLoToHigh[kNumElem]); } diff --git a/clang/include/clang/Basic/SourceManager.h b/clang/include/clang/Basic/SourceManager.h index c1b24eec2759c7..08a69e08405dfb 100644 --- a/clang/include/clang/Basic/SourceManager.h +++ b/clang/include/clang/Basic/SourceManager.h @@ -877,13 +877,6 @@ class SourceManager : public RefCountedBase { /// Create a new FileID that represents the specified file /// being \#included from the specified IncludePosition. - /// - /// This translates NULL into standard input. - FileID createFileID(const FileEntry *SourceFile, SourceLocation IncludePos, - SrcMgr::CharacteristicKind FileCharacter, - int LoadedID = 0, - SourceLocation::UIntTy LoadedOffset = 0); - FileID createFileID(FileEntryRef SourceFile, SourceLocation IncludePos, SrcMgr::CharacteristicKind FileCharacter, int LoadedID = 0, @@ -909,7 +902,7 @@ class SourceManager : public RefCountedBase { /// Get the FileID for \p SourceFile if it exists. Otherwise, create a /// new FileID for the \p SourceFile. - FileID getOrCreateFileID(const FileEntry *SourceFile, + FileID getOrCreateFileID(FileEntryRef SourceFile, SrcMgr::CharacteristicKind FileCharacter); /// Creates an expansion SLocEntry for the substitution of an argument into a diff --git a/clang/include/clang/Driver/OffloadBundler.h b/clang/include/clang/Driver/OffloadBundler.h index 28473c53662de2..17df31d31071d9 100644 --- a/clang/include/clang/Driver/OffloadBundler.h +++ b/clang/include/clang/Driver/OffloadBundler.h @@ -19,6 +19,7 @@ #include "llvm/Support/Error.h" #include "llvm/TargetParser/Triple.h" +#include #include #include @@ -26,11 +27,15 @@ namespace clang { class OffloadBundlerConfig { public: + OffloadBundlerConfig(); + bool AllowNoHost = false; bool AllowMissingBundles = false; bool CheckInputArchive = false; bool PrintExternalCommands = false; bool HipOpenmpCompatible = false; + bool Compress = false; + bool Verbose = false; unsigned BundleAlignment = 1; unsigned HostInputIndex = ~0u; @@ -84,6 +89,38 @@ struct OffloadTargetInfo { std::string str() const; }; +// CompressedOffloadBundle represents the format for the compressed offload +// bundles. +// +// The format is as follows: +// - Magic Number (4 bytes) - A constant "CCOB". +// - Version (2 bytes) +// - Compression Method (2 bytes) - Uses the values from +// llvm::compression::Format. +// - Uncompressed Size (4 bytes). +// - Truncated MD5 Hash (8 bytes). +// - Compressed Data (variable length). + +class CompressedOffloadBundle { +private: + static inline const size_t MagicSize = 4; + static inline const size_t VersionFieldSize = sizeof(uint16_t); + static inline const size_t MethodFieldSize = sizeof(uint16_t); + static inline const size_t SizeFieldSize = sizeof(uint32_t); + static inline const size_t HashFieldSize = 8; + static inline const size_t HeaderSize = MagicSize + VersionFieldSize + + MethodFieldSize + SizeFieldSize + + HashFieldSize; + static inline const llvm::StringRef MagicNumber = "CCOB"; + static inline const uint16_t Version = 1; + +public: + static llvm::Expected> + compress(const llvm::MemoryBuffer &Input, bool Verbose = false); + static llvm::Expected> + decompress(const llvm::MemoryBuffer &Input, bool Verbose = false); +}; + } // namespace clang #endif // LLVM_CLANG_DRIVER_OFFLOADBUNDLER_H diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index efd90942948af2..381126be176ac4 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -1183,6 +1183,10 @@ def fgpu_inline_threshold_EQ : Joined<["-"], "fgpu-inline-threshold=">, def fgpu_sanitize : Flag<["-"], "fgpu-sanitize">, Group, HelpText<"Enable sanitizer for supported offloading devices">; def fno_gpu_sanitize : Flag<["-"], "fno-gpu-sanitize">, Group; + +def offload_compress : Flag<["--"], "offload-compress">, + HelpText<"Compress offload device binaries (HIP only)">; +def no_offload_compress : Flag<["--"], "no-offload-compress">; } // CUDA options @@ -1258,6 +1262,32 @@ def rocm_path_EQ : Joined<["--"], "rocm-path=">, Group, HelpText<"ROCm installation path, used for finding and automatically linking required bitcode libraries.">; def hip_path_EQ : Joined<["--"], "hip-path=">, Group, HelpText<"HIP runtime installation path, used for finding HIP version and adding HIP include path.">; +def hipstdpar : Flag<["--"], "hipstdpar">, + Visibility<[ClangOption, CC1Option]>, + Group, + HelpText<"Enable HIP acceleration for standard parallel algorithms">, + MarshallingInfoFlag>; +def hipstdpar_interpose_alloc : Flag<["--"], "hipstdpar-interpose-alloc">, + Visibility<[ClangOption, CC1Option]>, + Group, + HelpText<"Replace all memory allocation / deallocation calls with " + "hipManagedMalloc / hipFree equivalents">, + MarshallingInfoFlag>; +// TODO: use MarshallingInfo here +def hipstdpar_path_EQ : Joined<["--"], "hipstdpar-path=">, Group, + HelpText< + "HIP Standard Parallel Algorithm Acceleration library path, used for " + "finding and implicitly including the library header">; +def hipstdpar_thrust_path_EQ : Joined<["--"], "hipstdpar-thrust-path=">, + Group, + HelpText< + "rocThrust path, required by the HIP Standard Parallel Algorithm " + "Acceleration library, used to implicitly include the rocThrust library">; +def hipstdpar_prim_path_EQ : Joined<["--"], "hipstdpar-prim-path=">, + Group, + HelpText< + "rocPrim path, required by the HIP Standard Parallel Algorithm " + "Acceleration library, used to implicitly include the rocPrim library">; def rocm_device_lib_path_EQ : Joined<["--"], "rocm-device-lib-path=">, Group, HelpText<"ROCm device library path. Alternative to rocm-path.">; def : Joined<["--"], "hip-device-lib-path=">, Alias; @@ -1879,6 +1909,12 @@ defm safe_buffer_usage_suggestions : BoolFOption<"safe-buffer-usage-suggestions" PosFlag, NegFlag>; +def fverify_intermediate_code : Flag<["-"], "fverify-intermediate-code">, + Group, Visibility<[ClangOption, CLOption, DXCOption]>, + HelpText<"Enable verification of LLVM IR">, Flags<[NoXarchOption]>; +def fno_verify_intermediate_code : Flag<["-"], "fno-verify-intermediate-code">, + Group, Visibility<[ClangOption, CLOption, DXCOption]>, + HelpText<"Disable verification of LLVM IR">, Flags<[NoXarchOption]>; def fdiscard_value_names : Flag<["-"], "fdiscard-value-names">, Group, Visibility<[ClangOption, DXCOption]>, HelpText<"Discard value names in LLVM IR">, Flags<[NoXarchOption]>; @@ -4257,7 +4293,7 @@ def mcmodel_EQ : Joined<["-"], "mcmodel=">, Group, MarshallingInfoString, [{"default"}]>; def mlarge_data_threshold_EQ : Joined<["-"], "mlarge-data-threshold=">, Group, Visibility<[ClangOption, CC1Option]>, - MarshallingInfoInt>; + MarshallingInfoInt, "65535">; def mtls_size_EQ : Joined<["-"], "mtls-size=">, Group, Flags<[NoXarchOption]>, Visibility<[ClangOption, CC1Option]>, HelpText<"Specify bit size of immediate TLS offsets (AArch64 ELF only): " @@ -4557,18 +4593,17 @@ foreach i = {8-15,18} in HelpText<"Make the x"#i#" register call-saved (AArch64 only)">; def msve_vector_bits_EQ : Joined<["-"], "msve-vector-bits=">, Group, + Visibility<[ClangOption, FlangOption]>, HelpText<"Specify the size in bits of an SVE vector register. Defaults to the" " vector length agnostic value of \"scalable\". (AArch64 only)">; } // let Flags = [TargetSpecific] def mvscale_min_EQ : Joined<["-"], "mvscale-min=">, - Group, Flags<[NoXarchOption]>, - Visibility<[ClangOption, CC1Option]>, + Visibility<[CC1Option, FC1Option]>, HelpText<"Specify the vscale minimum. Defaults to \"1\". (AArch64/RISC-V only)">, MarshallingInfoInt>; def mvscale_max_EQ : Joined<["-"], "mvscale-max=">, - Group, Flags<[NoXarchOption]>, - Visibility<[ClangOption, CC1Option]>, + Visibility<[CC1Option, FC1Option]>, HelpText<"Specify the vscale maximum. Defaults to the" " vector length agnostic value of \"0\". (AArch64/RISC-V only)">, MarshallingInfoInt>; diff --git a/clang/include/clang/Lex/HeaderSearchOptions.h b/clang/include/clang/Lex/HeaderSearchOptions.h index 126659f3ac0022..206bc69d7b2cdc 100644 --- a/clang/include/clang/Lex/HeaderSearchOptions.h +++ b/clang/include/clang/Lex/HeaderSearchOptions.h @@ -268,7 +268,7 @@ inline llvm::hash_code hash_value(const HeaderSearchOptions::Entry &E) { } template -inline void addHash(llvm::HashBuilderImpl &HBuilder, +inline void addHash(llvm::HashBuilder &HBuilder, const HeaderSearchOptions::Entry &E) { HBuilder.add(E.Path, E.Group, E.IsFramework, E.IgnoreSysRoot); } @@ -279,7 +279,7 @@ hash_value(const HeaderSearchOptions::SystemHeaderPrefix &SHP) { } template -inline void addHash(llvm::HashBuilderImpl &HBuilder, +inline void addHash(llvm::HashBuilder &HBuilder, const HeaderSearchOptions::SystemHeaderPrefix &SHP) { HBuilder.add(SHP.Prefix, SHP.IsSystemHeader); } diff --git a/clang/include/clang/Lex/Preprocessor.h b/clang/include/clang/Lex/Preprocessor.h index e88164f196c1f7..a8d2599d94ebc6 100644 --- a/clang/include/clang/Lex/Preprocessor.h +++ b/clang/include/clang/Lex/Preprocessor.h @@ -1722,6 +1722,9 @@ class Preprocessor { /// Lex the next token for this preprocessor. void Lex(Token &Result); + /// Lex all tokens for this preprocessor until (and excluding) end of file. + void LexTokensUntilEOF(std::vector *Tokens = nullptr); + /// Lex a token, forming a header-name token if possible. bool LexHeaderName(Token &Result, bool AllowMacroExpansion = true); diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 0e969f341bbe19..79ac622fd03e24 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -1766,6 +1766,7 @@ class Parser : public CodeCompletionHandler { ExprResult ParseConstantExpressionInExprEvalContext( TypeCastState isTypeCast = NotTypeCast); ExprResult ParseConstantExpression(); + ExprResult ParseArrayBoundExpression(); ExprResult ParseCaseExpression(SourceLocation CaseLoc); ExprResult ParseConstraintExpression(); ExprResult diff --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h index ff5e2e2e57366d..4561cca929c0d0 100644 --- a/clang/include/clang/Sema/DeclSpec.h +++ b/clang/include/clang/Sema/DeclSpec.h @@ -2674,6 +2674,8 @@ class Declarator { /// redeclaration time if the decl is static. bool isStaticMember(); + bool isExplicitObjectMemberFunction(); + /// Returns true if this declares a constructor or a destructor. bool isCtorOrDtor(); diff --git a/clang/include/clang/Sema/ScopeInfo.h b/clang/include/clang/Sema/ScopeInfo.h index 26c0387dfc444c..361108fb51ba0e 100644 --- a/clang/include/clang/Sema/ScopeInfo.h +++ b/clang/include/clang/Sema/ScopeInfo.h @@ -847,6 +847,8 @@ class LambdaScopeInfo final : /// is known. bool AfterParameterList = true; + ParmVarDecl *ExplicitObjectParameter = nullptr; + /// Source range covering the lambda introducer [...]. SourceRange IntroducerRange; @@ -1042,6 +1044,8 @@ class LambdaScopeInfo final : void visitPotentialCaptures( llvm::function_ref Callback) const; + + bool lambdaCaptureShouldBeConst() const; }; FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy() diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index e13524b5f3b30c..f77e109bac323e 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -1062,20 +1062,6 @@ class Sema final { } }; - /// Whether the AST is currently being rebuilt to correct immediate - /// invocations. Immediate invocation candidates and references to consteval - /// functions aren't tracked when this is set. - bool RebuildingImmediateInvocation = false; - - /// Used to change context to isConstantEvaluated without pushing a heavy - /// ExpressionEvaluationContextRecord object. - bool isConstantEvaluatedOverride; - - bool isConstantEvaluated() const { - return ExprEvalContexts.back().isConstantEvaluated() || - isConstantEvaluatedOverride; - } - /// RAII object to handle the state changes required to synthesize /// a function body. class SynthesizedFunctionScope { @@ -1361,6 +1347,11 @@ class Sema final { bool IsCurrentlyCheckingDefaultArgumentOrInitializer = false; + // We are in a constant context, but we also allow + // non constant expressions, for example for array bounds (which may be + // VLAs). + bool InConditionallyConstantEvaluateContext = false; + // When evaluating immediate functions in the initializer of a default // argument or default member initializer, this is the declaration whose // default initializer is being evaluated and the location of the call @@ -2183,20 +2174,17 @@ class Sema final { const FunctionProtoType *Old, SourceLocation OldLoc, const FunctionProtoType *New, SourceLocation NewLoc); bool handlerCanCatch(QualType HandlerType, QualType ExceptionType); - bool CheckExceptionSpecSubset(const PartialDiagnostic &DiagID, - const PartialDiagnostic &NestedDiagID, - const PartialDiagnostic &NoteID, - const PartialDiagnostic &NoThrowDiagID, - const FunctionProtoType *Superset, - SourceLocation SuperLoc, - const FunctionProtoType *Subset, - SourceLocation SubLoc); - bool CheckParamExceptionSpec(const PartialDiagnostic &NestedDiagID, - const PartialDiagnostic &NoteID, - const FunctionProtoType *Target, - SourceLocation TargetLoc, - const FunctionProtoType *Source, - SourceLocation SourceLoc); + bool CheckExceptionSpecSubset( + const PartialDiagnostic &DiagID, const PartialDiagnostic &NestedDiagID, + const PartialDiagnostic &NoteID, const PartialDiagnostic &NoThrowDiagID, + const FunctionProtoType *Superset, bool SkipSupersetFirstParameter, + SourceLocation SuperLoc, const FunctionProtoType *Subset, + bool SkipSubsetFirstParameter, SourceLocation SubLoc); + bool CheckParamExceptionSpec( + const PartialDiagnostic &NestedDiagID, const PartialDiagnostic &NoteID, + const FunctionProtoType *Target, bool SkipTargetFirstParameter, + SourceLocation TargetLoc, const FunctionProtoType *Source, + bool SkipSourceFirstParameter, SourceLocation SourceLoc); TypeResult ActOnTypeName(Scope *S, Declarator &D); @@ -3023,7 +3011,8 @@ class Sema final { Attr *getImplicitCodeSegOrSectionAttrForFunction(const FunctionDecl *FD, bool IsDefinition); void CheckFunctionOrTemplateParamDeclarator(Scope *S, Declarator &D); - Decl *ActOnParamDeclarator(Scope *S, Declarator &D); + Decl *ActOnParamDeclarator(Scope *S, Declarator &D, + SourceLocation ExplicitThisLoc = {}); ParmVarDecl *BuildParmVarDeclForTypedef(DeclContext *DC, SourceLocation Loc, QualType T); @@ -3797,8 +3786,12 @@ class Sema final { NamedDecl *&OldDecl, bool UseMemberUsingDeclRules); bool IsOverload(FunctionDecl *New, FunctionDecl *Old, - bool UseMemberUsingDeclRules, bool ConsiderCudaAttrs = true, - bool ConsiderRequiresClauses = true); + bool UseMemberUsingDeclRules, bool ConsiderCudaAttrs = true); + + // Checks whether MD constitutes an override the base class method BaseMD. + // When checking for overrides, the object object members are ignored. + bool IsOverride(FunctionDecl *MD, FunctionDecl *BaseMD, + bool UseMemberUsingDeclRules, bool ConsiderCudaAttrs = true); // Calculates whether the expression Constraint depends on an enclosing // template, for the purposes of [temp.friend] p9. @@ -3856,6 +3849,12 @@ class Sema final { QualType &ConvertedType); bool IsBlockPointerConversion(QualType FromType, QualType ToType, QualType& ConvertedType); + + bool FunctionParamTypesAreEqual(ArrayRef Old, + ArrayRef New, + unsigned *ArgPos = nullptr, + bool Reversed = false); + bool FunctionParamTypesAreEqual(const FunctionProtoType *OldType, const FunctionProtoType *NewType, unsigned *ArgPos = nullptr, @@ -3896,10 +3895,11 @@ class Sema final { ExprResult Init, bool TopLevelOfInitList = false, bool AllowExplicit = false); - ExprResult PerformObjectArgumentInitialization(Expr *From, - NestedNameSpecifier *Qualifier, - NamedDecl *FoundDecl, - CXXMethodDecl *Method); + ExprResult InitializeExplicitObjectArgument(Sema &S, Expr *Obj, + FunctionDecl *Fun); + ExprResult PerformImplicitObjectArgumentInitialization( + Expr *From, NestedNameSpecifier *Qualifier, NamedDecl *FoundDecl, + CXXMethodDecl *Method); /// Check that the lifetime of the initializer (and its subobjects) is /// sufficient for initializing the entity, and perform lifetime extension @@ -4221,9 +4221,8 @@ class Sema final { QualType DestTypeForComplaining = QualType(), unsigned DiagIDForComplaining = 0); - Expr *FixOverloadedFunctionReference(Expr *E, - DeclAccessPair FoundDecl, - FunctionDecl *Fn); + ExprResult FixOverloadedFunctionReference(Expr *E, DeclAccessPair FoundDecl, + FunctionDecl *Fn); ExprResult FixOverloadedFunctionReference(ExprResult, DeclAccessPair FoundDecl, FunctionDecl *Fn); @@ -4796,11 +4795,13 @@ class Sema final { 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. - void adjustMemberFunctionCC(QualType &T, bool IsStatic, bool IsCtorOrDtor, - SourceLocation Loc); + void adjustMemberFunctionCC(QualType &T, bool HasThisPointer, + bool IsCtorOrDtor, SourceLocation Loc); // Check if there is an explicit attribute, but only look through parens. // The intent is to look for an attribute on the current declarator, but not @@ -5796,6 +5797,10 @@ class Sema final { Expr *Input, bool IsAfterAmp = false); bool isQualifiedMemberAccess(Expr *E); + bool CheckUseOfCXXMethodAsAddressOfOperand(SourceLocation OpLoc, + const Expr *Op, + const CXXMethodDecl *MD); + QualType CheckAddressOfOperand(ExprResult &Operand, SourceLocation OpLoc); bool CheckTypeTraitArity(unsigned Arity, SourceLocation Loc, size_t N); @@ -7236,6 +7241,8 @@ class Sema final { StorageClass SC, ArrayRef Params, bool HasExplicitResultType); + void DiagnoseInvalidExplicitObjectParameterInLambda(CXXMethodDecl *Method); + /// Perform initialization analysis of the init-capture and perform /// any implicit conversions such as an lvalue-to-rvalue conversion if /// not being used to initialize a reference. @@ -7369,7 +7376,8 @@ class Sema final { public: LambdaScopeForCallOperatorInstantiationRAII( Sema &SemasRef, FunctionDecl *FD, MultiLevelTemplateArgumentList MLTAL, - LocalInstantiationScope &Scope); + LocalInstantiationScope &Scope, + bool ShouldAddDeclsFromParentScope = true); }; /// Check whether the given expression is a valid constraint expression. @@ -7395,6 +7403,11 @@ class Sema final { llvm::ContextualFoldingSet SatisfactionCache; + /// Introduce the instantiated local variables into the local + /// instantiation scope. + void addInstantiatedLocalVarsToScope(FunctionDecl *Function, + const FunctionDecl *PatternDecl, + LocalInstantiationScope &Scope); /// Introduce the instantiated function parameters into the local /// instantiation scope, and set the parameter names to those used /// in the template. @@ -7916,6 +7929,13 @@ class Sema final { void DefineDefaultedComparison(SourceLocation Loc, FunctionDecl *FD, DefaultedComparisonKind DCK); + void CheckExplicitObjectMemberFunction(Declarator &D, DeclarationName Name, + QualType R, bool IsLambda, + DeclContext *DC = nullptr); + void CheckExplicitObjectMemberFunction(DeclContext *DC, Declarator &D, + DeclarationName Name, QualType R); + void CheckExplicitObjectLambda(Declarator &D); + //===--------------------------------------------------------------------===// // C++ Derived Classes // @@ -7967,6 +7987,10 @@ class Sema final { bool CheckOverridingFunctionReturnType(const CXXMethodDecl *New, const CXXMethodDecl *Old); + // Check that the overriding method has no explicit object parameter. + bool CheckExplicitObjectOverride(CXXMethodDecl *New, + const CXXMethodDecl *Old); + /// CheckOverridingFunctionExceptionSpec - Checks whether the exception /// spec is a subset of base spec. bool CheckOverridingFunctionExceptionSpec(const CXXMethodDecl *New, @@ -9210,6 +9234,7 @@ class Sema final { TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef Args, FunctionDecl *&Specialization, sema::TemplateDeductionInfo &Info, bool PartialOverloading, bool AggregateDeductionCandidate, + QualType ObjectType, Expr::Classification ObjectClassification, llvm::function_ref)> CheckNonDependent); TemplateDeductionResult @@ -9220,11 +9245,10 @@ class Sema final { sema::TemplateDeductionInfo &Info, bool IsAddressOfFunction = false); - TemplateDeductionResult - DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, - QualType ToType, - CXXConversionDecl *&Specialization, - sema::TemplateDeductionInfo &Info); + TemplateDeductionResult DeduceTemplateArguments( + FunctionTemplateDecl *FunctionTemplate, QualType ObjectType, + Expr::Classification ObjectClassification, QualType ToType, + CXXConversionDecl *&Specialization, sema::TemplateDeductionInfo &Info); TemplateDeductionResult DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, @@ -9845,30 +9869,44 @@ class Sema final { /// diagnostics that will be suppressed. std::optional isSFINAEContext() const; - /// Determines whether we are currently in a context that - /// is not evaluated as per C++ [expr] p5. - bool isUnevaluatedContext() const { + /// Whether the AST is currently being rebuilt to correct immediate + /// invocations. Immediate invocation candidates and references to consteval + /// functions aren't tracked when this is set. + bool RebuildingImmediateInvocation = false; + + /// Used to change context to isConstantEvaluated without pushing a heavy + /// ExpressionEvaluationContextRecord object. + bool isConstantEvaluatedOverride = false; + + const ExpressionEvaluationContextRecord ¤tEvaluationContext() const { assert(!ExprEvalContexts.empty() && "Must be in an expression evaluation context"); - return ExprEvalContexts.back().isUnevaluated(); - } + return ExprEvalContexts.back(); + }; bool isConstantEvaluatedContext() const { - assert(!ExprEvalContexts.empty() && - "Must be in an expression evaluation context"); - return ExprEvalContexts.back().isConstantEvaluated(); + return currentEvaluationContext().isConstantEvaluated() || + isConstantEvaluatedOverride; + } + + bool isAlwaysConstantEvaluatedContext() const { + const ExpressionEvaluationContextRecord &Ctx = currentEvaluationContext(); + return (Ctx.isConstantEvaluated() || isConstantEvaluatedOverride) && + !Ctx.InConditionallyConstantEvaluateContext; + } + + /// Determines whether we are currently in a context that + /// is not evaluated as per C++ [expr] p5. + bool isUnevaluatedContext() const { + return currentEvaluationContext().isUnevaluated(); } bool isImmediateFunctionContext() const { - assert(!ExprEvalContexts.empty() && - "Must be in an expression evaluation context"); - return ExprEvalContexts.back().isImmediateFunctionContext(); + return currentEvaluationContext().isImmediateFunctionContext(); } bool isCheckingDefaultArgumentOrInitializer() const { - assert(!ExprEvalContexts.empty() && - "Must be in an expression evaluation context"); - const ExpressionEvaluationContextRecord &Ctx = ExprEvalContexts.back(); + const ExpressionEvaluationContextRecord &Ctx = currentEvaluationContext(); return (Ctx.Context == ExpressionEvaluationContext::PotentiallyEvaluatedIfUsed) || Ctx.IsCurrentlyCheckingDefaultArgumentOrInitializer; @@ -12448,6 +12486,10 @@ class Sema final { SourceLocation LParenLoc, SourceLocation EndLoc); + /// Called on a well-formed 'ompx_bare' clause. + OMPClause *ActOnOpenMPXBareClause(SourceLocation StartLoc, + SourceLocation EndLoc); + /// The kind of conversion being performed. enum CheckedConversionKind { /// An implicit conversion. diff --git a/clang/include/clang/Serialization/ModuleFileExtension.h b/clang/include/clang/Serialization/ModuleFileExtension.h index 2168ce2ce607c0..d7d456c8b5db8e 100644 --- a/clang/include/clang/Serialization/ModuleFileExtension.h +++ b/clang/include/clang/Serialization/ModuleFileExtension.h @@ -86,8 +86,7 @@ class ModuleFileExtension /// The default implementation of this function simply does nothing, so the /// presence/absence of this extension does not distinguish module files. using ExtensionHashBuilder = - llvm::HashBuilderImpl; + llvm::HashBuilder; virtual void hashExtension(ExtensionHashBuilder &HBuilder) const; /// Create a new module file extension writer, which will be diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 8917662c533682..cdc3d62bca0087 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -925,10 +925,14 @@ ASTContext::ASTContext(LangOptions &LOpts, SourceManager &SM, IdentifierTable &idents, SelectorTable &sels, Builtin::Context &builtins, TranslationUnitKind TUKind) : ConstantArrayTypes(this_(), ConstantArrayTypesLog2InitSize), + DependentSizedArrayTypes(this_()), DependentSizedExtVectorTypes(this_()), + DependentAddressSpaceTypes(this_()), DependentVectorTypes(this_()), + DependentSizedMatrixTypes(this_()), FunctionProtoTypes(this_(), FunctionProtoTypesLog2InitSize), + DependentTypeOfExprTypes(this_()), DependentDecltypeTypes(this_()), TemplateSpecializationTypes(this_()), DependentTemplateSpecializationTypes(this_()), AutoTypes(this_()), - SubstTemplateTemplateParmPacks(this_()), + DependentBitIntTypes(this_()), SubstTemplateTemplateParmPacks(this_()), CanonTemplateTemplateParms(this_()), SourceMgr(SM), LangOpts(LOpts), NoSanitizeL(new NoSanitizeList(LangOpts.NoSanitizeFiles, SM)), XRayFilter(new XRayFunctionFilter(LangOpts.XRayAlwaysInstrumentFiles, @@ -3786,11 +3790,8 @@ QualType ASTContext::getDependentSizedArrayType(QualType elementType, // initializer. We do no canonicalization here at all, which is okay // because they can't be used in most locations. if (!numElements) { - auto *newType - = new (*this, TypeAlignment) - DependentSizedArrayType(*this, elementType, QualType(), - numElements, ASM, elementTypeQuals, - brackets); + auto *newType = new (*this, TypeAlignment) DependentSizedArrayType( + elementType, QualType(), numElements, ASM, elementTypeQuals, brackets); Types.push_back(newType); return QualType(newType, 0); } @@ -3813,9 +3814,8 @@ QualType ASTContext::getDependentSizedArrayType(QualType elementType, // If we don't have one, build one. if (!canonTy) { canonTy = new (*this, TypeAlignment) - DependentSizedArrayType(*this, QualType(canonElementType.Ty, 0), - QualType(), numElements, ASM, elementTypeQuals, - brackets); + DependentSizedArrayType(QualType(canonElementType.Ty, 0), QualType(), + numElements, ASM, elementTypeQuals, brackets); DependentSizedArrayTypes.InsertNode(canonTy, insertPos); Types.push_back(canonTy); } @@ -3832,10 +3832,8 @@ QualType ASTContext::getDependentSizedArrayType(QualType elementType, // Otherwise, we need to build a type which follows the spelling // of the element type. - auto *sugaredType - = new (*this, TypeAlignment) - DependentSizedArrayType(*this, elementType, canon, numElements, - ASM, elementTypeQuals, brackets); + auto *sugaredType = new (*this, TypeAlignment) DependentSizedArrayType( + elementType, canon, numElements, ASM, elementTypeQuals, brackets); Types.push_back(sugaredType); return QualType(sugaredType, 0); } @@ -4111,12 +4109,12 @@ ASTContext::getDependentVectorType(QualType VecType, Expr *SizeExpr, if (Canon) { New = new (*this, TypeAlignment) DependentVectorType( - *this, VecType, QualType(Canon, 0), SizeExpr, AttrLoc, VecKind); + VecType, QualType(Canon, 0), SizeExpr, AttrLoc, VecKind); } else { QualType CanonVecTy = getCanonicalType(VecType); if (CanonVecTy == VecType) { - New = new (*this, TypeAlignment) DependentVectorType( - *this, VecType, QualType(), SizeExpr, AttrLoc, VecKind); + New = new (*this, TypeAlignment) + DependentVectorType(VecType, QualType(), SizeExpr, AttrLoc, VecKind); DependentVectorType *CanonCheck = DependentVectorTypes.FindNodeOrInsertPos(ID, InsertPos); @@ -4127,8 +4125,8 @@ ASTContext::getDependentVectorType(QualType VecType, Expr *SizeExpr, } else { QualType CanonTy = getDependentVectorType(CanonVecTy, SizeExpr, SourceLocation(), VecKind); - New = new (*this, TypeAlignment) DependentVectorType( - *this, VecType, CanonTy, SizeExpr, AttrLoc, VecKind); + New = new (*this, TypeAlignment) + DependentVectorType(VecType, CanonTy, SizeExpr, AttrLoc, VecKind); } } @@ -4186,15 +4184,13 @@ ASTContext::getDependentSizedExtVectorType(QualType vecType, if (Canon) { // We already have a canonical version of this array type; use it as // the canonical type for a newly-built type. - New = new (*this, TypeAlignment) - DependentSizedExtVectorType(*this, vecType, QualType(Canon, 0), - SizeExpr, AttrLoc); + New = new (*this, TypeAlignment) DependentSizedExtVectorType( + vecType, QualType(Canon, 0), SizeExpr, AttrLoc); } else { QualType CanonVecTy = getCanonicalType(vecType); if (CanonVecTy == vecType) { New = new (*this, TypeAlignment) - DependentSizedExtVectorType(*this, vecType, QualType(), SizeExpr, - AttrLoc); + DependentSizedExtVectorType(vecType, QualType(), SizeExpr, AttrLoc); DependentSizedExtVectorType *CanonCheck = DependentSizedExtVectorTypes.FindNodeOrInsertPos(ID, InsertPos); @@ -4204,8 +4200,8 @@ ASTContext::getDependentSizedExtVectorType(QualType vecType, } else { QualType CanonExtTy = getDependentSizedExtVectorType(CanonVecTy, SizeExpr, SourceLocation()); - New = new (*this, TypeAlignment) DependentSizedExtVectorType( - *this, vecType, CanonExtTy, SizeExpr, AttrLoc); + New = new (*this, TypeAlignment) + DependentSizedExtVectorType(vecType, CanonExtTy, SizeExpr, AttrLoc); } } @@ -4260,7 +4256,7 @@ QualType ASTContext::getDependentSizedMatrixType(QualType ElementTy, if (!Canon) { Canon = new (*this, TypeAlignment) DependentSizedMatrixType( - *this, CanonElementTy, QualType(), RowExpr, ColumnExpr, AttrLoc); + CanonElementTy, QualType(), RowExpr, ColumnExpr, AttrLoc); #ifndef NDEBUG DependentSizedMatrixType *CanonCheck = DependentSizedMatrixTypes.FindNodeOrInsertPos(ID, InsertPos); @@ -4279,7 +4275,7 @@ QualType ASTContext::getDependentSizedMatrixType(QualType ElementTy, // Use Canon as the canonical type for newly-built type. DependentSizedMatrixType *New = new (*this, TypeAlignment) - DependentSizedMatrixType(*this, ElementTy, QualType(Canon, 0), RowExpr, + DependentSizedMatrixType(ElementTy, QualType(Canon, 0), RowExpr, ColumnExpr, AttrLoc); Types.push_back(New); return QualType(New, 0); @@ -4301,9 +4297,8 @@ QualType ASTContext::getDependentAddressSpaceType(QualType PointeeType, DependentAddressSpaceTypes.FindNodeOrInsertPos(ID, insertPos); if (!canonTy) { - canonTy = new (*this, TypeAlignment) - DependentAddressSpaceType(*this, canonPointeeType, - QualType(), AddrSpaceExpr, AttrLoc); + canonTy = new (*this, TypeAlignment) DependentAddressSpaceType( + canonPointeeType, QualType(), AddrSpaceExpr, AttrLoc); DependentAddressSpaceTypes.InsertNode(canonTy, insertPos); Types.push_back(canonTy); } @@ -4312,10 +4307,8 @@ QualType ASTContext::getDependentAddressSpaceType(QualType PointeeType, canonTy->getAddrSpaceExpr() == AddrSpaceExpr) return QualType(canonTy, 0); - auto *sugaredType - = new (*this, TypeAlignment) - DependentAddressSpaceType(*this, PointeeType, QualType(canonTy, 0), - AddrSpaceExpr, AttrLoc); + auto *sugaredType = new (*this, TypeAlignment) DependentAddressSpaceType( + PointeeType, QualType(canonTy, 0), AddrSpaceExpr, AttrLoc); Types.push_back(sugaredType); return QualType(sugaredType, 0); } @@ -4619,8 +4612,8 @@ QualType ASTContext::getDependentBitIntType(bool IsUnsigned, DependentBitIntTypes.FindNodeOrInsertPos(ID, InsertPos)) return QualType(Existing, 0); - auto *New = new (*this, TypeAlignment) - DependentBitIntType(*this, IsUnsigned, NumBitsExpr); + auto *New = + new (*this, TypeAlignment) DependentBitIntType(IsUnsigned, NumBitsExpr); DependentBitIntTypes.InsertNode(New, InsertPos); Types.push_back(New); @@ -5662,8 +5655,7 @@ QualType ASTContext::getTypeOfExprType(Expr *tofExpr, TypeOfKind Kind) const { TypeOfExprType(tofExpr, Kind, QualType((TypeOfExprType *)Canon, 0)); } else { // Build a new, canonical typeof(expr) type. - Canon = new (*this, TypeAlignment) - DependentTypeOfExprType(*this, tofExpr, Kind); + Canon = new (*this, TypeAlignment) DependentTypeOfExprType(tofExpr, Kind); DependentTypeOfExprTypes.InsertNode(Canon, InsertPos); toe = Canon; } @@ -5731,7 +5723,7 @@ QualType ASTContext::getDecltypeType(Expr *e, QualType UnderlyingType) const { = DependentDecltypeTypes.FindNodeOrInsertPos(ID, InsertPos); if (!Canon) { // Build a new, canonical decltype(expr) type. - Canon = new (*this, TypeAlignment) DependentDecltypeType(*this, e); + Canon = new (*this, TypeAlignment) DependentDecltypeType(e, DependentTy); DependentDecltypeTypes.InsertNode(Canon, InsertPos); } dt = new (*this, TypeAlignment) @@ -11768,6 +11760,16 @@ GVALinkage ASTContext::GetGVALinkageForFunction(const FunctionDecl *FD) const { static GVALinkage basicGVALinkageForVariable(const ASTContext &Context, const VarDecl *VD) { + // As an extension for interactive REPLs, make sure constant variables are + // only emitted once instead of LinkageComputer::getLVForNamespaceScopeDecl + // marking them as internal. + if (Context.getLangOpts().CPlusPlus && + Context.getLangOpts().IncrementalExtensions && + VD->getType().isConstQualified() && + !VD->getType().isVolatileQualified() && !VD->isInline() && + !isa(VD) && !VD->getDescribedVarTemplate()) + return GVA_DiscardableODR; + if (!VD->isExternallyVisible()) return GVA_Internal; diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index c7c2aecc8b179a..29b9d492904f5c 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -4521,6 +4521,8 @@ ExpectedDecl ASTNodeImporter::VisitImplicitParamDecl(ImplicitParamDecl *D) { Error ASTNodeImporter::ImportDefaultArgOfParmVarDecl( const ParmVarDecl *FromParam, ParmVarDecl *ToParam) { ToParam->setHasInheritedDefaultArg(FromParam->hasInheritedDefaultArg()); + ToParam->setExplicitObjectParameterLoc( + FromParam->getExplicitObjectParamThisLoc()); ToParam->setKNRPromoted(FromParam->isKNRPromoted()); if (FromParam->hasUninstantiatedDefaultArg()) { @@ -8975,6 +8977,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. @@ -9181,6 +9187,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/ASTStructuralEquivalence.cpp b/clang/lib/AST/ASTStructuralEquivalence.cpp index 5b98d14dd3d910..8ad142ff09b788 100644 --- a/clang/lib/AST/ASTStructuralEquivalence.cpp +++ b/clang/lib/AST/ASTStructuralEquivalence.cpp @@ -1403,6 +1403,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, Method1->getAccess() == Method2->getAccess() && Method1->getOverloadedOperator() == Method2->getOverloadedOperator() && Method1->isStatic() == Method2->isStatic() && + Method1->isImplicitObjectMemberFunction() == + Method2->isImplicitObjectMemberFunction() && Method1->isConst() == Method2->isConst() && Method1->isVolatile() == Method2->isVolatile() && Method1->isVirtual() == Method2->isVirtual() && diff --git a/clang/lib/AST/ComputeDependence.cpp b/clang/lib/AST/ComputeDependence.cpp index 09df5401d6693a..097753fd3267b5 100644 --- a/clang/lib/AST/ComputeDependence.cpp +++ b/clang/lib/AST/ComputeDependence.cpp @@ -484,6 +484,10 @@ ExprDependence clang::computeDependence(DeclRefExpr *E, const ASTContext &Ctx) { // - an identifier associated by name lookup with one or more declarations // declared with a dependent type + // - an identifier associated by name lookup with an entity captured by + // copy ([expr.prim.lambda.capture]) + // in a lambda-expression that has an explicit object parameter whose + // type is dependent ([dcl.fct]), // // [The "or more" case is not modeled as a DeclRefExpr. There are a bunch // more bullets here that we handle by treating the declaration as having a @@ -493,6 +497,11 @@ ExprDependence clang::computeDependence(DeclRefExpr *E, const ASTContext &Ctx) { else if (Type->isInstantiationDependentType()) Deps |= ExprDependence::Instantiation; + // - an identifier associated by name lookup with an entity captured by + // copy ([expr.prim.lambda.capture]) + if (E->isCapturedByCopyInLambdaWithExplicitObjectParameter()) + Deps |= ExprDependence::Type; + // - a conversion-function-id that specifies a dependent type if (Decl->getDeclName().getNameKind() == DeclarationName::CXXConversionFunctionName) { diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index dc02706f649967..b88df1edf845ac 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -3652,6 +3652,20 @@ unsigned FunctionDecl::getMinRequiredArguments() const { return NumRequiredArgs; } +bool FunctionDecl::hasCXXExplicitFunctionObjectParameter() const { + return getNumParams() != 0 && getParamDecl(0)->isExplicitObjectParameter(); +} + +unsigned FunctionDecl::getNumNonObjectParams() const { + return getNumParams() - + static_cast(hasCXXExplicitFunctionObjectParameter()); +} + +unsigned FunctionDecl::getMinRequiredExplicitArguments() const { + return getMinRequiredArguments() - + static_cast(hasCXXExplicitFunctionObjectParameter()); +} + bool FunctionDecl::hasOneParamOrDefaultArgs() const { return getNumParams() == 1 || (getNumParams() > 1 && diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp index 834beef49a4441..46372f97289c30 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,81 @@ 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(); + FAMKind StrictFlexArraysLevel = + Ctx.getLangOpts().getStrictFlexArraysLevel(); + + 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()) { + const Expr *SizeExpr = dyn_cast(CTL.getSizeExpr()); + if (!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 9d9c33820c3640..42bab4ed51b729 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -838,7 +838,7 @@ void CXXRecordDecl::addedMember(Decl *D) { SMKind |= SMF_CopyAssignment; const auto *ParamTy = - Method->getParamDecl(0)->getType()->getAs(); + Method->getNonObjectParameter(0)->getType()->getAs(); if (!ParamTy || ParamTy->getPointeeType().isConstQualified()) data().HasDeclaredCopyAssignmentWithConstParam = true; } @@ -2409,6 +2409,17 @@ bool CXXMethodDecl::isUsualDeallocationFunction( return Result; } +bool CXXMethodDecl::isExplicitObjectMemberFunction() const { + // C++2b [dcl.fct]p6: + // An explicit object member function is a non-static member + // function with an explicit object parameter + return !isStatic() && hasCXXExplicitFunctionObjectParameter(); +} + +bool CXXMethodDecl::isImplicitObjectMemberFunction() const { + return !isStatic() && !hasCXXExplicitFunctionObjectParameter(); +} + bool CXXMethodDecl::isCopyAssignmentOperator() const { // C++0x [class.copy]p17: // A user-declared copy assignment operator X::operator= is a non-static @@ -2416,11 +2427,12 @@ bool CXXMethodDecl::isCopyAssignmentOperator() const { // type X, X&, const X&, volatile X& or const volatile X&. if (/*operator=*/getOverloadedOperator() != OO_Equal || /*non-static*/ isStatic() || - /*non-template*/getPrimaryTemplate() || getDescribedFunctionTemplate() || - getNumParams() != 1) + + /*non-template*/ getPrimaryTemplate() || getDescribedFunctionTemplate() || + getNumExplicitParams() != 1) return false; - QualType ParamType = getParamDecl(0)->getType(); + QualType ParamType = getNonObjectParameter(0)->getType(); if (const auto *Ref = ParamType->getAs()) ParamType = Ref->getPointeeType(); @@ -2437,10 +2449,10 @@ bool CXXMethodDecl::isMoveAssignmentOperator() const { // X&&, const X&&, volatile X&&, or const volatile X&&. if (getOverloadedOperator() != OO_Equal || isStatic() || getPrimaryTemplate() || getDescribedFunctionTemplate() || - getNumParams() != 1) + getNumExplicitParams() != 1) return false; - QualType ParamType = getParamDecl(0)->getType(); + QualType ParamType = getNonObjectParameter(0)->getType(); if (!ParamType->isRValueReferenceType()) return false; ParamType = ParamType->getPointeeType(); @@ -2496,12 +2508,6 @@ QualType CXXMethodDecl::getThisType(const FunctionProtoType *FPT, : C.getPointerType(ObjectTy); } -QualType CXXMethodDecl::getThisObjectType(const FunctionProtoType *FPT, - const CXXRecordDecl *Decl) { - ASTContext &C = Decl->getASTContext(); - return ::getThisObjectType(C, FPT, Decl); -} - QualType CXXMethodDecl::getThisType() const { // C++ 9.3.2p1: The type of this in a member function of a class X is X*. // If the member function is declared const, the type of this is const X*, @@ -2513,11 +2519,17 @@ QualType CXXMethodDecl::getThisType() const { getParent()); } -QualType CXXMethodDecl::getThisObjectType() const { - // Ditto getThisType. - assert(isInstance() && "No 'this' for static methods!"); - return CXXMethodDecl::getThisObjectType( - getType()->castAs(), getParent()); +QualType CXXMethodDecl::getFunctionObjectParameterReferenceType() const { + if (isExplicitObjectMemberFunction()) + return parameters()[0]->getType(); + + ASTContext &C = getParentASTContext(); + const FunctionProtoType *FPT = getType()->castAs(); + QualType Type = ::getThisObjectType(C, FPT, getParent()); + RefQualifierKind RK = FPT->getRefQualifier(); + if (RK == RefQualifierKind::RQ_RValue) + return C.getRValueReferenceType(Type); + return C.getLValueReferenceType(Type); } bool CXXMethodDecl::hasInlineBody() const { diff --git a/clang/lib/AST/DeclPrinter.cpp b/clang/lib/AST/DeclPrinter.cpp index 748ed3721d23f9..daa219b43c4e6c 100644 --- a/clang/lib/AST/DeclPrinter.cpp +++ b/clang/lib/AST/DeclPrinter.cpp @@ -962,6 +962,10 @@ void DeclPrinter::VisitLabelDecl(LabelDecl *D) { void DeclPrinter::VisitVarDecl(VarDecl *D) { prettyPrintPragmas(D); + if (const auto *Param = dyn_cast(D); + Param && Param->isExplicitObjectParameter()) + Out << "this "; + std::string LeftSide; llvm::raw_string_ostream LeftSideStream(LeftSide); diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 4f3837371b3fc5..5d3b510df1ef9b 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; + D = IRE->getDecl(); - if (!ND) - return false; - - // 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 * @@ -491,6 +428,7 @@ DeclRefExpr::DeclRefExpr(const ASTContext &Ctx, ValueDecl *D, DeclRefExprBits.HadMultipleCandidates = false; DeclRefExprBits.RefersToEnclosingVariableOrCapture = RefersToEnclosingVariableOrCapture; + DeclRefExprBits.CapturedByCopyInLambdaWithExplicitObjectParameter = false; DeclRefExprBits.NonOdrUseReason = NOUR; DeclRefExprBits.IsImmediateEscalating = false; DeclRefExprBits.Loc = L; @@ -518,6 +456,7 @@ DeclRefExpr::DeclRefExpr(const ASTContext &Ctx, = (TemplateArgs || TemplateKWLoc.isValid()) ? 1 : 0; DeclRefExprBits.RefersToEnclosingVariableOrCapture = RefersToEnclosingVariableOrCapture; + DeclRefExprBits.CapturedByCopyInLambdaWithExplicitObjectParameter = false; DeclRefExprBits.NonOdrUseReason = NOUR; if (TemplateArgs) { auto Deps = TemplateArgumentDependence::None; @@ -659,7 +598,7 @@ std::string SYCLUniqueStableNameExpr::ComputeName(ASTContext &Context, std::string Buffer; Buffer.reserve(128); llvm::raw_string_ostream Out(Buffer); - Ctx->mangleTypeName(Ty, Out); + Ctx->mangleCanonicalTypeName(Ty, Out); return Out.str(); } @@ -1619,6 +1558,10 @@ QualType CallExpr::getCallReturnType(const ASTContext &Ctx) const { // This should never be overloaded and so should never return null. CalleeType = Expr::findBoundMemberType(Callee); assert(!CalleeType.isNull()); + } else if (CalleeType->isRecordType()) { + // If the Callee is a record type, then it is a not-yet-resolved + // dependent call to the call operator of that type. + return Ctx.DependentTy; } else if (CalleeType->isDependentType() || CalleeType->isSpecificPlaceholderType(BuiltinType::Overload)) { return Ctx.DependentTy; diff --git a/clang/lib/AST/ExprClassification.cpp b/clang/lib/AST/ExprClassification.cpp index 12193b7812f9bf..ffa7c6802ea6e1 100644 --- a/clang/lib/AST/ExprClassification.cpp +++ b/clang/lib/AST/ExprClassification.cpp @@ -465,8 +465,13 @@ static Cl::Kinds ClassifyDecl(ASTContext &Ctx, const Decl *D) { // lvalue unless it's a reference type (C++ [temp.param]p6), so we need to // special-case this. - if (isa(D) && cast(D)->isInstance()) - return Cl::CL_MemberFunction; + if (const auto *M = dyn_cast(D)) { + if (M->isImplicitObjectMemberFunction()) + return Cl::CL_MemberFunction; + if (M->isStatic()) + return Cl::CL_LValue; + return Cl::CL_PRValue; + } bool islvalue; if (const auto *NTTParm = dyn_cast(D)) @@ -551,8 +556,13 @@ static Cl::Kinds ClassifyMemberExpr(ASTContext &Ctx, const MemberExpr *E) { // -- If it refers to a static member function [...], then E1.E2 is an // lvalue; [...] // -- Otherwise [...] E1.E2 is a prvalue. - if (const auto *Method = dyn_cast(Member)) - return Method->isStatic() ? Cl::CL_LValue : Cl::CL_MemberFunction; + if (const auto *Method = dyn_cast(Member)) { + if (Method->isStatic()) + return Cl::CL_LValue; + if (Method->isImplicitObjectMemberFunction()) + return Cl::CL_MemberFunction; + return Cl::CL_PRValue; + } // -- If E2 is a member enumerator [...], the expression E1.E2 is a prvalue. // So is everything else we haven't handled yet. diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index f7a99bdae18f98..5a33e918db8e8c 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -1945,9 +1945,9 @@ APValue *EvalInfo::createHeapAlloc(const Expr *E, QualType T, LValue &LV) { /// Produce a string describing the given constexpr call. void CallStackFrame::describe(raw_ostream &Out) const { unsigned ArgIndex = 0; - bool IsMemberCall = isa(Callee) && - !isa(Callee) && - cast(Callee)->isInstance(); + bool IsMemberCall = + isa(Callee) && !isa(Callee) && + cast(Callee)->isImplicitObjectMemberFunction(); if (!IsMemberCall) Callee->getNameForDiagnostic(Out, Info.Ctx.getPrintingPolicy(), @@ -3357,6 +3357,9 @@ static bool evaluateVarDeclInit(EvalInfo &Info, const Expr *E, return false; } + if (E->isValueDependent()) + return false; + // Dig out the initializer, and use the declaration which it's attached to. // FIXME: We should eventually check whether the variable has a reachable // initializing declaration. @@ -4711,6 +4714,9 @@ static bool EvaluateObjectArgument(EvalInfo &Info, const Expr *Object, if (Object->getType()->isLiteralType(Info.Ctx)) return EvaluateTemporary(Object, This, Info); + if (Object->getType()->isRecordType() && Object->isPRValue()) + return EvaluateTemporary(Object, This, Info); + Info.FFDiag(Object, diag::note_constexpr_nonliteral) << Object->getType(); return false; } @@ -7789,15 +7795,18 @@ class ExprEvaluatorBase if (OCE && OCE->isAssignmentOp()) { assert(Args.size() == 2 && "wrong number of arguments in assignment"); Call = Info.CurrentCall->createCall(FD); - if (!EvaluateArgs(isa(FD) ? Args.slice(1) : Args, Call, - Info, FD, /*RightToLeft=*/true)) + bool HasThis = false; + if (const auto *MD = dyn_cast(FD)) + HasThis = MD->isImplicitObjectMemberFunction(); + if (!EvaluateArgs(HasThis ? Args.slice(1) : Args, Call, Info, FD, + /*RightToLeft=*/true)) return false; } // Overloaded operator calls to member functions are represented as normal // calls with '*this' as the first argument. const CXXMethodDecl *MD = dyn_cast(FD); - if (MD && !MD->isStatic()) { + if (MD && MD->isImplicitObjectMemberFunction()) { // FIXME: When selecting an implicit conversion for an overloaded // operator delete, we sometimes try to evaluate calls to conversion // operators without a 'this' parameter! @@ -7881,7 +7890,7 @@ class ExprEvaluatorBase CovariantAdjustmentPath); if (!FD) return false; - } else { + } else if (NamedMember && NamedMember->isImplicitObjectMemberFunction()) { // Check that the 'this' pointer points to an object of the right type. // FIXME: If this is an assignment operator call, we may need to change // the active union member before we check this. @@ -8361,7 +8370,13 @@ bool LValueExprEvaluator::VisitVarDecl(const Expr *E, const VarDecl *VD) { if (auto *FD = Info.CurrentCall->LambdaCaptureFields.lookup(VD)) { // Start with 'Result' referring to the complete closure object... - Result = *Info.CurrentCall->This; + if (auto *MD = cast(Info.CurrentCall->Callee); + MD->isExplicitObjectMemberFunction()) { + APValue *RefValue = + Info.getParamSlot(Info.CurrentCall->Arguments, MD->getParamDecl(0)); + Result.setFrom(Info.Ctx, *RefValue); + } else + Result = *Info.CurrentCall->This; // ... then update it to refer to the field of the closure object // that represents the capture. if (!HandleLValueMember(Info, E, Result, FD)) @@ -16284,7 +16299,8 @@ bool Expr::EvaluateWithSubstitution(APValue &Value, ASTContext &Ctx, #ifndef NDEBUG auto *MD = dyn_cast(Callee); assert(MD && "Don't provide `this` for non-methods."); - assert(!MD->isStatic() && "Don't provide `this` for static methods."); + assert(MD->isImplicitObjectMemberFunction() && + "Don't provide `this` for methods without an implicit object."); #endif if (!This->isValueDependent() && EvaluateObjectArgument(Info, This, ThisVal) && @@ -16379,9 +16395,10 @@ bool Expr::isPotentialConstantExpr(const FunctionDecl *FD, HandleConstructorCall(&VIE, This, Args, CD, Info, Scratch); } else { SourceLocation Loc = FD->getLocation(); - HandleFunctionCall(Loc, FD, (MD && MD->isInstance()) ? &This : nullptr, - &VIE, Args, CallRef(), FD->getBody(), Info, Scratch, - /*ResultSlot=*/nullptr); + HandleFunctionCall( + Loc, FD, (MD && MD->isImplicitObjectMemberFunction()) ? &This : nullptr, + &VIE, Args, CallRef(), FD->getBody(), Info, Scratch, + /*ResultSlot=*/nullptr); } return Diags.empty(); diff --git a/clang/lib/AST/Interp/ByteCodeEmitter.cpp b/clang/lib/AST/Interp/ByteCodeEmitter.cpp index 23c28b430d81c2..a634ee288f57c9 100644 --- a/clang/lib/AST/Interp/ByteCodeEmitter.cpp +++ b/clang/lib/AST/Interp/ByteCodeEmitter.cpp @@ -44,7 +44,7 @@ ByteCodeEmitter::compileFunc(const FunctionDecl *FuncDecl) { // InterpStack when calling the function. bool HasThisPointer = false; if (const auto *MD = dyn_cast(FuncDecl)) { - if (MD->isInstance()) { + if (MD->isImplicitObjectMemberFunction()) { HasThisPointer = true; ParamTypes.push_back(PT_Ptr); ParamOffsets.push_back(ParamOffset); @@ -64,8 +64,8 @@ ByteCodeEmitter::compileFunc(const FunctionDecl *FuncDecl) { this->LambdaCaptures[Cap.first] = { Offset, Cap.second->getType()->isReferenceType()}; } - // FIXME: LambdaThisCapture - (void)LTC; + if (LTC) + this->LambdaThisCapture = R->getField(LTC)->Offset; } } diff --git a/clang/lib/AST/Interp/ByteCodeEmitter.h b/clang/lib/AST/Interp/ByteCodeEmitter.h index d184484a9197f9..5520f8c3006106 100644 --- a/clang/lib/AST/Interp/ByteCodeEmitter.h +++ b/clang/lib/AST/Interp/ByteCodeEmitter.h @@ -67,7 +67,8 @@ class ByteCodeEmitter { llvm::DenseMap Params; /// Lambda captures. llvm::DenseMap LambdaCaptures; - unsigned LambdaThisCapture; + /// Offset of the This parameter in a lambda record. + unsigned LambdaThisCapture = 0; /// Local descriptors. llvm::SmallVector, 2> Descriptors; diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp index e266804a4e75de..3cf8bf874b1d21 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -561,7 +561,7 @@ bool ByteCodeExprGen::visitInitList(ArrayRef Inits, if (!this->visitInitializer(Init)) return false; - if (!this->emitPopPtr(E)) + if (!this->emitInitPtrPop(E)) return false; // Base initializers don't increase InitIndex, since they don't count // into the Record's fields. @@ -1718,7 +1718,7 @@ bool ByteCodeExprGen::visitZeroRecordInitializer(const Record *R, return false; if (!this->visitZeroRecordInitializer(B.R, E)) return false; - if (!this->emitPopPtr(E)) + if (!this->emitInitPtrPop(E)) return false; } @@ -2305,6 +2305,10 @@ template bool ByteCodeExprGen::VisitCXXThisExpr(const CXXThisExpr *E) { if (DiscardResult) return true; + + if (this->LambdaThisCapture > 0) + return this->emitGetThisFieldPtr(this->LambdaThisCapture, E); + return this->emitThis(E); } @@ -2536,7 +2540,8 @@ bool ByteCodeExprGen::VisitDeclRefExpr(const DeclRefExpr *E) { // This happens in C. if (!Ctx.getLangOpts().CPlusPlus) { if (const auto *VD = dyn_cast(D); - VD && VD->hasGlobalStorage() && VD->getAnyInitializer()) { + VD && VD->hasGlobalStorage() && VD->getAnyInitializer() && + VD->getType().isConstQualified()) { if (!this->visitVarDecl(VD)) return false; // Retry. diff --git a/clang/lib/AST/Interp/ByteCodeStmtGen.cpp b/clang/lib/AST/Interp/ByteCodeStmtGen.cpp index 15eae8e20b3a67..a81c82c38955e9 100644 --- a/clang/lib/AST/Interp/ByteCodeStmtGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeStmtGen.cpp @@ -191,7 +191,7 @@ bool ByteCodeStmtGen::visitFunc(const FunctionDecl *F) { return false; if (!this->visitInitializer(InitExpr)) return false; - if (!this->emitPopPtr(InitExpr)) + if (!this->emitInitPtrPop(InitExpr)) return false; } } diff --git a/clang/lib/AST/Interp/EvalEmitter.h b/clang/lib/AST/Interp/EvalEmitter.h index c63e46bbf347bd..1128e0fb09f0de 100644 --- a/clang/lib/AST/Interp/EvalEmitter.h +++ b/clang/lib/AST/Interp/EvalEmitter.h @@ -73,7 +73,8 @@ class EvalEmitter : public SourceMapper { llvm::DenseMap Params; /// Lambda captures. llvm::DenseMap LambdaCaptures; - unsigned LambdaThisCapture; + /// Offset of the This parameter in a lambda record. + unsigned LambdaThisCapture = 0; /// Local descriptors. llvm::SmallVector, 2> Descriptors; diff --git a/clang/lib/AST/Interp/IntegralAP.h b/clang/lib/AST/Interp/IntegralAP.h index 53ad76d8a1997e..a8df431bef1178 100644 --- a/clang/lib/AST/Interp/IntegralAP.h +++ b/clang/lib/AST/Interp/IntegralAP.h @@ -32,14 +32,22 @@ template class Integral; class Boolean; template class IntegralAP final { -public: +private: + friend IntegralAP; APSInt V; + template static T truncateCast(const APSInt &V) { + return std::is_signed_v ? V.trunc(sizeof(T) * 8).getSExtValue() + : V.trunc(sizeof(T) * 8).getZExtValue(); + } + public: using AsUnsigned = IntegralAP; template - IntegralAP(T Value) : V(APInt(sizeof(T) * 8, Value, std::is_signed_v)) {} + IntegralAP(T Value) + : V(APInt(sizeof(T) * 8, static_cast(Value), + std::is_signed_v)) {} IntegralAP(APInt V) : V(V) {} IntegralAP(APSInt V) : V(V) {} @@ -53,18 +61,18 @@ template class IntegralAP final { bool operator<=(IntegralAP RHS) const { return V <= RHS.V; } explicit operator bool() const { return !V.isZero(); } - explicit operator int8_t() const { return V.getSExtValue(); } - explicit operator uint8_t() const { return V.getZExtValue(); } - explicit operator int16_t() const { return V.getSExtValue(); } - explicit operator uint16_t() const { return V.getZExtValue(); } - explicit operator int32_t() const { return V.getSExtValue(); } - explicit operator uint32_t() const { return V.getZExtValue(); } - explicit operator int64_t() const { return V.getSExtValue(); } - explicit operator uint64_t() const { return V.getZExtValue(); } + explicit operator int8_t() const { return truncateCast(V); } + explicit operator uint8_t() const { return truncateCast(V); } + explicit operator int16_t() const { return truncateCast(V); } + explicit operator uint16_t() const { return truncateCast(V); } + explicit operator int32_t() const { return truncateCast(V); } + explicit operator uint32_t() const { return truncateCast(V); } + explicit operator int64_t() const { return truncateCast(V); } + explicit operator uint64_t() const { return truncateCast(V); } template static IntegralAP from(T Value, unsigned NumBits = 0) { assert(NumBits > 0); - APSInt Copy = APSInt(APInt(NumBits, Value, Signed), !Signed); + APSInt Copy = APSInt(APInt(NumBits, static_cast(Value), Signed), !Signed); return IntegralAP(Copy); } @@ -208,7 +216,6 @@ template class IntegralAP final { } static bool comp(IntegralAP A, IntegralAP *R) { - assert(false); *R = IntegralAP(~A.V); return false; } diff --git a/clang/lib/AST/Interp/Interp.cpp b/clang/lib/AST/Interp/Interp.cpp index e1951574edb628..8e851595963184 100644 --- a/clang/lib/AST/Interp/Interp.cpp +++ b/clang/lib/AST/Interp/Interp.cpp @@ -467,6 +467,12 @@ static bool CheckFieldsInitialized(InterpState &S, CodePtr OpPC, // Check Fields in all bases for (const Record::Base &B : R->bases()) { Pointer P = BasePtr.atField(B.Offset); + if (!P.isInitialized()) { + S.FFDiag(BasePtr.getDeclDesc()->asDecl()->getLocation(), + diag::note_constexpr_uninitialized_base) + << B.Desc->getType(); + return false; + } Result &= CheckFieldsInitialized(S, OpPC, P, B.R); } diff --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h index 9d5ec3315415cf..d62e64bedb213a 100644 --- a/clang/lib/AST/Interp/Interp.h +++ b/clang/lib/AST/Interp/Interp.h @@ -1245,6 +1245,12 @@ inline bool GetPtrThisBase(InterpState &S, CodePtr OpPC, uint32_t Off) { return true; } +inline bool InitPtrPop(InterpState &S, CodePtr OpPC) { + const Pointer &Ptr = S.Stk.pop(); + Ptr.initialize(); + return true; +} + inline bool VirtBaseHelper(InterpState &S, CodePtr OpPC, const RecordDecl *Decl, const Pointer &Ptr) { Pointer Base = Ptr; diff --git a/clang/lib/AST/Interp/InterpBuiltin.cpp b/clang/lib/AST/Interp/InterpBuiltin.cpp index d816145598049b..bba0255219bc0d 100644 --- a/clang/lib/AST/Interp/InterpBuiltin.cpp +++ b/clang/lib/AST/Interp/InterpBuiltin.cpp @@ -398,6 +398,16 @@ static bool interp__builtin_fabs(InterpState &S, CodePtr OpPC, return true; } +static bool interp__builtin_popcount(InterpState &S, CodePtr OpPC, + const InterpFrame *Frame, + const Function *Func, + const CallExpr *Call) { + PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType()); + APSInt Val = peekToAPSInt(S.Stk, ArgT); + pushInt(S, Val.popcount()); + return true; +} + bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F, const CallExpr *Call) { InterpFrame *Frame = S.Current; @@ -513,6 +523,16 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F, return Ret(S, OpPC, Dummy); break; + case Builtin::BI__builtin_popcount: + case Builtin::BI__builtin_popcountl: + case Builtin::BI__builtin_popcountll: + case Builtin::BI__popcnt16: // Microsoft variants of popcount + case Builtin::BI__popcnt: + case Builtin::BI__popcnt64: + if (interp__builtin_popcount(S, OpPC, Frame, F, Call)) + return retInt(S, OpPC, Dummy); + break; + default: return false; } diff --git a/clang/lib/AST/Interp/Opcodes.td b/clang/lib/AST/Interp/Opcodes.td index 9fc4938bb37bde..50b6c0ac154de3 100644 --- a/clang/lib/AST/Interp/Opcodes.td +++ b/clang/lib/AST/Interp/Opcodes.td @@ -304,6 +304,10 @@ def GetPtrBasePop : Opcode { let Args = [ArgUint32]; } +def InitPtrPop : Opcode { + let Args = []; +} + def GetPtrDerivedPop : Opcode { let Args = [ArgUint32]; } diff --git a/clang/lib/AST/Interp/Source.h b/clang/lib/AST/Interp/Source.h index e97e897e72394d..fec950dd544f8a 100644 --- a/clang/lib/AST/Interp/Source.h +++ b/clang/lib/AST/Interp/Source.h @@ -14,12 +14,12 @@ #define LLVM_CLANG_AST_INTERP_SOURCE_H #include "PrimType.h" +#include "clang/AST/DeclBase.h" +#include "clang/AST/Stmt.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/Support/Endian.h" namespace clang { -class Stmt; -class Decl; class Expr; class SourceLocation; class SourceRange; diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index 830a35b98d6072..23ec35cae4b7b4 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -112,8 +112,8 @@ class ItaniumMangleContextImpl : public ItaniumMangleContext { void mangleCXXRTTI(QualType T, raw_ostream &) override; void mangleCXXRTTIName(QualType T, raw_ostream &, bool NormalizeIntegers) override; - void mangleTypeName(QualType T, raw_ostream &, - bool NormalizeIntegers) override; + void mangleCanonicalTypeName(QualType T, raw_ostream &, + bool NormalizeIntegers) override; void mangleCXXCtorComdat(const CXXConstructorDecl *D, raw_ostream &) override; void mangleCXXDtorComdat(const CXXDestructorDecl *D, raw_ostream &) override; @@ -1721,7 +1721,7 @@ void CXXNameMangler::mangleUnqualifiedName( // If we have a member function, we need to include the 'this' pointer. if (const auto *MD = dyn_cast(ND)) - if (!MD->isStatic()) + if (MD->isImplicitObjectMemberFunction()) Arity++; } [[fallthrough]]; @@ -1781,6 +1781,8 @@ void CXXNameMangler::mangleNestedName(GlobalDecl GD, Qualifiers MethodQuals = Method->getMethodQualifiers(); // We do not consider restrict a distinguishing attribute for overloading // purposes so we must not mangle it. + if (Method->isExplicitObjectMemberFunction()) + Out << 'H'; MethodQuals.removeRestrict(); mangleQualifiers(MethodQuals); mangleRefQualifier(Method->getRefQualifier()); @@ -7130,8 +7132,8 @@ void ItaniumMangleContextImpl::mangleCXXRTTIName( Mangler.mangleType(Ty); } -void ItaniumMangleContextImpl::mangleTypeName(QualType Ty, raw_ostream &Out, - bool NormalizeIntegers = false) { +void ItaniumMangleContextImpl::mangleCanonicalTypeName( + QualType Ty, raw_ostream &Out, bool NormalizeIntegers = false) { mangleCXXRTTIName(Ty, Out, NormalizeIntegers); } diff --git a/clang/lib/AST/JSONNodeDumper.cpp b/clang/lib/AST/JSONNodeDumper.cpp index e67c2c7e216dce..beb07015f0bcbb 100644 --- a/clang/lib/AST/JSONNodeDumper.cpp +++ b/clang/lib/AST/JSONNodeDumper.cpp @@ -876,6 +876,9 @@ void JSONNodeDumper::VisitUsingShadowDecl(const UsingShadowDecl *USD) { void JSONNodeDumper::VisitVarDecl(const VarDecl *VD) { VisitNamedDecl(VD); JOS.attribute("type", createQualType(VD->getType())); + if (const auto *P = dyn_cast(VD)) + attributeOnlyIfTrue("explicitObjectParameter", + P->isExplicitObjectParameter()); StorageClass SC = VD->getStorageClass(); if (SC != SC_None) diff --git a/clang/lib/AST/Mangle.cpp b/clang/lib/AST/Mangle.cpp index 53af9fc4d51897..64c971912a91d0 100644 --- a/clang/lib/AST/Mangle.cpp +++ b/clang/lib/AST/Mangle.cpp @@ -225,7 +225,7 @@ void MangleContext::mangleName(GlobalDecl GD, raw_ostream &Out) { assert(!Proto->isVariadic()); unsigned ArgWords = 0; if (const CXXMethodDecl *MD = dyn_cast(FD)) - if (!MD->isStatic()) + if (MD->isImplicitObjectMemberFunction()) ++ArgWords; uint64_t DefaultPtrWidth = TI.getPointerWidth(LangAS::Default); for (const auto &AT : Proto->param_types()) { diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp index 79175c79de96bf..f6d8cdee8443d5 100644 --- a/clang/lib/AST/MicrosoftMangle.cpp +++ b/clang/lib/AST/MicrosoftMangle.cpp @@ -196,8 +196,8 @@ class MicrosoftMangleContextImpl : public MicrosoftMangleContext { mangleCXXRTTICompleteObjectLocator(const CXXRecordDecl *Derived, ArrayRef BasePath, raw_ostream &Out) override; - void mangleTypeName(QualType T, raw_ostream &, - bool NormalizeIntegers) override; + void mangleCanonicalTypeName(QualType T, raw_ostream &, + bool NormalizeIntegers) override; void mangleReferenceTemporary(const VarDecl *, unsigned ManglingNumber, raw_ostream &) override; void mangleStaticGuardVariable(const VarDecl *D, raw_ostream &Out) override; @@ -2636,7 +2636,7 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T, if (const CXXMethodDecl *MD = dyn_cast_or_null(D)) { if (MD->getParent()->isLambda()) IsInLambda = true; - if (MD->isInstance()) + if (MD->isImplicitObjectMemberFunction()) HasThisQuals = true; if (isa(MD)) { IsStructor = true; @@ -2745,6 +2745,10 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T, } else { // Happens for function pointer type arguments for example. for (unsigned I = 0, E = Proto->getNumParams(); I != E; ++I) { + // Explicit object parameters are prefixed by "_V". + if (I == 0 && D && D->getParamDecl(I)->isExplicitObjectParameter()) + Out << "_V"; + mangleFunctionArgumentType(Proto->getParamType(I), Range); // Mangle each pass_object_size parameter as if it's a parameter of enum // type passed directly after the parameter with the pass_object_size @@ -2810,7 +2814,7 @@ void MicrosoftCXXNameMangler::mangleFunctionClass(const FunctionDecl *FD) { case AS_none: llvm_unreachable("Unsupported access specifier"); case AS_private: - if (MD->isStatic()) + if (!MD->isImplicitObjectMemberFunction()) Out << 'C'; else if (IsVirtual) Out << 'E'; @@ -2818,7 +2822,7 @@ void MicrosoftCXXNameMangler::mangleFunctionClass(const FunctionDecl *FD) { Out << 'A'; break; case AS_protected: - if (MD->isStatic()) + if (!MD->isImplicitObjectMemberFunction()) Out << 'K'; else if (IsVirtual) Out << 'M'; @@ -2826,7 +2830,7 @@ void MicrosoftCXXNameMangler::mangleFunctionClass(const FunctionDecl *FD) { Out << 'I'; break; case AS_public: - if (MD->isStatic()) + if (!MD->isImplicitObjectMemberFunction()) Out << 'S'; else if (IsVirtual) Out << 'U'; @@ -3838,13 +3842,13 @@ void MicrosoftMangleContextImpl::mangleSEHFinallyBlock( Mangler.mangleName(EnclosingDecl); } -void MicrosoftMangleContextImpl::mangleTypeName( +void MicrosoftMangleContextImpl::mangleCanonicalTypeName( QualType T, raw_ostream &Out, bool NormalizeIntegers = false) { // This is just a made up unique string for the purposes of tbaa. undname // does *not* know how to demangle it. MicrosoftCXXNameMangler Mangler(*this, Out); Mangler.getStream() << '?'; - Mangler.mangleType(T, SourceRange()); + Mangler.mangleType(T.getCanonicalType(), SourceRange()); } void MicrosoftMangleContextImpl::mangleReferenceTemporary( diff --git a/clang/lib/AST/OpenMPClause.cpp b/clang/lib/AST/OpenMPClause.cpp index f5ad75028a641e..b95b4fce180e73 100644 --- a/clang/lib/AST/OpenMPClause.cpp +++ b/clang/lib/AST/OpenMPClause.cpp @@ -170,6 +170,7 @@ const OMPClauseWithPreInit *OMPClauseWithPreInit::get(const OMPClause *C) { case OMPC_affinity: case OMPC_when: case OMPC_bind: + case OMPC_ompx_bare: break; default: break; @@ -2546,6 +2547,10 @@ void OMPClausePrinter::VisitOMPXAttributeClause(OMPXAttributeClause *Node) { OS << ")"; } +void OMPClausePrinter::VisitOMPXBareClause(OMPXBareClause *Node) { + OS << "ompx_bare"; +} + void OMPTraitInfo::getAsVariantMatchInfo(ASTContext &ASTCtx, VariantMatchInfo &VMI) const { for (const OMPTraitSet &Set : Sets) { diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index 2e4f15f83ac26e..22b6855b0fff23 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -930,6 +930,7 @@ void OMPClauseProfiler::VisitOMPDoacrossClause(const OMPDoacrossClause *C) { } void OMPClauseProfiler::VisitOMPXAttributeClause(const OMPXAttributeClause *C) { } +void OMPClauseProfiler::VisitOMPXBareClause(const OMPXBareClause *C) {} } // namespace void @@ -1335,6 +1336,8 @@ void StmtProfiler::VisitIntegerLiteral(const IntegerLiteral *S) { S->getValue().Profile(ID); QualType T = S->getType(); + if (Canonical) + T = T.getCanonicalType(); ID.AddInteger(T->getTypeClass()); if (auto BitIntT = T->getAs()) BitIntT->Profile(ID); diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp index 233dc6c6359515..15eb6c6191edf2 100644 --- a/clang/lib/AST/TextNodeDumper.cpp +++ b/clang/lib/AST/TextNodeDumper.cpp @@ -1949,6 +1949,10 @@ void TextNodeDumper::VisitFieldDecl(const FieldDecl *D) { void TextNodeDumper::VisitVarDecl(const VarDecl *D) { dumpNestedNameSpecifier(D->getQualifier()); dumpName(D); + if (const auto *P = dyn_cast(D); + P && P->isExplicitObjectParameter()) + OS << " this"; + dumpType(D->getType()); dumpTemplateSpecializationKind(D->getTemplateSpecializationKind()); StorageClass SC = D->getStorageClass(); diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index c08ebfb7f142b3..4c433f7fe9daca 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -225,13 +225,12 @@ void ConstantArrayType::Profile(llvm::FoldingSetNodeID &ID, SizeExpr->Profile(ID, Context, true); } -DependentSizedArrayType::DependentSizedArrayType(const ASTContext &Context, - QualType et, QualType can, +DependentSizedArrayType::DependentSizedArrayType(QualType et, QualType can, Expr *e, ArraySizeModifier sm, unsigned tq, SourceRange brackets) - : ArrayType(DependentSizedArray, et, can, sm, tq, e), - Context(Context), SizeExpr((Stmt*) e), Brackets(brackets) {} + : ArrayType(DependentSizedArray, et, can, sm, tq, e), SizeExpr((Stmt *)e), + Brackets(brackets) {} void DependentSizedArrayType::Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, @@ -245,8 +244,7 @@ void DependentSizedArrayType::Profile(llvm::FoldingSetNodeID &ID, E->Profile(ID, Context, true); } -DependentVectorType::DependentVectorType(const ASTContext &Context, - QualType ElementType, +DependentVectorType::DependentVectorType(QualType ElementType, QualType CanonType, Expr *SizeExpr, SourceLocation Loc, VectorType::VectorKind VecKind) @@ -255,7 +253,7 @@ DependentVectorType::DependentVectorType(const ASTContext &Context, ElementType->getDependence() | (SizeExpr ? toTypeDependence(SizeExpr->getDependence()) : TypeDependence::None)), - Context(Context), ElementType(ElementType), SizeExpr(SizeExpr), Loc(Loc) { + ElementType(ElementType), SizeExpr(SizeExpr), Loc(Loc) { VectorTypeBits.VecKind = VecKind; } @@ -268,16 +266,16 @@ void DependentVectorType::Profile(llvm::FoldingSetNodeID &ID, SizeExpr->Profile(ID, Context, true); } -DependentSizedExtVectorType::DependentSizedExtVectorType( - const ASTContext &Context, QualType ElementType, QualType can, - Expr *SizeExpr, SourceLocation loc) +DependentSizedExtVectorType::DependentSizedExtVectorType(QualType ElementType, + QualType can, + Expr *SizeExpr, + SourceLocation loc) : Type(DependentSizedExtVector, can, TypeDependence::DependentInstantiation | ElementType->getDependence() | (SizeExpr ? toTypeDependence(SizeExpr->getDependence()) : TypeDependence::None)), - Context(Context), SizeExpr(SizeExpr), ElementType(ElementType), loc(loc) { -} + SizeExpr(SizeExpr), ElementType(ElementType), loc(loc) {} void DependentSizedExtVectorType::Profile(llvm::FoldingSetNodeID &ID, @@ -287,8 +285,7 @@ DependentSizedExtVectorType::Profile(llvm::FoldingSetNodeID &ID, SizeExpr->Profile(ID, Context, true); } -DependentAddressSpaceType::DependentAddressSpaceType(const ASTContext &Context, - QualType PointeeType, +DependentAddressSpaceType::DependentAddressSpaceType(QualType PointeeType, QualType can, Expr *AddrSpaceExpr, SourceLocation loc) @@ -297,8 +294,7 @@ DependentAddressSpaceType::DependentAddressSpaceType(const ASTContext &Context, PointeeType->getDependence() | (AddrSpaceExpr ? toTypeDependence(AddrSpaceExpr->getDependence()) : TypeDependence::None)), - Context(Context), AddrSpaceExpr(AddrSpaceExpr), PointeeType(PointeeType), - loc(loc) {} + AddrSpaceExpr(AddrSpaceExpr), PointeeType(PointeeType), loc(loc) {} void DependentAddressSpaceType::Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, @@ -337,12 +333,14 @@ ConstantMatrixType::ConstantMatrixType(TypeClass tc, QualType matrixType, : MatrixType(tc, matrixType, canonType), NumRows(nRows), NumColumns(nColumns) {} -DependentSizedMatrixType::DependentSizedMatrixType( - const ASTContext &CTX, QualType ElementType, QualType CanonicalType, - Expr *RowExpr, Expr *ColumnExpr, SourceLocation loc) +DependentSizedMatrixType::DependentSizedMatrixType(QualType ElementType, + QualType CanonicalType, + Expr *RowExpr, + Expr *ColumnExpr, + SourceLocation loc) : MatrixType(DependentSizedMatrix, ElementType, CanonicalType, RowExpr, ColumnExpr), - Context(CTX), RowExpr(RowExpr), ColumnExpr(ColumnExpr), loc(loc) {} + RowExpr(RowExpr), ColumnExpr(ColumnExpr), loc(loc) {} void DependentSizedMatrixType::Profile(llvm::FoldingSetNodeID &ID, const ASTContext &CTX, @@ -368,11 +366,10 @@ BitIntType::BitIntType(bool IsUnsigned, unsigned NumBits) : Type(BitInt, QualType{}, TypeDependence::None), IsUnsigned(IsUnsigned), NumBits(NumBits) {} -DependentBitIntType::DependentBitIntType(const ASTContext &Context, - bool IsUnsigned, Expr *NumBitsExpr) +DependentBitIntType::DependentBitIntType(bool IsUnsigned, Expr *NumBitsExpr) : Type(DependentBitInt, QualType{}, toTypeDependence(NumBitsExpr->getDependence())), - Context(Context), ExprAndUnsigned(NumBitsExpr, IsUnsigned) {} + ExprAndUnsigned(NumBitsExpr, IsUnsigned) {} bool DependentBitIntType::isUnsigned() const { return ExprAndUnsigned.getInt(); @@ -3726,8 +3723,8 @@ QualType DecltypeType::desugar() const { return QualType(this, 0); } -DependentDecltypeType::DependentDecltypeType(const ASTContext &Context, Expr *E) - : DecltypeType(E, Context.DependentTy), Context(Context) {} +DependentDecltypeType::DependentDecltypeType(Expr *E, QualType UnderlyingType) + : DecltypeType(E, UnderlyingType) {} void DependentDecltypeType::Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, Expr *E) { diff --git a/clang/lib/Analysis/Consumed.cpp b/clang/lib/Analysis/Consumed.cpp index d90a8a966b210b..d01c7f688e8b5d 100644 --- a/clang/lib/Analysis/Consumed.cpp +++ b/clang/lib/Analysis/Consumed.cpp @@ -771,7 +771,7 @@ void ConsumedStmtVisitor::VisitCXXBindTemporaryExpr( void ConsumedStmtVisitor::VisitCXXConstructExpr(const CXXConstructExpr *Call) { CXXConstructorDecl *Constructor = Call->getConstructor(); - QualType ThisType = Constructor->getThisObjectType(); + QualType ThisType = Constructor->getFunctionObjectParameterType(); if (!isConsumableType(ThisType)) return; @@ -1199,7 +1199,7 @@ void ConsumedAnalyzer::determineExpectedReturnState(AnalysisDeclContext &AC, const FunctionDecl *D) { QualType ReturnType; if (const auto *Constructor = dyn_cast(D)) { - ReturnType = Constructor->getThisObjectType(); + ReturnType = Constructor->getFunctionObjectParameterType(); } else ReturnType = D->getCallResultType(); diff --git a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp index 1ea40927ac58ad..66d98c99546859 100644 --- a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp +++ b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp @@ -452,8 +452,8 @@ Environment::Environment(DataflowAnalysisContext &DACtx, MethodDecl = dyn_cast(Parent->getDeclContext()); // FIXME: Initialize the ThisPointeeLoc of lambdas too. - if (MethodDecl && !MethodDecl->isStatic()) { - QualType ThisPointeeType = MethodDecl->getThisObjectType(); + if (MethodDecl && MethodDecl->isImplicitObjectMemberFunction()) { + QualType ThisPointeeType = MethodDecl->getFunctionObjectParameterType(); ThisPointeeLoc = &cast(createValue(ThisPointeeType))->getLoc(); } diff --git a/clang/lib/Analysis/FlowSensitive/HTMLLogger.cpp b/clang/lib/Analysis/FlowSensitive/HTMLLogger.cpp index 47915958750d1f..8aef1d6f46089d 100644 --- a/clang/lib/Analysis/FlowSensitive/HTMLLogger.cpp +++ b/clang/lib/Analysis/FlowSensitive/HTMLLogger.cpp @@ -150,6 +150,7 @@ class HTMLLogger : public Logger { const CFGBlock *Block; unsigned Iter; bool PostVisit; + bool Converged; }; StreamFactory Streams; @@ -159,8 +160,8 @@ class HTMLLogger : public Logger { const ControlFlowContext *CFG; // Timeline of iterations of CFG block visitation. std::vector Iters; - // Number of times each CFG block has been seen. - llvm::DenseMap> BlockIters; + // Indexes in `Iters` of the iterations for each block. + llvm::DenseMap> BlockIters; // The messages logged in the current context but not yet written. std::string ContextLogs; // The number of elements we have visited within the current CFG block. @@ -207,6 +208,7 @@ class HTMLLogger : public Logger { JOS->attribute("block", blockID(E.Block->getBlockID())); JOS->attribute("iter", E.Iter); JOS->attribute("post_visit", E.PostVisit); + JOS->attribute("converged", E.Converged); }); } }); @@ -222,10 +224,10 @@ class HTMLLogger : public Logger { } void enterBlock(const CFGBlock &B, bool PostVisit) override { - llvm::SmallVector &BIter = BlockIters[&B]; + llvm::SmallVector &BIter = BlockIters[&B]; unsigned IterNum = BIter.size() + 1; - BIter.push_back({&B, IterNum, PostVisit}); - Iters.push_back({&B, IterNum, PostVisit}); + BIter.push_back(Iters.size()); + Iters.push_back({&B, IterNum, PostVisit, /*Converged=*/false}); ElementIndex = 0; } void enterElement(const CFGElement &E) override { @@ -290,7 +292,7 @@ class HTMLLogger : public Logger { } }); } - void blockConverged() override { logText("Block converged"); } + void blockConverged() override { Iters.back().Converged = true; } void logText(llvm::StringRef S) override { ContextLogs.append(S.begin(), S.end()); @@ -301,13 +303,15 @@ class HTMLLogger : public Logger { // Write the CFG block details. // Currently this is just the list of elements in execution order. // FIXME: an AST dump would be a useful view, too. - void writeBlock(const CFGBlock &B, llvm::ArrayRef ItersForB) { + void writeBlock(const CFGBlock &B, llvm::ArrayRef ItersForB) { JOS->attributeObject(blockID(B.getBlockID()), [&] { JOS->attributeArray("iters", [&] { - for (const auto &Iter : ItersForB) { + for (size_t IterIdx : ItersForB) { + const Iteration &Iter = Iters[IterIdx]; JOS->object([&] { JOS->attribute("iter", Iter.Iter); JOS->attribute("post_visit", Iter.PostVisit); + JOS->attribute("converged", Iter.Converged); }); } }); diff --git a/clang/lib/Analysis/FlowSensitive/HTMLLogger.html b/clang/lib/Analysis/FlowSensitive/HTMLLogger.html index 6d866d57e14486..ec9d74c71d35d9 100644 --- a/clang/lib/Analysis/FlowSensitive/HTMLLogger.html +++ b/clang/lib/Analysis/FlowSensitive/HTMLLogger.html @@ -45,6 +45,7 @@ {{entry.block}} + @@ -62,6 +63,7 @@ + diff --git a/clang/lib/Analysis/FlowSensitive/Transfer.cpp b/clang/lib/Analysis/FlowSensitive/Transfer.cpp index 6c92b847cd1d28..bb26e9f8dc8db8 100644 --- a/clang/lib/Analysis/FlowSensitive/Transfer.cpp +++ b/clang/lib/Analysis/FlowSensitive/Transfer.cpp @@ -525,7 +525,9 @@ class TransferVisitor : public ConstStmtVisitor { // The assignment operators are different from the type of the destination // in this model (i.e. in one of their base classes). This must be very // rare and we just bail. - if (Method->getThisObjectType().getCanonicalType().getUnqualifiedType() != + if (Method->getFunctionObjectParameterType() + .getCanonicalType() + .getUnqualifiedType() != LocDst->getType().getCanonicalType().getUnqualifiedType()) return; diff --git a/clang/lib/Analysis/ThreadSafety.cpp b/clang/lib/Analysis/ThreadSafety.cpp index 58dd7113665b13..54d0e95c6bd79a 100644 --- a/clang/lib/Analysis/ThreadSafety.cpp +++ b/clang/lib/Analysis/ThreadSafety.cpp @@ -1008,7 +1008,7 @@ class ThreadSafetyAnalyzer { threadSafety::SExprBuilder SxBuilder; ThreadSafetyHandler &Handler; - const CXXMethodDecl *CurrentMethod = nullptr; + const FunctionDecl *CurrentFunction; LocalVariableMap LocalVarMap; FactManager FactMan; std::vector BlockInfo; @@ -1243,10 +1243,10 @@ bool ThreadSafetyAnalyzer::inCurrentScope(const CapabilityExpr &CapE) { // Members are in scope from methods of the same class. if (const auto *P = dyn_cast(SExp)) { - if (!CurrentMethod) + if (!isa_and_nonnull(CurrentFunction)) return false; const ValueDecl *VD = P->clangDecl(); - return VD->getDeclContext() == CurrentMethod->getDeclContext(); + return VD->getDeclContext() == CurrentFunction->getDeclContext(); } return false; @@ -1541,6 +1541,8 @@ class BuildLockset : public ConstStmtVisitor { ThreadSafetyAnalyzer *Analyzer; FactSet FSet; + // The fact set for the function on exit. + const FactSet &FunctionExitFSet; /// Maps constructed objects to `this` placeholder prior to initialization. llvm::SmallDenseMap ConstructedObjects; LocalVariableMap::Context LVarCtx; @@ -1566,9 +1568,11 @@ class BuildLockset : public ConstStmtVisitor { bool SkipFirstParam = false); public: - BuildLockset(ThreadSafetyAnalyzer *Anlzr, CFGBlockInfo &Info) + BuildLockset(ThreadSafetyAnalyzer *Anlzr, CFGBlockInfo &Info, + const FactSet &FunctionExitFSet) : ConstStmtVisitor(), Analyzer(Anlzr), FSet(Info.EntrySet), - LVarCtx(Info.EntryContext), CtxIndex(Info.EntryIndex) {} + FunctionExitFSet(FunctionExitFSet), LVarCtx(Info.EntryContext), + CtxIndex(Info.EntryIndex) {} void VisitUnaryOperator(const UnaryOperator *UO); void VisitBinaryOperator(const BinaryOperator *BO); @@ -1577,6 +1581,7 @@ class BuildLockset : public ConstStmtVisitor { void VisitCXXConstructExpr(const CXXConstructExpr *Exp); void VisitDeclStmt(const DeclStmt *S); void VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *Exp); + void VisitReturnStmt(const ReturnStmt *S); }; } // namespace @@ -1758,6 +1763,8 @@ void ThreadSafetyAnalyzer::checkPtAccess(const FactSet &FSet, const Expr *Exp, // Pass by reference warnings are under a different flag. ProtectedOperationKind PtPOK = POK_VarDereference; if (POK == POK_PassByRef) PtPOK = POK_PtPassByRef; + if (POK == POK_ReturnByRef) + PtPOK = POK_PtReturnByRef; const ValueDecl *D = getValueDecl(Exp); if (!D || !D->hasAttrs()) @@ -2142,6 +2149,25 @@ void BuildLockset::VisitMaterializeTemporaryExpr( } } +void BuildLockset::VisitReturnStmt(const ReturnStmt *S) { + if (Analyzer->CurrentFunction == nullptr) + return; + const Expr *RetVal = S->getRetValue(); + if (!RetVal) + return; + + // If returning by reference, check that the function requires the appropriate + // capabilities. + const QualType ReturnType = + Analyzer->CurrentFunction->getReturnType().getCanonicalType(); + if (ReturnType->isLValueReferenceType()) { + Analyzer->checkAccess( + FunctionExitFSet, RetVal, + ReturnType->getPointeeType().isConstQualified() ? AK_Read : AK_Written, + POK_ReturnByRef); + } +} + /// Given two facts merging on a join point, possibly warn and decide whether to /// keep or replace. /// @@ -2251,8 +2277,7 @@ void ThreadSafetyAnalyzer::runAnalysis(AnalysisDeclContext &AC) { CFG *CFGraph = walker.getGraph(); const NamedDecl *D = walker.getDecl(); - const auto *CurrentFunction = dyn_cast(D); - CurrentMethod = dyn_cast(D); + CurrentFunction = dyn_cast(D); if (D->hasAttr()) return; @@ -2278,7 +2303,7 @@ void ThreadSafetyAnalyzer::runAnalysis(AnalysisDeclContext &AC) { PostOrderCFGView::CFGBlockSet VisitedBlocks(CFGraph); CFGBlockInfo &Initial = BlockInfo[CFGraph->getEntry().getBlockID()]; - CFGBlockInfo &Final = BlockInfo[CFGraph->getExit().getBlockID()]; + CFGBlockInfo &Final = BlockInfo[CFGraph->getExit().getBlockID()]; // Mark entry block as reachable Initial.Reachable = true; @@ -2348,6 +2373,25 @@ void ThreadSafetyAnalyzer::runAnalysis(AnalysisDeclContext &AC) { } } + // Compute the expected exit set. + // By default, we expect all locks held on entry to be held on exit. + FactSet ExpectedFunctionExitSet = Initial.EntrySet; + + // Adjust the expected exit set by adding or removing locks, as declared + // by *-LOCK_FUNCTION and UNLOCK_FUNCTION. The intersect below will then + // issue the appropriate warning. + // FIXME: the location here is not quite right. + for (const auto &Lock : ExclusiveLocksAcquired) + ExpectedFunctionExitSet.addLock( + FactMan, std::make_unique(Lock, LK_Exclusive, + D->getLocation())); + for (const auto &Lock : SharedLocksAcquired) + ExpectedFunctionExitSet.addLock( + FactMan, + std::make_unique(Lock, LK_Shared, D->getLocation())); + for (const auto &Lock : LocksReleased) + ExpectedFunctionExitSet.removeLock(FactMan, Lock); + for (const auto *CurrBlock : *SortedGraph) { unsigned CurrBlockID = CurrBlock->getBlockID(); CFGBlockInfo *CurrBlockInfo = &BlockInfo[CurrBlockID]; @@ -2407,7 +2451,7 @@ void ThreadSafetyAnalyzer::runAnalysis(AnalysisDeclContext &AC) { if (!CurrBlockInfo->Reachable) continue; - BuildLockset LocksetBuilder(this, *CurrBlockInfo); + BuildLockset LocksetBuilder(this, *CurrBlockInfo, ExpectedFunctionExitSet); // Visit all the statements in the basic block. for (const auto &BI : *CurrBlock) { @@ -2483,24 +2527,8 @@ void ThreadSafetyAnalyzer::runAnalysis(AnalysisDeclContext &AC) { if (!Final.Reachable) return; - // By default, we expect all locks held on entry to be held on exit. - FactSet ExpectedExitSet = Initial.EntrySet; - - // Adjust the expected exit set by adding or removing locks, as declared - // by *-LOCK_FUNCTION and UNLOCK_FUNCTION. The intersect below will then - // issue the appropriate warning. - // FIXME: the location here is not quite right. - for (const auto &Lock : ExclusiveLocksAcquired) - ExpectedExitSet.addLock(FactMan, std::make_unique( - Lock, LK_Exclusive, D->getLocation())); - for (const auto &Lock : SharedLocksAcquired) - ExpectedExitSet.addLock(FactMan, std::make_unique( - Lock, LK_Shared, D->getLocation())); - for (const auto &Lock : LocksReleased) - ExpectedExitSet.removeLock(FactMan, Lock); - // FIXME: Should we call this function for all blocks which exit the function? - intersectAndWarn(ExpectedExitSet, Final.ExitSet, Final.ExitLoc, + intersectAndWarn(ExpectedFunctionExitSet, Final.ExitSet, Final.ExitLoc, LEK_LockedAtEndOfFunction, LEK_NotLockedAtEndOfFunction); Handler.leaveFunction(CurrentFunction); diff --git a/clang/lib/Analysis/ThreadSafetyCommon.cpp b/clang/lib/Analysis/ThreadSafetyCommon.cpp index 63cc66852a9eb7..2fe0f85897c3bc 100644 --- a/clang/lib/Analysis/ThreadSafetyCommon.cpp +++ b/clang/lib/Analysis/ThreadSafetyCommon.cpp @@ -154,7 +154,9 @@ CapabilityExpr SExprBuilder::translateAttrExpr(const Expr *AttrExp, // If the attribute has no arguments, then assume the argument is "this". if (!AttrExp) return CapabilityExpr( - Self, ClassifyDiagnostic(cast(D)->getThisObjectType()), + Self, + ClassifyDiagnostic( + cast(D)->getFunctionObjectParameterType()), false); else // For most attributes. return translateAttrExpr(AttrExp, &Ctx); diff --git a/clang/lib/Basic/Diagnostic.cpp b/clang/lib/Basic/Diagnostic.cpp index 7a54d27ef9d8ee..0208ccc31bd7fc 100644 --- a/clang/lib/Basic/Diagnostic.cpp +++ b/clang/lib/Basic/Diagnostic.cpp @@ -800,9 +800,10 @@ FormatDiagnostic(SmallVectorImpl &OutStr) const { FormatDiagnostic(Diag.begin(), Diag.end(), OutStr); } -/// pushEscapedString - Append Str to the diagnostic buffer, +/// EscapeStringForDiagnostic - Append Str to the diagnostic buffer, /// escaping non-printable characters and ill-formed code unit sequences. -static void pushEscapedString(StringRef Str, SmallVectorImpl &OutStr) { +void clang::EscapeStringForDiagnostic(StringRef Str, + SmallVectorImpl &OutStr) { OutStr.reserve(OutStr.size() + Str.size()); auto *Begin = reinterpret_cast(Str.data()); llvm::raw_svector_ostream OutStream(OutStr); @@ -854,7 +855,7 @@ FormatDiagnostic(const char *DiagStr, const char *DiagEnd, StringRef(DiagStr, DiagEnd - DiagStr).equals("%0") && getArgKind(0) == DiagnosticsEngine::ak_std_string) { const std::string &S = getArgStdStr(0); - pushEscapedString(S, OutStr); + EscapeStringForDiagnostic(S, OutStr); return; } @@ -961,7 +962,7 @@ FormatDiagnostic(const char *DiagStr, const char *DiagEnd, case DiagnosticsEngine::ak_std_string: { const std::string &S = getArgStdStr(ArgNo); assert(ModifierLen == 0 && "No modifiers for strings yet"); - pushEscapedString(S, OutStr); + EscapeStringForDiagnostic(S, OutStr); break; } case DiagnosticsEngine::ak_c_string: { @@ -971,7 +972,7 @@ FormatDiagnostic(const char *DiagStr, const char *DiagEnd, // Don't crash if get passed a null pointer by accident. if (!S) S = "(null)"; - pushEscapedString(S, OutStr); + EscapeStringForDiagnostic(S, OutStr); break; } // ---- INTEGERS ---- diff --git a/clang/lib/Basic/Module.cpp b/clang/lib/Basic/Module.cpp index 0455304ef7f2b1..7879a11179b6d4 100644 --- a/clang/lib/Basic/Module.cpp +++ b/clang/lib/Basic/Module.cpp @@ -299,8 +299,10 @@ bool Module::directlyUses(const Module *Requested) { if (Requested->isSubModuleOf(Use)) return true; - // Anyone is allowed to use our builtin stddef.h and its accompanying module. - if (!Requested->Parent && Requested->Name == "_Builtin_stddef_max_align_t") + // Anyone is allowed to use our builtin stdarg.h and stddef.h and their + // accompanying modules. + if (Requested->getTopLevelModuleName() == "_Builtin_stdarg" || + Requested->getTopLevelModuleName() == "_Builtin_stddef") return true; if (NoUndeclaredIncludes) diff --git a/clang/lib/Basic/SourceManager.cpp b/clang/lib/Basic/SourceManager.cpp index 3066cc53dbfd87..7312f0514e72fd 100644 --- a/clang/lib/Basic/SourceManager.cpp +++ b/clang/lib/Basic/SourceManager.cpp @@ -527,17 +527,6 @@ FileID SourceManager::getNextFileID(FileID FID) const { /// Create a new FileID that represents the specified file /// being \#included from the specified IncludePosition. -/// -/// This translates NULL into standard input. -FileID SourceManager::createFileID(const FileEntry *SourceFile, - SourceLocation IncludePos, - SrcMgr::CharacteristicKind FileCharacter, - int LoadedID, - SourceLocation::UIntTy LoadedOffset) { - return createFileID(SourceFile->getLastRef(), IncludePos, FileCharacter, - LoadedID, LoadedOffset); -} - FileID SourceManager::createFileID(FileEntryRef SourceFile, SourceLocation IncludePos, SrcMgr::CharacteristicKind FileCharacter, @@ -585,7 +574,7 @@ FileID SourceManager::createFileID(const llvm::MemoryBufferRef &Buffer, /// Get the FileID for \p SourceFile if it exists. Otherwise, create a /// new FileID for the \p SourceFile. FileID -SourceManager::getOrCreateFileID(const FileEntry *SourceFile, +SourceManager::getOrCreateFileID(FileEntryRef SourceFile, SrcMgr::CharacteristicKind FileCharacter) { FileID ID = translateFile(SourceFile); return ID.isValid() ? ID : createFileID(SourceFile, SourceLocation(), @@ -2375,8 +2364,9 @@ SourceManagerForFile::SourceManagerForFile(StringRef FileName, IntrusiveRefCntPtr(new DiagnosticIDs), new DiagnosticOptions); SourceMgr = std::make_unique(*Diagnostics, *FileMgr); - FileID ID = SourceMgr->createFileID(*FileMgr->getFile(FileName), - SourceLocation(), clang::SrcMgr::C_User); + FileEntryRef FE = llvm::cantFail(FileMgr->getFileRef(FileName)); + FileID ID = + SourceMgr->createFileID(FE, SourceLocation(), clang::SrcMgr::C_User); assert(ID.isValid()); SourceMgr->setMainFileID(ID); } diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp index b0fe8e03aa0f5f..d066819871dfde 100644 --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -923,6 +923,9 @@ void EmitAssemblyHelper::RunOptimizationPipeline( PB.crossRegisterProxies(LAM, FAM, CGAM, MAM); ModulePassManager MPM; + // Add a verifier pass, before any other passes, to catch CodeGen issues. + if (CodeGenOpts.VerifyModule) + MPM.addPass(VerifierPass()); if (!CodeGenOpts.DisableLLVMPasses) { // Map our optimization levels into one of the distinct levels used to @@ -1020,21 +1023,23 @@ void EmitAssemblyHelper::RunOptimizationPipeline( } if (CodeGenOpts.FatLTO) { - MPM = PB.buildFatLTODefaultPipeline(Level, PrepareForThinLTO, - PrepareForThinLTO || - shouldEmitRegularLTOSummary()); + MPM.addPass(PB.buildFatLTODefaultPipeline( + Level, PrepareForThinLTO, + PrepareForThinLTO || shouldEmitRegularLTOSummary())); } else if (PrepareForThinLTO) { - MPM = PB.buildThinLTOPreLinkDefaultPipeline(Level); + MPM.addPass(PB.buildThinLTOPreLinkDefaultPipeline(Level)); } else if (PrepareForLTO) { - MPM = PB.buildLTOPreLinkDefaultPipeline(Level); + MPM.addPass(PB.buildLTOPreLinkDefaultPipeline(Level)); } else { - MPM = PB.buildPerModuleDefaultPipeline(Level); + MPM.addPass(PB.buildPerModuleDefaultPipeline(Level)); } } // Add a verifier pass if requested. We don't have to do this if the action // requires code generation because there will already be a verifier pass in // the code-generation pipeline. + // Since we already added a verifier pass above, this + // might even not run the analysis, if previous passes caused no changes. if (!actionRequiresCodeGen(Action) && CodeGenOpts.VerifyModule) MPM.addPass(VerifierPass()); diff --git a/clang/lib/CodeGen/CGBlocks.cpp b/clang/lib/CodeGen/CGBlocks.cpp index aa3e730d28efae..27f525ee35edbf 100644 --- a/clang/lib/CodeGen/CGBlocks.cpp +++ b/clang/lib/CodeGen/CGBlocks.cpp @@ -1710,7 +1710,7 @@ static std::string getBlockCaptureStr(const CGBlockInfo::Capture &Cap, Str += "c"; SmallString<256> TyStr; llvm::raw_svector_ostream Out(TyStr); - CGM.getCXXABI().getMangleContext().mangleTypeName(CaptureTy, Out); + CGM.getCXXABI().getMangleContext().mangleCanonicalTypeName(CaptureTy, Out); Str += llvm::to_string(TyStr.size()) + TyStr.c_str(); break; } diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 3f68aa2c953c74..bf984861bccb5c 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -853,6 +853,57 @@ CodeGenFunction::emitBuiltinObjectSize(const Expr *E, unsigned Type, } } + if (IsDynamic) { + LangOptions::StrictFlexArraysLevelKind StrictFlexArraysLevel = + getLangOpts().getStrictFlexArraysLevel(); + const Expr *Base = E->IgnoreParenImpCasts(); + + if (FieldDecl *FD = FindCountedByField(Base, StrictFlexArraysLevel)) { + const auto *ME = dyn_cast(Base); + llvm::Value *ObjectSize = nullptr; + + if (!ME) { + const auto *DRE = dyn_cast(Base); + ValueDecl *VD = nullptr; + + ObjectSize = ConstantInt::get( + ResType, + getContext().getTypeSize(DRE->getType()->getPointeeType()) / 8, + true); + + if (auto *RD = DRE->getType()->getPointeeType()->getAsRecordDecl()) + VD = RD->getLastField(); + + Expr *ICE = ImplicitCastExpr::Create( + getContext(), DRE->getType(), CK_LValueToRValue, + const_cast(cast(DRE)), nullptr, VK_PRValue, + FPOptionsOverride()); + ME = MemberExpr::CreateImplicit(getContext(), ICE, true, VD, + VD->getType(), VK_LValue, OK_Ordinary); + } + + // At this point, we know that \p ME is a flexible array member. + const auto *ArrayTy = getContext().getAsArrayType(ME->getType()); + unsigned Size = getContext().getTypeSize(ArrayTy->getElementType()); + + llvm::Value *CountField = + EmitAnyExprToTemp(MemberExpr::CreateImplicit( + getContext(), const_cast(ME->getBase()), + ME->isArrow(), FD, FD->getType(), VK_LValue, + OK_Ordinary)) + .getScalarVal(); + + llvm::Value *Mul = Builder.CreateMul( + CountField, llvm::ConstantInt::get(CountField->getType(), Size / 8)); + Mul = Builder.CreateZExtOrTrunc(Mul, ResType); + + if (ObjectSize) + return Builder.CreateAdd(ObjectSize, Mul); + + return Mul; + } + } + // 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. diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 3fe8d0a7cf49e1..93e16575042c4d 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -298,7 +298,7 @@ CodeGenTypes::arrangeCXXMethodDeclaration(const CXXMethodDecl *MD) { setCUDAKernelCallingConvention(FT, CGM, MD); auto prototype = FT.getAs(); - if (MD->isInstance()) { + if (MD->isImplicitObjectMemberFunction()) { // The abstract case is perfectly fine. const CXXRecordDecl *ThisType = TheCXXABI.getThisArgumentTypeForMethod(MD); return arrangeCXXMethodType(ThisType, prototype.getTypePtr(), MD); @@ -448,7 +448,7 @@ CodeGenTypes::arrangeCXXConstructorCall(const CallArgList &args, const CGFunctionInfo & CodeGenTypes::arrangeFunctionDeclaration(const FunctionDecl *FD) { if (const CXXMethodDecl *MD = dyn_cast(FD)) - if (MD->isInstance()) + if (MD->isImplicitObjectMemberFunction()) return arrangeCXXMethodDeclaration(MD); CanQualType FTy = FD->getType()->getCanonicalTypeUnqualified(); diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp index e7ed3ec431f75b..d18f186ce5b415 100644 --- a/clang/lib/CodeGen/CGClass.cpp +++ b/clang/lib/CodeGen/CGClass.cpp @@ -28,6 +28,7 @@ #include "clang/CodeGen/CGFunctionInfo.h" #include "llvm/IR/Intrinsics.h" #include "llvm/IR/Metadata.h" +#include "llvm/Support/SaveAndRestore.h" #include "llvm/Transforms/Utils/SanitizerStats.h" #include @@ -138,7 +139,7 @@ Address CodeGenFunction::LoadCXXThisAddress() { CXXThisAlignment = CGM.getClassPointerAlignment(MD->getParent()); } - llvm::Type *Ty = ConvertType(MD->getThisObjectType()); + llvm::Type *Ty = ConvertType(MD->getFunctionObjectParameterType()); return Address(LoadCXXThis(), Ty, CXXThisAlignment, KnownNonNull); } @@ -510,7 +511,7 @@ namespace { const CXXDestructorDecl *D = BaseClass->getDestructor(); // We are already inside a destructor, so presumably the object being // destroyed should have the expected type. - QualType ThisTy = D->getThisObjectType(); + QualType ThisTy = D->getFunctionObjectParameterType(); Address Addr = CGF.GetAddressOfDirectBaseInCompleteClass(CGF.LoadCXXThisAddress(), DerivedClass, BaseClass, @@ -1291,10 +1292,10 @@ void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD, assert(BaseCtorContinueBB); } - llvm::Value *const OldThis = CXXThisValue; for (; B != E && (*B)->isBaseInitializer() && (*B)->isBaseVirtual(); B++) { if (!ConstructVBases) continue; + SaveAndRestore ThisRAII(CXXThisValue); if (CGM.getCodeGenOpts().StrictVTablePointers && CGM.getCodeGenOpts().OptimizationLevel > 0 && isInitializerOfDynamicClass(*B)) @@ -1311,7 +1312,7 @@ void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD, // Then, non-virtual base initializers. for (; B != E && (*B)->isBaseInitializer(); B++) { assert(!(*B)->isBaseVirtual()); - + SaveAndRestore ThisRAII(CXXThisValue); if (CGM.getCodeGenOpts().StrictVTablePointers && CGM.getCodeGenOpts().OptimizationLevel > 0 && isInitializerOfDynamicClass(*B)) @@ -1319,8 +1320,6 @@ void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD, EmitBaseInitializer(*this, ClassDecl, *B); } - CXXThisValue = OldThis; - InitializeVTablePointers(ClassDecl); // And finally, initialize class members. @@ -1456,7 +1455,7 @@ void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) { RunCleanupsScope DtorEpilogue(*this); EnterDtorCleanups(Dtor, Dtor_Deleting); if (HaveInsertPoint()) { - QualType ThisTy = Dtor->getThisObjectType(); + QualType ThisTy = Dtor->getFunctionObjectParameterType(); EmitCXXDestructorCall(Dtor, Dtor_Complete, /*ForVirtualBase=*/false, /*Delegating=*/false, LoadCXXThisAddress(), ThisTy); } @@ -1490,7 +1489,7 @@ void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) { EnterDtorCleanups(Dtor, Dtor_Complete); if (!isTryBody) { - QualType ThisTy = Dtor->getThisObjectType(); + QualType ThisTy = Dtor->getFunctionObjectParameterType(); EmitCXXDestructorCall(Dtor, Dtor_Base, /*ForVirtualBase=*/false, /*Delegating=*/false, LoadCXXThisAddress(), ThisTy); break; @@ -2114,7 +2113,7 @@ void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D, CallArgList Args; Address This = ThisAVS.getAddress(); LangAS SlotAS = ThisAVS.getQualifiers().getAddressSpace(); - LangAS ThisAS = D->getThisObjectType().getAddressSpace(); + LangAS ThisAS = D->getFunctionObjectParameterType().getAddressSpace(); llvm::Value *ThisPtr = This.getPointer(); if (SlotAS != ThisAS) { @@ -2453,7 +2452,7 @@ namespace { void Emit(CodeGenFunction &CGF, Flags flags) override { // We are calling the destructor from within the constructor. // Therefore, "this" should have the expected type. - QualType ThisTy = Dtor->getThisObjectType(); + QualType ThisTy = Dtor->getFunctionObjectParameterType(); CGF.EmitCXXDestructorCall(Dtor, Type, /*ForVirtualBase=*/false, /*Delegating=*/true, Addr, ThisTy); } diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index 36e29285141b59..c73a63e12f03aa 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -2130,14 +2130,14 @@ CGDebugInfo::CollectTemplateParams(std::optional OArgs, // attribute, i.e. that value is not available at the host side. if (!CGM.getLangOpts().CUDA || CGM.getLangOpts().CUDAIsDevice || !D->hasAttr()) { - const CXXMethodDecl *MD; // Variable pointer template parameters have a value that is the address // of the variable. if (const auto *VD = dyn_cast(D)) V = CGM.GetAddrOfGlobalVar(VD); // Member function pointers have special support for building them, // though this is currently unsupported in LLVM CodeGen. - else if ((MD = dyn_cast(D)) && MD->isInstance()) + else if (const auto *MD = dyn_cast(D); + MD && MD->isImplicitObjectMemberFunction()) V = CGM.getCXXABI().EmitMemberFunctionPointer(MD); else if (const auto *FD = dyn_cast(D)) V = CGM.GetAddrOfFunction(FD); diff --git a/clang/lib/CodeGen/CGDeclCXX.cpp b/clang/lib/CodeGen/CGDeclCXX.cpp index 8a05e4893196ad..30683ad474cd2c 100644 --- a/clang/lib/CodeGen/CGDeclCXX.cpp +++ b/clang/lib/CodeGen/CGDeclCXX.cpp @@ -666,13 +666,13 @@ void CodeGenModule::EmitCXXModuleInitFunc(Module *Primary) { // Module initializers for imported modules are emitted first. // Collect all the modules that we import - SmallVector AllImports; + llvm::SmallSetVector AllImports; // Ones that we export for (auto I : Primary->Exports) - AllImports.push_back(I.getPointer()); + AllImports.insert(I.getPointer()); // Ones that we only import. for (Module *M : Primary->Imports) - AllImports.push_back(M); + AllImports.insert(M); // Ones that we import in the global module fragment or the private module // fragment. llvm::for_each(Primary->submodules(), [&AllImports](Module *SubM) { @@ -683,7 +683,7 @@ void CodeGenModule::EmitCXXModuleInitFunc(Module *Primary) { "The global mdoule fragments and the private module fragments are " "not allowed to export import modules."); for (Module *M : SubM->Imports) - AllImports.push_back(M); + AllImports.insert(M); }); SmallVector ModuleInits; diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 7b4389c874b3f9..54a1d300a9ac73 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -30,6 +30,7 @@ #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" @@ -931,16 +932,31 @@ 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. } + + if (FieldDecl *FD = CGF.FindCountedByField(Base, StrictFlexArraysLevel)) { + const auto *ME = dyn_cast(CE->getSubExpr()); + IndexedType = Base->getType(); + return CGF + .EmitAnyExprToTemp(MemberExpr::CreateImplicit( + CGF.getContext(), const_cast(ME->getBase()), + ME->isArrow(), FD, FD->getType(), VK_LValue, OK_Ordinary)) + .getScalarVal(); + } } + CodeGenFunction::SanitizerScope SanScope(&CGF); + QualType EltTy{Base->getType()->getPointeeOrArrayElementType(), 0}; if (llvm::Value *POS = CGF.LoadPassedObjectSize(Base, EltTy)) { IndexedType = Base->getType(); @@ -950,13 +966,53 @@ static llvm::Value *getArrayIndexingBound(CodeGenFunction &CGF, return nullptr; } +FieldDecl *CodeGenFunction::FindCountedByField( + const Expr *Base, + LangOptions::StrictFlexArraysLevelKind StrictFlexArraysLevel) { + const ValueDecl *VD = nullptr; + + Base = Base->IgnoreParenImpCasts(); + + if (const auto *ME = dyn_cast(Base)) { + VD = dyn_cast(ME->getMemberDecl()); + } else if (const auto *DRE = dyn_cast(Base)) { + // Pointing to the full structure. + VD = dyn_cast(DRE->getDecl()); + + QualType Ty = VD->getType(); + if (Ty->isPointerType()) + Ty = Ty->getPointeeType(); + + if (const auto *RD = Ty->getAsRecordDecl()) + VD = RD->getLastField(); + } else if (const auto *CE = dyn_cast(Base)) { + if (const auto *ME = dyn_cast(CE->getSubExpr())) + VD = dyn_cast(ME->getMemberDecl()); + } + + const auto *FD = dyn_cast_if_present(VD); + if (!FD || !FD->getParent() || + !Decl::isFlexibleArrayMemberLike(getContext(), FD, FD->getType(), + StrictFlexArraysLevel, true)) + return nullptr; + + const auto *CBA = FD->getAttr(); + if (!CBA) + return nullptr; + + StringRef FieldName = CBA->getCountedByField()->getName(); + auto It = + llvm::find_if(FD->getParent()->fields(), [&](const FieldDecl *Field) { + return FieldName == Field->getName(); + }); + return It != FD->getParent()->field_end() ? *It : nullptr; +} + 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(); @@ -966,6 +1022,8 @@ void CodeGenFunction::EmitBoundsCheck(const Expr *E, const Expr *Base, 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); @@ -2647,9 +2705,8 @@ static LValue EmitFunctionDeclLValue(CodeGenFunction &CGF, const Expr *E, static LValue EmitCapturedFieldLValue(CodeGenFunction &CGF, const FieldDecl *FD, llvm::Value *ThisValue) { - QualType TagType = CGF.getContext().getTagDeclType(FD->getParent()); - LValue LV = CGF.MakeNaturalAlignAddrLValue(ThisValue, TagType); - return CGF.EmitLValueForField(LV, FD); + + return CGF.EmitLValueForLambdaField(FD, ThisValue); } /// Named Registers are named metadata pointing to the register name @@ -4262,17 +4319,38 @@ LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) { /// Given that we are currently emitting a lambda, emit an l-value for /// one of its members. -LValue CodeGenFunction::EmitLValueForLambdaField(const FieldDecl *Field) { - if (CurCodeDecl) { - assert(cast(CurCodeDecl)->getParent()->isLambda()); - assert(cast(CurCodeDecl)->getParent() == Field->getParent()); +/// +LValue CodeGenFunction::EmitLValueForLambdaField(const FieldDecl *Field, + llvm::Value *ThisValue) { + bool HasExplicitObjectParameter = false; + if (const auto *MD = dyn_cast_if_present(CurCodeDecl)) { + HasExplicitObjectParameter = MD->isExplicitObjectMemberFunction(); + assert(MD->getParent()->isLambda()); + assert(MD->getParent() == Field->getParent()); + } + LValue LambdaLV; + if (HasExplicitObjectParameter) { + const VarDecl *D = cast(CurCodeDecl)->getParamDecl(0); + auto It = LocalDeclMap.find(D); + assert(It != LocalDeclMap.end() && "explicit parameter not loaded?"); + Address AddrOfExplicitObject = It->getSecond(); + if (D->getType()->isReferenceType()) + LambdaLV = EmitLoadOfReferenceLValue(AddrOfExplicitObject, D->getType(), + AlignmentSource::Decl); + else + LambdaLV = MakeNaturalAlignAddrLValue(AddrOfExplicitObject.getPointer(), + D->getType().getNonReferenceType()); + } else { + QualType LambdaTagType = getContext().getTagDeclType(Field->getParent()); + LambdaLV = MakeNaturalAlignAddrLValue(ThisValue, LambdaTagType); } - QualType LambdaTagType = - getContext().getTagDeclType(Field->getParent()); - LValue LambdaLV = MakeNaturalAlignAddrLValue(CXXABIThisValue, LambdaTagType); return EmitLValueForField(LambdaLV, Field); } +LValue CodeGenFunction::EmitLValueForLambdaField(const FieldDecl *Field) { + return EmitLValueForLambdaField(Field, CXXABIThisValue); +} + /// Get the field index in the debug info. The debug info structure/union /// will ignore the unnamed bitfields. unsigned CodeGenFunction::getDebugInfoFIndex(const RecordDecl *Rec, @@ -4987,9 +5065,12 @@ RValue CodeGenFunction::EmitCallExpr(const CallExpr *E, if (const auto *CE = dyn_cast(E)) return EmitCUDAKernelCallExpr(CE, ReturnValue); + // A CXXOperatorCallExpr is created even for explicit object methods, but + // these should be treated like static function call. if (const auto *CE = dyn_cast(E)) - if (const CXXMethodDecl *MD = - dyn_cast_or_null(CE->getCalleeDecl())) + if (const auto *MD = + dyn_cast_if_present(CE->getCalleeDecl()); + MD && MD->isImplicitObjectMemberFunction()) return EmitCXXOperatorMemberCallExpr(CE, MD, ReturnValue); CGCallee callee = EmitCallee(E->getCallee()); diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp index 34d4f37a5d295f..2e7059cc8f5b63 100644 --- a/clang/lib/CodeGen/CGExprCXX.cpp +++ b/clang/lib/CodeGen/CGExprCXX.cpp @@ -41,7 +41,7 @@ commonEmitCXXMemberOrOperatorCall(CodeGenFunction &CGF, GlobalDecl GD, assert(CE == nullptr || isa(CE) || isa(CE)); - assert(MD->isInstance() && + assert(MD->isImplicitObjectMemberFunction() && "Trying to emit a member or operator call expr on a static method!"); // Push the this ptr. @@ -66,7 +66,12 @@ commonEmitCXXMemberOrOperatorCall(CodeGenFunction &CGF, GlobalDecl GD, Args.addFrom(*RtlArgs); } else if (CE) { // Special case: skip first argument of CXXOperatorCall (it is "this"). - unsigned ArgsToSkip = isa(CE) ? 1 : 0; + unsigned ArgsToSkip = 0; + if (const auto *Op = dyn_cast(CE)) { + if (const auto *M = dyn_cast(Op->getCalleeDecl())) + ArgsToSkip = + static_cast(!M->isExplicitObjectMemberFunction()); + } CGF.EmitCallArgs(Args, FPT, drop_begin(CE->arguments(), ArgsToSkip), CE->getDirectCallee()); } else { @@ -484,7 +489,7 @@ RValue CodeGenFunction::EmitCXXOperatorMemberCallExpr(const CXXOperatorCallExpr *E, const CXXMethodDecl *MD, ReturnValueSlot ReturnValue) { - assert(MD->isInstance() && + assert(MD->isImplicitObjectMemberFunction() && "Trying to emit a member call expr on a static method!"); return EmitCXXMemberOrOperatorMemberCallExpr( E, MD, ReturnValue, /*HasQualifier=*/false, /*Qualifier=*/nullptr, diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index d76ce15b41ac57..93ab064bdf3915 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -3723,10 +3723,12 @@ static Value *emitPointerArithmetic(CodeGenFunction &CGF, // Explicitly handle GNU void* and function pointer arithmetic extensions. The // GNU void* casts amount to no-ops since our void* type is i8*, but this is // future proof. + llvm::Type *elemTy; if (elementType->isVoidType() || elementType->isFunctionType()) - return CGF.Builder.CreateGEP(CGF.Int8Ty, pointer, index, "add.ptr"); + elemTy = CGF.Int8Ty; + else + elemTy = CGF.ConvertTypeForMem(elementType); - llvm::Type *elemTy = CGF.ConvertTypeForMem(elementType); if (CGF.getLangOpts().isSignedOverflowDefined()) return CGF.Builder.CreateGEP(elemTy, pointer, index, "add.ptr"); diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp index b4e482ca5cba6e..aae1a0ea250eea 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp @@ -7734,30 +7734,6 @@ class MappableExprsHandler { OpenMPOffloadMappingFlags::OMP_MAP_FROM; } - static OpenMPOffloadMappingFlags getMemberOfFlag(unsigned Position) { - // Rotate by getFlagMemberOffset() bits. - return static_cast(((uint64_t)Position + 1) - << getFlagMemberOffset()); - } - - static void setCorrectMemberOfFlag(OpenMPOffloadMappingFlags &Flags, - OpenMPOffloadMappingFlags MemberOfFlag) { - // If the entry is PTR_AND_OBJ but has not been marked with the special - // placeholder value 0xFFFF in the MEMBER_OF field, then it should not be - // marked as MEMBER_OF. - if (static_cast>( - Flags & OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ) && - static_cast>( - (Flags & OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF) != - OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF)) - return; - - // Reset the placeholder value to prepare the flag for the assignment of the - // proper MEMBER_OF value. - Flags &= ~OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF; - Flags |= MemberOfFlag; - } - void getPlainLayout(const CXXRecordDecl *RD, llvm::SmallVectorImpl &Layout, bool AsBase) const { @@ -7825,6 +7801,7 @@ class MappableExprsHandler { /// the device pointers info array. void generateAllInfoForClauses( ArrayRef Clauses, MapCombinedInfoTy &CombinedInfo, + llvm::OpenMPIRBuilder &OMPBuilder, const llvm::DenseSet> &SkipVarSet = llvm::DenseSet>()) const { // We have to process the component lists that relate with the same @@ -8159,7 +8136,7 @@ class MappableExprsHandler { if (PartialStruct.Base.isValid()) { CurInfo.NonContigInfo.Dims.push_back(0); emitCombinedEntry(CombinedInfo, CurInfo.Types, PartialStruct, - /*IsMapThis*/ !VD, VD); + /*IsMapThis*/ !VD, OMPBuilder, VD); } // We need to append the results of this capture to what we already @@ -8226,6 +8203,7 @@ class MappableExprsHandler { void emitCombinedEntry(MapCombinedInfoTy &CombinedInfo, MapFlagsArrayTy &CurTypes, const StructRangeInfoTy &PartialStruct, bool IsMapThis, + llvm::OpenMPIRBuilder &OMPBuilder, const ValueDecl *VD = nullptr, bool NotTargetParams = true) const { if (CurTypes.size() == 1 && @@ -8260,7 +8238,7 @@ class MappableExprsHandler { // of tofrom. // Emit this[:1] CombinedInfo.Pointers.push_back(PartialStruct.Base.getPointer()); - QualType Ty = MD->getThisObjectType(); + QualType Ty = MD->getFunctionObjectParameterType(); llvm::Value *Size = CGF.Builder.CreateIntCast(CGF.getTypeSize(Ty), CGF.Int64Ty, /*isSigned=*/true); @@ -8313,9 +8291,9 @@ class MappableExprsHandler { // (except for PTR_AND_OBJ entries which do not have a placeholder value // 0xFFFF in the MEMBER_OF field). OpenMPOffloadMappingFlags MemberOfFlag = - getMemberOfFlag(CombinedInfo.BasePointers.size() - 1); + OMPBuilder.getMemberOfFlag(CombinedInfo.BasePointers.size() - 1); for (auto &M : CurTypes) - setCorrectMemberOfFlag(M, MemberOfFlag); + OMPBuilder.setCorrectMemberOfFlag(M, MemberOfFlag); } /// Generate all the base pointers, section pointers, sizes, map types, and @@ -8324,23 +8302,26 @@ class MappableExprsHandler { /// pair of the relevant declaration and index where it occurs is appended to /// the device pointers info array. void generateAllInfo( - MapCombinedInfoTy &CombinedInfo, + MapCombinedInfoTy &CombinedInfo, llvm::OpenMPIRBuilder &OMPBuilder, const llvm::DenseSet> &SkipVarSet = llvm::DenseSet>()) const { assert(CurDir.is() && "Expect a executable directive"); const auto *CurExecDir = CurDir.get(); - generateAllInfoForClauses(CurExecDir->clauses(), CombinedInfo, SkipVarSet); + generateAllInfoForClauses(CurExecDir->clauses(), CombinedInfo, OMPBuilder, + SkipVarSet); } /// Generate all the base pointers, section pointers, sizes, map types, and /// mappers for the extracted map clauses of user-defined mapper (all included /// in \a CombinedInfo). - void generateAllInfoForMapper(MapCombinedInfoTy &CombinedInfo) const { + void generateAllInfoForMapper(MapCombinedInfoTy &CombinedInfo, + llvm::OpenMPIRBuilder &OMPBuilder) const { assert(CurDir.is() && "Expect a declare mapper directive"); const auto *CurMapperDir = CurDir.get(); - generateAllInfoForClauses(CurMapperDir->clauses(), CombinedInfo); + generateAllInfoForClauses(CurMapperDir->clauses(), CombinedInfo, + OMPBuilder); } /// Emit capture info for lambdas for variables captured by reference. @@ -8422,6 +8403,7 @@ class MappableExprsHandler { /// Set correct indices for lambdas captures. void adjustMemberOfForLambdaCaptures( + llvm::OpenMPIRBuilder &OMPBuilder, const llvm::DenseMap &LambdaPointers, MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers, MapFlagsArrayTy &Types) const { @@ -8446,8 +8428,9 @@ class MappableExprsHandler { // All other current entries will be MEMBER_OF the combined entry // (except for PTR_AND_OBJ entries which do not have a placeholder value // 0xFFFF in the MEMBER_OF field). - OpenMPOffloadMappingFlags MemberOfFlag = getMemberOfFlag(TgtIdx); - setCorrectMemberOfFlag(Types[I], MemberOfFlag); + OpenMPOffloadMappingFlags MemberOfFlag = + OMPBuilder.getMemberOfFlag(TgtIdx); + OMPBuilder.setCorrectMemberOfFlag(Types[I], MemberOfFlag); } } @@ -9069,7 +9052,7 @@ void CGOpenMPRuntime::emitUserDefinedMapper(const OMPDeclareMapperDecl *D, llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); SmallString<64> TyStr; llvm::raw_svector_ostream Out(TyStr); - CGM.getCXXABI().getMangleContext().mangleTypeName(Ty, Out); + CGM.getCXXABI().getMangleContext().mangleCanonicalTypeName(Ty, Out); std::string Name = getName({"omp_mapper", TyStr, D->getName()}); auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule()); @@ -9141,7 +9124,7 @@ void CGOpenMPRuntime::emitUserDefinedMapper(const OMPDeclareMapperDecl *D, // Get map clause information. Fill up the arrays with all mapped variables. MappableExprsHandler::MapCombinedInfoTy Info; MappableExprsHandler MEHandler(*D, MapperCGF); - MEHandler.generateAllInfoForMapper(Info); + MEHandler.generateAllInfoForMapper(Info, OMPBuilder); // Call the runtime API __tgt_mapper_num_components to get the number of // pre-existing components. @@ -9525,7 +9508,8 @@ static void emitTargetCallKernelLaunch( CombinedInfo.append(PartialStruct.PreliminaryMapData); MEHandler.emitCombinedEntry( CombinedInfo, CurInfo.Types, PartialStruct, CI->capturesThis(), - nullptr, !PartialStruct.PreliminaryMapData.BasePointers.empty()); + OMPBuilder, nullptr, + !PartialStruct.PreliminaryMapData.BasePointers.empty()); } // We need to append the results of this capture to what we already have. @@ -9533,11 +9517,11 @@ static void emitTargetCallKernelLaunch( } // Adjust MEMBER_OF flags for the lambdas captures. MEHandler.adjustMemberOfForLambdaCaptures( - LambdaPointers, CombinedInfo.BasePointers, CombinedInfo.Pointers, - CombinedInfo.Types); + OMPBuilder, LambdaPointers, CombinedInfo.BasePointers, + CombinedInfo.Pointers, CombinedInfo.Types); // Map any list items in a map clause that were not captures because they // weren't referenced within the construct. - MEHandler.generateAllInfo(CombinedInfo, MappedVarSet); + MEHandler.generateAllInfo(CombinedInfo, OMPBuilder, MappedVarSet); CGOpenMPRuntime::TargetDataInfo Info; // Fill up the arrays and create the arguments. @@ -10272,7 +10256,7 @@ void CGOpenMPRuntime::emitTargetDataCalls( CGF.Builder.restoreIP(CodeGenIP); // Get map clause information. MappableExprsHandler MEHandler(D, CGF); - MEHandler.generateAllInfo(CombinedInfo); + MEHandler.generateAllInfo(CombinedInfo, OMPBuilder); auto FillInfoMap = [&](MappableExprsHandler::MappingExprInfo &MapExpr) { return emitMappingInformation(CGF, OMPBuilder, MapExpr); @@ -10478,7 +10462,7 @@ void CGOpenMPRuntime::emitTargetDataStandAloneCall( // Get map clause information. MappableExprsHandler MEHandler(D, CGF); - MEHandler.generateAllInfo(CombinedInfo); + MEHandler.generateAllInfo(CombinedInfo, OMPBuilder); CGOpenMPRuntime::TargetDataInfo Info; // Fill up the arrays and create the arguments. diff --git a/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp b/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp index 93819ab815add0..56de8d39fe856d 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp @@ -551,10 +551,9 @@ CGOpenMPRuntimeGPU::getExecutionMode() const { return CurrentExecutionMode; } -static CGOpenMPRuntimeGPU::DataSharingMode -getDataSharingMode(CodeGenModule &CGM) { - return CGM.getLangOpts().OpenMPCUDAMode ? CGOpenMPRuntimeGPU::CUDA - : CGOpenMPRuntimeGPU::Generic; +CGOpenMPRuntimeGPU::DataSharingMode +CGOpenMPRuntimeGPU::getDataSharingMode() const { + return CurrentDataSharingMode; } /// Check for inner (nested) SPMD construct, if any @@ -752,6 +751,9 @@ void CGOpenMPRuntimeGPU::emitNonSPMDKernel(const OMPExecutableDirective &D, EntryFunctionState EST; WrapperFunctionsMap.clear(); + [[maybe_unused]] bool IsBareKernel = D.getSingleClause(); + assert(!IsBareKernel && "bare kernel should not be at generic mode"); + // Emit target region as a standalone region. class NVPTXPrePostActionTy : public PrePostActionTy { CGOpenMPRuntimeGPU::EntryFunctionState &EST; @@ -760,15 +762,13 @@ void CGOpenMPRuntimeGPU::emitNonSPMDKernel(const OMPExecutableDirective &D, NVPTXPrePostActionTy(CGOpenMPRuntimeGPU::EntryFunctionState &EST) : EST(EST) {} void Enter(CodeGenFunction &CGF) override { - auto &RT = - static_cast(CGF.CGM.getOpenMPRuntime()); + auto &RT = static_cast(CGF.CGM.getOpenMPRuntime()); RT.emitKernelInit(CGF, EST, /* IsSPMD */ false); // Skip target region initialization. RT.setLocThreadIdInsertPt(CGF, /*AtCurrentPoint=*/true); } void Exit(CodeGenFunction &CGF) override { - auto &RT = - static_cast(CGF.CGM.getOpenMPRuntime()); + auto &RT = static_cast(CGF.CGM.getOpenMPRuntime()); RT.clearLocThreadIdInsertPt(CGF); RT.emitKernelDeinit(CGF, EST, /* IsSPMD */ false); } @@ -807,25 +807,39 @@ void CGOpenMPRuntimeGPU::emitSPMDKernel(const OMPExecutableDirective &D, ExecutionRuntimeModesRAII ModeRAII(CurrentExecutionMode, EM_SPMD); EntryFunctionState EST; + bool IsBareKernel = D.getSingleClause(); + // Emit target region as a standalone region. class NVPTXPrePostActionTy : public PrePostActionTy { CGOpenMPRuntimeGPU &RT; CGOpenMPRuntimeGPU::EntryFunctionState &EST; + bool IsBareKernel; + DataSharingMode Mode; public: NVPTXPrePostActionTy(CGOpenMPRuntimeGPU &RT, - CGOpenMPRuntimeGPU::EntryFunctionState &EST) - : RT(RT), EST(EST) {} + CGOpenMPRuntimeGPU::EntryFunctionState &EST, + bool IsBareKernel) + : RT(RT), EST(EST), IsBareKernel(IsBareKernel), + Mode(RT.CurrentDataSharingMode) {} void Enter(CodeGenFunction &CGF) override { + if (IsBareKernel) { + RT.CurrentDataSharingMode = DataSharingMode::DS_CUDA; + return; + } RT.emitKernelInit(CGF, EST, /* IsSPMD */ true); // Skip target region initialization. RT.setLocThreadIdInsertPt(CGF, /*AtCurrentPoint=*/true); } void Exit(CodeGenFunction &CGF) override { + if (IsBareKernel) { + RT.CurrentDataSharingMode = Mode; + return; + } RT.clearLocThreadIdInsertPt(CGF); RT.emitKernelDeinit(CGF, EST, /* IsSPMD */ true); } - } Action(*this, EST); + } Action(*this, EST, IsBareKernel); CodeGen.setAction(Action); IsInTTDRegion = true; emitTargetOutlinedFunctionHelper(D, ParentName, OutlinedFn, OutlinedFnID, @@ -843,7 +857,8 @@ void CGOpenMPRuntimeGPU::emitTargetOutlinedFunction( assert(!ParentName.empty() && "Invalid target region parent name!"); bool Mode = supportsSPMDExecutionMode(CGM.getContext(), D); - if (Mode) + bool IsBareKernel = D.getSingleClause(); + if (Mode || IsBareKernel) emitSPMDKernel(D, ParentName, OutlinedFn, OutlinedFnID, IsOffloadEntry, CodeGen); else @@ -863,6 +878,9 @@ CGOpenMPRuntimeGPU::CGOpenMPRuntimeGPU(CodeGenModule &CGM) if (!CGM.getLangOpts().OpenMPIsTargetDevice) llvm_unreachable("OpenMP can only handle device code."); + if (CGM.getLangOpts().OpenMPCUDAMode) + CurrentDataSharingMode = CGOpenMPRuntimeGPU::DS_CUDA; + llvm::OpenMPIRBuilder &OMPBuilder = getOMPBuilder(); if (CGM.getLangOpts().NoGPULib || CGM.getLangOpts().OMPHostIRFile.empty()) return; @@ -1030,7 +1048,7 @@ llvm::Function *CGOpenMPRuntimeGPU::emitTeamsOutlinedFunction( void CGOpenMPRuntimeGPU::emitGenericVarsProlog(CodeGenFunction &CGF, SourceLocation Loc, bool WithSPMDCheck) { - if (getDataSharingMode(CGM) != CGOpenMPRuntimeGPU::Generic && + if (getDataSharingMode() != CGOpenMPRuntimeGPU::DS_Generic && getExecutionMode() != CGOpenMPRuntimeGPU::EM_SPMD) return; @@ -1142,7 +1160,7 @@ void CGOpenMPRuntimeGPU::getKmpcFreeShared( void CGOpenMPRuntimeGPU::emitGenericVarsEpilog(CodeGenFunction &CGF, bool WithSPMDCheck) { - if (getDataSharingMode(CGM) != CGOpenMPRuntimeGPU::Generic && + if (getDataSharingMode() != CGOpenMPRuntimeGPU::DS_Generic && getExecutionMode() != CGOpenMPRuntimeGPU::EM_SPMD) return; @@ -1178,11 +1196,18 @@ void CGOpenMPRuntimeGPU::emitTeamsCall(CodeGenFunction &CGF, if (!CGF.HaveInsertPoint()) return; + bool IsBareKernel = D.getSingleClause(); + Address ZeroAddr = CGF.CreateDefaultAlignTempAlloca(CGF.Int32Ty, /*Name=*/".zero.addr"); CGF.Builder.CreateStore(CGF.Builder.getInt32(/*C*/ 0), ZeroAddr); llvm::SmallVector OutlinedFnArgs; - OutlinedFnArgs.push_back(emitThreadIDAddress(CGF, Loc).getPointer()); + // We don't emit any thread id function call in bare kernel, but because the + // outlined function has a pointer argument, we emit a nullptr here. + if (IsBareKernel) + OutlinedFnArgs.push_back(llvm::ConstantPointerNull::get(CGM.VoidPtrTy)); + else + OutlinedFnArgs.push_back(emitThreadIDAddress(CGF, Loc).getPointer()); OutlinedFnArgs.push_back(ZeroAddr.getPointer()); OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end()); emitOutlinedFunctionCall(CGF, Loc, OutlinedFn, OutlinedFnArgs); @@ -3273,7 +3298,7 @@ llvm::Function *CGOpenMPRuntimeGPU::createParallelDataSharingWrapper( void CGOpenMPRuntimeGPU::emitFunctionProlog(CodeGenFunction &CGF, const Decl *D) { - if (getDataSharingMode(CGM) != CGOpenMPRuntimeGPU::Generic) + if (getDataSharingMode() != CGOpenMPRuntimeGPU::DS_Generic) return; assert(D && "Expected function or captured|block decl."); @@ -3382,7 +3407,7 @@ Address CGOpenMPRuntimeGPU::getAddressOfLocalVariable(CodeGenFunction &CGF, VarTy, Align); } - if (getDataSharingMode(CGM) != CGOpenMPRuntimeGPU::Generic) + if (getDataSharingMode() != CGOpenMPRuntimeGPU::DS_Generic) return Address::invalid(); VD = VD->getCanonicalDecl(); diff --git a/clang/lib/CodeGen/CGOpenMPRuntimeGPU.h b/clang/lib/CodeGen/CGOpenMPRuntimeGPU.h index dddfe5a94dccb8..86871dfce418fd 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntimeGPU.h +++ b/clang/lib/CodeGen/CGOpenMPRuntimeGPU.h @@ -32,6 +32,18 @@ class CGOpenMPRuntimeGPU : public CGOpenMPRuntime { /// Unknown execution mode (orphaned directive). EM_Unknown, }; + + /// Target codegen is specialized based on two data-sharing modes: CUDA, in + /// which the local variables are actually global threadlocal, and Generic, in + /// which the local variables are placed in global memory if they may escape + /// their declaration context. + enum DataSharingMode { + /// CUDA data sharing mode. + DS_CUDA, + /// Generic data-sharing mode. + DS_Generic, + }; + private: /// Parallel outlined function work for workers to execute. llvm::SmallVector Work; @@ -42,6 +54,8 @@ class CGOpenMPRuntimeGPU : public CGOpenMPRuntime { ExecutionMode getExecutionMode() const; + DataSharingMode getDataSharingMode() const; + /// Get barrier to synchronize all threads in a block. void syncCTAThreads(CodeGenFunction &CGF); @@ -297,17 +311,6 @@ class CGOpenMPRuntimeGPU : public CGOpenMPRuntime { Address getAddressOfLocalVariable(CodeGenFunction &CGF, const VarDecl *VD) override; - /// Target codegen is specialized based on two data-sharing modes: CUDA, in - /// which the local variables are actually global threadlocal, and Generic, in - /// which the local variables are placed in global memory if they may escape - /// their declaration context. - enum DataSharingMode { - /// CUDA data sharing mode. - CUDA, - /// Generic data-sharing mode. - Generic, - }; - /// Cleans up references to the objects in finished function. /// void functionFinished(CodeGenFunction &CGF) override; @@ -343,6 +346,10 @@ class CGOpenMPRuntimeGPU : public CGOpenMPRuntime { /// to emit optimized code. ExecutionMode CurrentExecutionMode = EM_Unknown; + /// Track the data sharing mode when codegening directives within a target + /// region. + DataSharingMode CurrentDataSharingMode = DataSharingMode::DS_Generic; + /// true if currently emitting code for target/teams/distribute region, false /// - otherwise. bool IsInTTDRegion = false; diff --git a/clang/lib/CodeGen/CGVTables.cpp b/clang/lib/CodeGen/CGVTables.cpp index 23cfcdd138439f..25e4b1c2793202 100644 --- a/clang/lib/CodeGen/CGVTables.cpp +++ b/clang/lib/CodeGen/CGVTables.cpp @@ -24,6 +24,7 @@ #include "llvm/Transforms/Utils/Cloning.h" #include #include +#include using namespace clang; using namespace CodeGen; @@ -201,7 +202,7 @@ CodeGenFunction::GenerateVarArgsThunk(llvm::Function *Fn, // Find the first store of "this", which will be to the alloca associated // with "this". Address ThisPtr = - Address(&*AI, ConvertTypeForMem(MD->getThisObjectType()), + Address(&*AI, ConvertTypeForMem(MD->getFunctionObjectParameterType()), CGM.getClassPointerAlignment(MD->getParent())); llvm::BasicBlock *EntryBB = &Fn->front(); llvm::BasicBlock::iterator ThisStore = @@ -639,8 +640,16 @@ void CodeGenVTables::addRelativeComponent(ConstantArrayBuilder &builder, // want the stub/proxy to be emitted for properly calculating the offset. // Examples where there would be no symbol emitted are available_externally // and private linkages. - auto stubLinkage = vtableHasLocalLinkage ? llvm::GlobalValue::InternalLinkage - : llvm::GlobalValue::ExternalLinkage; + // + // `internal` linkage results in STB_LOCAL Elf binding while still manifesting a + // local symbol. + // + // `linkonce_odr` linkage results in a STB_DEFAULT Elf binding but also allows for + // the rtti_proxy to be transparently replaced with a GOTPCREL reloc by a + // target that supports this replacement. + auto stubLinkage = vtableHasLocalLinkage + ? llvm::GlobalValue::InternalLinkage + : llvm::GlobalValue::LinkOnceODRLinkage; llvm::Constant *target; if (auto *func = dyn_cast(globalVal)) { @@ -1308,43 +1317,34 @@ void CodeGenModule::EmitVTableTypeMetadata(const CXXRecordDecl *RD, CharUnits ComponentWidth = GetTargetTypeStoreSize(getVTableComponentType()); - typedef std::pair AddressPoint; + struct AddressPoint { + const CXXRecordDecl *Base; + size_t Offset; + std::string TypeName; + bool operator<(const AddressPoint &RHS) const { + int D = TypeName.compare(RHS.TypeName); + return D < 0 || (D == 0 && Offset < RHS.Offset); + } + }; std::vector AddressPoints; - for (auto &&AP : VTLayout.getAddressPoints()) - AddressPoints.push_back(std::make_pair( - AP.first.getBase(), VTLayout.getVTableOffset(AP.second.VTableIndex) + - AP.second.AddressPointIndex)); + for (auto &&AP : VTLayout.getAddressPoints()) { + AddressPoint N{AP.first.getBase(), + VTLayout.getVTableOffset(AP.second.VTableIndex) + + AP.second.AddressPointIndex, + {}}; + llvm::raw_string_ostream Stream(N.TypeName); + getCXXABI().getMangleContext().mangleCanonicalTypeName( + QualType(N.Base->getTypeForDecl(), 0), Stream); + AddressPoints.push_back(std::move(N)); + } // Sort the address points for determinism. - llvm::sort(AddressPoints, [this](const AddressPoint &AP1, - const AddressPoint &AP2) { - if (&AP1 == &AP2) - return false; - - std::string S1; - llvm::raw_string_ostream O1(S1); - getCXXABI().getMangleContext().mangleTypeName( - QualType(AP1.first->getTypeForDecl(), 0), O1); - O1.flush(); - - std::string S2; - llvm::raw_string_ostream O2(S2); - getCXXABI().getMangleContext().mangleTypeName( - QualType(AP2.first->getTypeForDecl(), 0), O2); - O2.flush(); - - if (S1 < S2) - return true; - if (S1 != S2) - return false; - - return AP1.second < AP2.second; - }); + llvm::sort(AddressPoints); ArrayRef Comps = VTLayout.vtable_components(); for (auto AP : AddressPoints) { // Create type metadata for the address point. - AddVTableTypeMetadata(VTable, ComponentWidth * AP.second, AP.first); + AddVTableTypeMetadata(VTable, ComponentWidth * AP.Offset, AP.Base); // The class associated with each address point could also potentially be // used for indirect calls via a member function pointer, so we need to @@ -1356,7 +1356,7 @@ void CodeGenModule::EmitVTableTypeMetadata(const CXXRecordDecl *RD, llvm::Metadata *MD = CreateMetadataIdentifierForVirtualMemPtrType( Context.getMemberPointerType( Comps[I].getFunctionDecl()->getType(), - Context.getRecordType(AP.first).getTypePtr())); + Context.getRecordType(AP.Base).getTypePtr())); VTable->addTypeMetadata((ComponentWidth * I).getQuantity(), MD); } } diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index bf83171e2c6814..9b21f428b0af7f 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -576,7 +576,7 @@ CodeGenFunction::getUBSanFunctionTypeHash(QualType Ty) const { Ty = getContext().getFunctionTypeWithExceptionSpec(Ty, EST_None); std::string Mangled; llvm::raw_string_ostream Out(Mangled); - CGM.getCXXABI().getMangleContext().mangleTypeName(Ty, Out, false); + CGM.getCXXABI().getMangleContext().mangleCanonicalTypeName(Ty, Out, false); return llvm::ConstantInt::get( CGM.Int32Ty, static_cast(llvm::xxh3_64bits(Mangled))); } @@ -1167,12 +1167,13 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy, EmitFunctionProlog(*CurFnInfo, CurFn, Args); - if (isa_and_nonnull(D) && - cast(D)->isInstance()) { - CGM.getCXXABI().EmitInstanceFunctionProlog(*this); - const CXXMethodDecl *MD = cast(D); - if (MD->getParent()->isLambda() && - MD->getOverloadedOperator() == OO_Call) { + if (const CXXMethodDecl *MD = dyn_cast_if_present(D); + MD && !MD->isStatic()) { + bool IsInLambda = + MD->getParent()->isLambda() && MD->getOverloadedOperator() == OO_Call; + if (MD->isImplicitObjectMemberFunction()) + CGM.getCXXABI().EmitInstanceFunctionProlog(*this); + if (IsInLambda) { // We're in a lambda; figure out the captures. MD->getParent()->getCaptureFields(LambdaCaptureFields, LambdaThisCaptureField); @@ -1202,7 +1203,7 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy, VLASizeMap[VAT->getSizeExpr()] = ExprArg; } } - } else { + } else if (MD->isImplicitObjectMemberFunction()) { // Not in a lambda; just use 'this' from the method. // FIXME: Should we generate a new load for each use of 'this'? The // fast register allocator would be happier... @@ -1313,7 +1314,7 @@ QualType CodeGenFunction::BuildFunctionArgList(GlobalDecl GD, QualType ResTy = FD->getReturnType(); const CXXMethodDecl *MD = dyn_cast(FD); - if (MD && MD->isInstance()) { + if (MD && MD->isImplicitObjectMemberFunction()) { if (CGM.getCXXABI().HasThisReturn(GD)) ResTy = MD->getThisType(); else if (CGM.getCXXABI().hasMostDerivedReturn(GD)) diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 60f2f21de53ab9..d5336382a2b9c9 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -3022,6 +3022,12 @@ class CodeGenFunction : public CodeGenTypeCache { void EmitBoundsCheck(const Expr *E, const Expr *Base, llvm::Value *Index, QualType IndexType, bool Accessed); + /// Find the FieldDecl specified in a FAM's "counted_by" attribute. Returns + /// \p nullptr if either the attribute or the field doesn't exist. + FieldDecl *FindCountedByField( + const Expr *Base, + LangOptions::StrictFlexArraysLevelKind StrictFlexArraysLevel); + llvm::Value *EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV, bool isInc, bool isPre); ComplexPairTy EmitComplexPrePostIncDec(const UnaryOperator *E, LValue LV, @@ -4017,6 +4023,8 @@ class CodeGenFunction : public CodeGenTypeCache { const ObjCIvarDecl *Ivar); LValue EmitLValueForField(LValue Base, const FieldDecl* Field); LValue EmitLValueForLambdaField(const FieldDecl *Field); + LValue EmitLValueForLambdaField(const FieldDecl *Field, + llvm::Value *ThisValue); /// EmitLValueForFieldInitialization - Like EmitLValueForField, except that /// if the Field is a reference, this will return the address of the reference diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index c96523c5256258..cae9dd93bc5592 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -1390,6 +1390,19 @@ void CodeGenModule::setGlobalVisibility(llvm::GlobalValue *GV, } if (!D) return; + + // OpenMP declare target variables must be visible to the host so they can + // be registered. We require protected visibility unless the variable has + // the DT_nohost modifier and does not need to be registered. + if (Context.getLangOpts().OpenMP && + Context.getLangOpts().OpenMPIsTargetDevice && isa(D) && + D->hasAttr() && + D->getAttr()->getDevType() != + OMPDeclareTargetDeclAttr::DT_NoHost) { + GV->setVisibility(llvm::GlobalValue::ProtectedVisibility); + return; + } + // Set visibility for definitions, and for declarations if requested globally // or set explicitly. LinkageInfo LV = D->getLinkageAndVisibility(); @@ -2006,7 +2019,7 @@ llvm::ConstantInt *CodeGenModule::CreateKCFITypeId(QualType T) { std::string OutName; llvm::raw_string_ostream Out(OutName); - getCXXABI().getMangleContext().mangleTypeName( + getCXXABI().getMangleContext().mangleCanonicalTypeName( T, Out, getCodeGenOpts().SanitizeCfiICallNormalizeIntegers); if (getCodeGenOpts().SanitizeCfiICallNormalizeIntegers) @@ -2246,8 +2259,8 @@ static bool requiresMemberFunctionPointerTypeMetadata(CodeGenModule &CGM, // Only functions whose address can be taken with a member function pointer // need this sort of type metadata. - return !MD->isStatic() && !MD->isVirtual() && !isa(MD) && - !isa(MD); + return MD->isImplicitObjectMemberFunction() && !MD->isVirtual() && + !isa(MD); } SmallVector @@ -2938,6 +2951,9 @@ void CodeGenModule::EmitModuleInitializers(clang::Module *Primary) { // Third any associated with the Privat eMOdule Fragment, if present. if (auto PMF = Primary->getPrivateModuleFragment()) { for (Decl *D : getContext().getModuleInitializers(PMF)) { + // Skip import decls, the inits for those are called explicitly. + if (isa(D)) + continue; assert(isa(D) && "PMF initializer decl is not a var?"); EmitTopLevelDecl(D); } @@ -4787,7 +4803,8 @@ CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName, llvm::Type *Ty, assert(getContext().getTargetAddressSpace(ExpectedAS) == TargetAS); if (DAddrSpace != ExpectedAS) { return getTargetCodeGenInfo().performAddrSpaceCast( - *this, GV, DAddrSpace, ExpectedAS, Ty->getPointerTo(TargetAS)); + *this, GV, DAddrSpace, ExpectedAS, + llvm::PointerType::get(getLLVMContext(), TargetAS)); } return GV; @@ -4999,7 +5016,8 @@ castStringLiteralToDefaultAddressSpace(CodeGenModule &CGM, if (AS != LangAS::Default) Cast = CGM.getTargetCodeGenInfo().performAddrSpaceCast( CGM, GV, AS, LangAS::Default, - GV->getValueType()->getPointerTo( + llvm::PointerType::get( + CGM.getLLVMContext(), CGM.getContext().getTargetAddressSpace(LangAS::Default))); } return Cast; @@ -6374,7 +6392,8 @@ ConstantAddress CodeGenModule::GetAddrOfGlobalTemporary( if (AddrSpace != LangAS::Default) CV = getTargetCodeGenInfo().performAddrSpaceCast( *this, GV, AddrSpace, LangAS::Default, - Type->getPointerTo( + llvm::PointerType::get( + getLLVMContext(), getContext().getTargetAddressSpace(LangAS::Default))); // Update the map with the new temporary. If we created a placeholder above, @@ -7200,7 +7219,7 @@ CodeGenModule::CreateMetadataIdentifierImpl(QualType T, MetadataTypeMap &Map, if (isExternallyVisible(T->getLinkage())) { std::string OutName; llvm::raw_string_ostream Out(OutName); - getCXXABI().getMangleContext().mangleTypeName( + getCXXABI().getMangleContext().mangleCanonicalTypeName( T, Out, getCodeGenOpts().SanitizeCfiICallNormalizeIntegers); if (getCodeGenOpts().SanitizeCfiICallNormalizeIntegers) diff --git a/clang/lib/CodeGen/CodeGenTBAA.cpp b/clang/lib/CodeGen/CodeGenTBAA.cpp index 395ed7b1d703a5..8705d3d65f1a57 100644 --- a/clang/lib/CodeGen/CodeGenTBAA.cpp +++ b/clang/lib/CodeGen/CodeGenTBAA.cpp @@ -205,7 +205,7 @@ llvm::MDNode *CodeGenTBAA::getTypeInfoHelper(const Type *Ty) { SmallString<256> OutName; llvm::raw_svector_ostream Out(OutName); - MContext.mangleTypeName(QualType(ETy, 0), Out); + MContext.mangleCanonicalTypeName(QualType(ETy, 0), Out); return createScalarTypeNode(OutName, getChar(), Size); } @@ -391,7 +391,7 @@ llvm::MDNode *CodeGenTBAA::getBaseTypeInfoHelper(const Type *Ty) { if (Features.CPlusPlus) { // Don't use the mangler for C code. llvm::raw_svector_ostream Out(OutName); - MContext.mangleTypeName(QualType(Ty, 0), Out); + MContext.mangleCanonicalTypeName(QualType(Ty, 0), Out); } else { OutName = RD->getName(); } diff --git a/clang/lib/CodeGen/Targets/AMDGPU.cpp b/clang/lib/CodeGen/Targets/AMDGPU.cpp index dc628b7345f59f..f6a614b3e4d54d 100644 --- a/clang/lib/CodeGen/Targets/AMDGPU.cpp +++ b/clang/lib/CodeGen/Targets/AMDGPU.cpp @@ -308,12 +308,13 @@ static bool requiresAMDGPUProtectedVisibility(const Decl *D, if (GV->getVisibility() != llvm::GlobalValue::HiddenVisibility) return false; - return D->hasAttr() || - (isa(D) && D->hasAttr()) || - (isa(D) && - (D->hasAttr() || D->hasAttr() || - cast(D)->getType()->isCUDADeviceBuiltinSurfaceType() || - cast(D)->getType()->isCUDADeviceBuiltinTextureType())); + return !D->hasAttr() && + (D->hasAttr() || + (isa(D) && D->hasAttr()) || + (isa(D) && + (D->hasAttr() || D->hasAttr() || + cast(D)->getType()->isCUDADeviceBuiltinSurfaceType() || + cast(D)->getType()->isCUDADeviceBuiltinTextureType()))); } void AMDGPUTargetCodeGenInfo::setFunctionDeclAttributes( diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index 84b8fc7685fed4..77328e1f99e502 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -767,7 +767,8 @@ void Driver::CreateOffloadingDeviceToolChains(Compilation &C, [](std::pair &I) { return types::isHIP(I.first); }) || - C.getInputArgs().hasArg(options::OPT_hip_link); + C.getInputArgs().hasArg(options::OPT_hip_link) || + C.getInputArgs().hasArg(options::OPT_hipstdpar); if (IsCuda && IsHIP) { Diag(clang::diag::err_drv_mix_cuda_hip); return; @@ -2705,6 +2706,10 @@ void Driver::BuildInputs(const ToolChain &TC, DerivedArgList &Args, } } + if ((Ty == types::TY_C || Ty == types::TY_CXX) && + Args.hasArgNoClaim(options::OPT_hipstdpar)) + Ty = types::TY_HIP; + if (DiagnoseInputExistence(Args, Value, Ty, /*TypoCorrect=*/true)) Inputs.push_back(std::make_pair(Ty, A)); @@ -3915,6 +3920,11 @@ void Driver::handleArguments(Compilation &C, DerivedArgList &Args, phases::ID FinalPhase = getFinalPhase(Args, &FinalPhaseArg); if (FinalPhase == phases::Link) { + if (Args.hasArgNoClaim(options::OPT_hipstdpar)) { + Args.AddFlagArg(nullptr, getOpts().getOption(options::OPT_hip_link)); + Args.AddFlagArg(nullptr, + getOpts().getOption(options::OPT_frtlib_add_rpath)); + } // Emitting LLVM while linking disabled except in HIPAMD Toolchain if (Args.hasArg(options::OPT_emit_llvm) && !Args.hasArg(options::OPT_hip_link)) Diag(clang::diag::err_drv_emit_llvm_link); diff --git a/clang/lib/Driver/OffloadBundler.cpp b/clang/lib/Driver/OffloadBundler.cpp index d11c41605bf39e..0ad9de299603ba 100644 --- a/clang/lib/Driver/OffloadBundler.cpp +++ b/clang/lib/Driver/OffloadBundler.cpp @@ -21,24 +21,29 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" +#include "llvm/BinaryFormat/Magic.h" #include "llvm/Object/Archive.h" #include "llvm/Object/ArchiveWriter.h" #include "llvm/Object/Binary.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/Casting.h" +#include "llvm/Support/Compression.h" #include "llvm/Support/Debug.h" #include "llvm/Support/EndianStream.h" #include "llvm/Support/Errc.h" #include "llvm/Support/Error.h" #include "llvm/Support/ErrorOr.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/MD5.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" #include "llvm/Support/Program.h" #include "llvm/Support/Signals.h" #include "llvm/Support/StringSaver.h" +#include "llvm/Support/Timer.h" #include "llvm/Support/WithColor.h" #include "llvm/Support/raw_ostream.h" #include "llvm/TargetParser/Host.h" @@ -48,6 +53,7 @@ #include #include #include +#include #include #include #include @@ -58,6 +64,10 @@ using namespace llvm; using namespace llvm::object; using namespace clang; +static llvm::TimerGroup + ClangOffloadBundlerTimerGroup("Clang Offload Bundler Timer Group", + "Timer group for clang offload bundler"); + /// Magic string that marks the existence of offloading data. #define OFFLOAD_BUNDLER_MAGIC_STR "__CLANG_OFFLOAD_BUNDLE__" @@ -224,20 +234,22 @@ class FileHandler { /// Write the header of the bundled file to \a OS based on the information /// gathered from \a Inputs. - virtual Error WriteHeader(raw_fd_ostream &OS, + virtual Error WriteHeader(raw_ostream &OS, ArrayRef> Inputs) = 0; /// Write the marker that initiates a bundle for the triple \a TargetTriple to /// \a OS. - virtual Error WriteBundleStart(raw_fd_ostream &OS, - StringRef TargetTriple) = 0; + virtual Error WriteBundleStart(raw_ostream &OS, StringRef TargetTriple) = 0; /// Write the marker that closes a bundle for the triple \a TargetTriple to \a /// OS. - virtual Error WriteBundleEnd(raw_fd_ostream &OS, StringRef TargetTriple) = 0; + virtual Error WriteBundleEnd(raw_ostream &OS, StringRef TargetTriple) = 0; /// Write the bundle from \a Input into \a OS. - virtual Error WriteBundle(raw_fd_ostream &OS, MemoryBuffer &Input) = 0; + virtual Error WriteBundle(raw_ostream &OS, MemoryBuffer &Input) = 0; + + /// Finalize output file. + virtual Error finalizeOutputFile() { return Error::success(); } /// List bundle IDs in \a Input. virtual Error listBundleIDs(MemoryBuffer &Input) { @@ -311,7 +323,7 @@ static uint64_t Read8byteIntegerFromBuffer(StringRef Buffer, size_t pos) { } /// Write 8-byte integers to a buffer in little-endian format. -static void Write8byteIntegerToBuffer(raw_fd_ostream &OS, uint64_t Val) { +static void Write8byteIntegerToBuffer(raw_ostream &OS, uint64_t Val) { llvm::support::endian::write(OS, Val, llvm::support::little); } @@ -359,8 +371,7 @@ class BinaryFileHandler final : public FileHandler { return Error::success(); // Check if no magic was found. - StringRef Magic(FC.data(), sizeof(OFFLOAD_BUNDLER_MAGIC_STR) - 1); - if (!Magic.equals(OFFLOAD_BUNDLER_MAGIC_STR)) + if (llvm::identify_magic(FC) != llvm::file_magic::offload_bundle) return Error::success(); // Read number of bundles. @@ -435,7 +446,7 @@ class BinaryFileHandler final : public FileHandler { return Error::success(); } - Error WriteHeader(raw_fd_ostream &OS, + Error WriteHeader(raw_ostream &OS, ArrayRef> Inputs) final { // Compute size of the header. @@ -472,19 +483,27 @@ class BinaryFileHandler final : public FileHandler { return Error::success(); } - Error WriteBundleStart(raw_fd_ostream &OS, StringRef TargetTriple) final { + Error WriteBundleStart(raw_ostream &OS, StringRef TargetTriple) final { CurWriteBundleTarget = TargetTriple.str(); return Error::success(); } - Error WriteBundleEnd(raw_fd_ostream &OS, StringRef TargetTriple) final { + Error WriteBundleEnd(raw_ostream &OS, StringRef TargetTriple) final { return Error::success(); } - Error WriteBundle(raw_fd_ostream &OS, MemoryBuffer &Input) final { + Error WriteBundle(raw_ostream &OS, MemoryBuffer &Input) final { auto BI = BundlesInfo[CurWriteBundleTarget]; - OS.seek(BI.Offset); + + // Pad with 0 to reach specified offset. + size_t CurrentPos = OS.tell(); + size_t PaddingSize = BI.Offset > CurrentPos ? BI.Offset - CurrentPos : 0; + for (size_t I = 0; I < PaddingSize; ++I) + OS.write('\0'); + assert(OS.tell() == BI.Offset); + OS.write(Input.getBufferStart(), Input.getBufferSize()); + return Error::success(); } }; @@ -541,7 +560,7 @@ class ObjectFileHandler final : public FileHandler { return NameOrErr.takeError(); // If it does not start with the reserved suffix, just skip this section. - if (!NameOrErr->startswith(OFFLOAD_BUNDLER_MAGIC_STR)) + if (llvm::identify_magic(*NameOrErr) != llvm::file_magic::offload_bundle) return std::nullopt; // Return the triple that is right after the reserved prefix. @@ -607,7 +626,7 @@ class ObjectFileHandler final : public FileHandler { return Error::success(); } - Error WriteHeader(raw_fd_ostream &OS, + Error WriteHeader(raw_ostream &OS, ArrayRef> Inputs) final { assert(BundlerConfig.HostInputIndex != ~0u && "Host input index not defined."); @@ -617,12 +636,16 @@ class ObjectFileHandler final : public FileHandler { return Error::success(); } - Error WriteBundleStart(raw_fd_ostream &OS, StringRef TargetTriple) final { + Error WriteBundleStart(raw_ostream &OS, StringRef TargetTriple) final { ++NumberOfProcessedInputs; return Error::success(); } - Error WriteBundleEnd(raw_fd_ostream &OS, StringRef TargetTriple) final { + Error WriteBundleEnd(raw_ostream &OS, StringRef TargetTriple) final { + return Error::success(); + } + + Error finalizeOutputFile() final { assert(NumberOfProcessedInputs <= NumberOfInputs && "Processing more inputs that actually exist!"); assert(BundlerConfig.HostInputIndex != ~0u && @@ -640,10 +663,6 @@ class ObjectFileHandler final : public FileHandler { assert(BundlerConfig.ObjcopyPath != "" && "llvm-objcopy path not specified"); - // We write to the output file directly. So, we close it and use the name - // to pass down to llvm-objcopy. - OS.close(); - // Temporary files that need to be removed. TempFileHandlerRAII TempFiles; @@ -684,7 +703,7 @@ class ObjectFileHandler final : public FileHandler { return Error::success(); } - Error WriteBundle(raw_fd_ostream &OS, MemoryBuffer &Input) final { + Error WriteBundle(raw_ostream &OS, MemoryBuffer &Input) final { return Error::success(); } @@ -781,22 +800,22 @@ class TextFileHandler final : public FileHandler { return Error::success(); } - Error WriteHeader(raw_fd_ostream &OS, + Error WriteHeader(raw_ostream &OS, ArrayRef> Inputs) final { return Error::success(); } - Error WriteBundleStart(raw_fd_ostream &OS, StringRef TargetTriple) final { + Error WriteBundleStart(raw_ostream &OS, StringRef TargetTriple) final { OS << BundleStartString << TargetTriple << "\n"; return Error::success(); } - Error WriteBundleEnd(raw_fd_ostream &OS, StringRef TargetTriple) final { + Error WriteBundleEnd(raw_ostream &OS, StringRef TargetTriple) final { OS << BundleEndString << TargetTriple << "\n"; return Error::success(); } - Error WriteBundle(raw_fd_ostream &OS, MemoryBuffer &Input) final { + Error WriteBundle(raw_ostream &OS, MemoryBuffer &Input) final { OS << Input.getBuffer(); return Error::success(); } @@ -881,6 +900,187 @@ CreateFileHandler(MemoryBuffer &FirstInput, "'" + FilesType + "': invalid file type specified"); } +OffloadBundlerConfig::OffloadBundlerConfig() { + auto IgnoreEnvVarOpt = + llvm::sys::Process::GetEnv("OFFLOAD_BUNDLER_IGNORE_ENV_VAR"); + if (IgnoreEnvVarOpt.has_value() && IgnoreEnvVarOpt.value() == "1") + return; + + auto VerboseEnvVarOpt = llvm::sys::Process::GetEnv("OFFLOAD_BUNDLER_VERBOSE"); + if (VerboseEnvVarOpt.has_value()) + Verbose = VerboseEnvVarOpt.value() == "1"; + + auto CompressEnvVarOpt = + llvm::sys::Process::GetEnv("OFFLOAD_BUNDLER_COMPRESS"); + if (CompressEnvVarOpt.has_value()) + Compress = CompressEnvVarOpt.value() == "1"; +} + +llvm::Expected> +CompressedOffloadBundle::compress(const llvm::MemoryBuffer &Input, + bool Verbose) { + llvm::Timer HashTimer("Hash Calculation Timer", "Hash calculation time", + ClangOffloadBundlerTimerGroup); + if (Verbose) + HashTimer.startTimer(); + llvm::MD5 Hash; + llvm::MD5::MD5Result Result; + Hash.update(Input.getBuffer()); + Hash.final(Result); + uint64_t TruncatedHash = Result.low(); + if (Verbose) + HashTimer.stopTimer(); + + SmallVector CompressedBuffer; + auto BufferUint8 = llvm::ArrayRef( + reinterpret_cast(Input.getBuffer().data()), + Input.getBuffer().size()); + + llvm::compression::Format CompressionFormat; + + if (llvm::compression::zstd::isAvailable()) + CompressionFormat = llvm::compression::Format::Zstd; + else if (llvm::compression::zlib::isAvailable()) + CompressionFormat = llvm::compression::Format::Zlib; + else + return createStringError(llvm::inconvertibleErrorCode(), + "Compression not supported"); + + llvm::Timer CompressTimer("Compression Timer", "Compression time", + ClangOffloadBundlerTimerGroup); + if (Verbose) + CompressTimer.startTimer(); + llvm::compression::compress(CompressionFormat, BufferUint8, CompressedBuffer); + if (Verbose) + CompressTimer.stopTimer(); + + uint16_t CompressionMethod = static_cast(CompressionFormat); + uint32_t UncompressedSize = Input.getBuffer().size(); + + SmallVector FinalBuffer; + llvm::raw_svector_ostream OS(FinalBuffer); + OS << MagicNumber; + OS.write(reinterpret_cast(&Version), sizeof(Version)); + OS.write(reinterpret_cast(&CompressionMethod), + sizeof(CompressionMethod)); + OS.write(reinterpret_cast(&UncompressedSize), + sizeof(UncompressedSize)); + OS.write(reinterpret_cast(&TruncatedHash), + sizeof(TruncatedHash)); + OS.write(reinterpret_cast(CompressedBuffer.data()), + CompressedBuffer.size()); + + if (Verbose) { + auto MethodUsed = + CompressionFormat == llvm::compression::Format::Zstd ? "zstd" : "zlib"; + llvm::errs() << "Compressed bundle format version: " << Version << "\n" + << "Compression method used: " << MethodUsed << "\n" + << "Binary size before compression: " << UncompressedSize + << " bytes\n" + << "Binary size after compression: " << CompressedBuffer.size() + << " bytes\n" + << "Truncated MD5 hash: " + << llvm::format_hex(TruncatedHash, 16) << "\n"; + } + + return llvm::MemoryBuffer::getMemBufferCopy( + llvm::StringRef(FinalBuffer.data(), FinalBuffer.size())); +} + +llvm::Expected> +CompressedOffloadBundle::decompress(const llvm::MemoryBuffer &Input, + bool Verbose) { + + StringRef Blob = Input.getBuffer(); + + if (Blob.size() < HeaderSize) { + return llvm::MemoryBuffer::getMemBufferCopy(Blob); + } + if (llvm::identify_magic(Blob) != + llvm::file_magic::offload_bundle_compressed) { + if (Verbose) + llvm::errs() << "Uncompressed bundle.\n"; + return llvm::MemoryBuffer::getMemBufferCopy(Blob); + } + + uint16_t ThisVersion; + uint16_t CompressionMethod; + uint32_t UncompressedSize; + uint64_t StoredHash; + memcpy(&ThisVersion, Input.getBuffer().data() + MagicNumber.size(), + sizeof(uint16_t)); + memcpy(&CompressionMethod, Blob.data() + MagicSize + VersionFieldSize, + sizeof(uint16_t)); + memcpy(&UncompressedSize, + Blob.data() + MagicSize + VersionFieldSize + MethodFieldSize, + sizeof(uint32_t)); + memcpy(&StoredHash, + Blob.data() + MagicSize + VersionFieldSize + MethodFieldSize + + SizeFieldSize, + sizeof(uint64_t)); + + llvm::compression::Format CompressionFormat; + if (CompressionMethod == + static_cast(llvm::compression::Format::Zlib)) + CompressionFormat = llvm::compression::Format::Zlib; + else if (CompressionMethod == + static_cast(llvm::compression::Format::Zstd)) + CompressionFormat = llvm::compression::Format::Zstd; + else + return createStringError(inconvertibleErrorCode(), + "Unknown compressing method"); + + llvm::Timer DecompressTimer("Decompression Timer", "Decompression time", + ClangOffloadBundlerTimerGroup); + if (Verbose) + DecompressTimer.startTimer(); + + SmallVector DecompressedData; + StringRef CompressedData = Blob.substr(HeaderSize); + if (llvm::Error DecompressionError = llvm::compression::decompress( + CompressionFormat, llvm::arrayRefFromStringRef(CompressedData), + DecompressedData, UncompressedSize)) + return createStringError(inconvertibleErrorCode(), + "Could not decompress embedded file contents: " + + llvm::toString(std::move(DecompressionError))); + + if (Verbose) { + DecompressTimer.stopTimer(); + + // Recalculate MD5 hash + llvm::Timer HashRecalcTimer("Hash Recalculation Timer", + "Hash recalculation time", + ClangOffloadBundlerTimerGroup); + HashRecalcTimer.startTimer(); + llvm::MD5 Hash; + llvm::MD5::MD5Result Result; + Hash.update(llvm::ArrayRef(DecompressedData.data(), + DecompressedData.size())); + Hash.final(Result); + uint64_t RecalculatedHash = Result.low(); + HashRecalcTimer.stopTimer(); + bool HashMatch = (StoredHash == RecalculatedHash); + + llvm::errs() << "Compressed bundle format version: " << ThisVersion << "\n" + << "Decompression method: " + << (CompressionFormat == llvm::compression::Format::Zlib + ? "zlib" + : "zstd") + << "\n" + << "Size before decompression: " << CompressedData.size() + << " bytes\n" + << "Size after decompression: " << UncompressedSize + << " bytes\n" + << "Stored hash: " << llvm::format_hex(StoredHash, 16) << "\n" + << "Recalculated hash: " + << llvm::format_hex(RecalculatedHash, 16) << "\n" + << "Hashes match: " << (HashMatch ? "Yes" : "No") << "\n"; + } + + return llvm::MemoryBuffer::getMemBufferCopy( + llvm::toStringRef(DecompressedData)); +} + // List bundle IDs. Return true if an error was found. Error OffloadBundler::ListBundleIDsInFile( StringRef InputFileName, const OffloadBundlerConfig &BundlerConfig) { @@ -890,28 +1090,35 @@ Error OffloadBundler::ListBundleIDsInFile( if (std::error_code EC = CodeOrErr.getError()) return createFileError(InputFileName, EC); - MemoryBuffer &Input = **CodeOrErr; + // Decompress the input if necessary. + Expected> DecompressedBufferOrErr = + CompressedOffloadBundle::decompress(**CodeOrErr, BundlerConfig.Verbose); + if (!DecompressedBufferOrErr) + return createStringError( + inconvertibleErrorCode(), + "Failed to decompress input: " + + llvm::toString(DecompressedBufferOrErr.takeError())); + + MemoryBuffer &DecompressedInput = **DecompressedBufferOrErr; // Select the right files handler. Expected> FileHandlerOrErr = - CreateFileHandler(Input, BundlerConfig); + CreateFileHandler(DecompressedInput, BundlerConfig); if (!FileHandlerOrErr) return FileHandlerOrErr.takeError(); std::unique_ptr &FH = *FileHandlerOrErr; assert(FH); - return FH->listBundleIDs(Input); + return FH->listBundleIDs(DecompressedInput); } /// Bundle the files. Return true if an error was found. Error OffloadBundler::BundleFiles() { std::error_code EC; - // Create output file. - raw_fd_ostream OutputFile(BundlerConfig.OutputFileNames.front(), EC, - sys::fs::OF_None); - if (EC) - return createFileError(BundlerConfig.OutputFileNames.front(), EC); + // Create a buffer to hold the content before compressing. + SmallVector Buffer; + llvm::raw_svector_ostream BufferStream(Buffer); // Open input files. SmallVector, 8u> InputBuffers; @@ -938,22 +1145,46 @@ Error OffloadBundler::BundleFiles() { assert(FH); // Write header. - if (Error Err = FH->WriteHeader(OutputFile, InputBuffers)) + if (Error Err = FH->WriteHeader(BufferStream, InputBuffers)) return Err; // Write all bundles along with the start/end markers. If an error was found // writing the end of the bundle component, abort the bundle writing. auto Input = InputBuffers.begin(); for (auto &Triple : BundlerConfig.TargetNames) { - if (Error Err = FH->WriteBundleStart(OutputFile, Triple)) + if (Error Err = FH->WriteBundleStart(BufferStream, Triple)) return Err; - if (Error Err = FH->WriteBundle(OutputFile, **Input)) + if (Error Err = FH->WriteBundle(BufferStream, **Input)) return Err; - if (Error Err = FH->WriteBundleEnd(OutputFile, Triple)) + if (Error Err = FH->WriteBundleEnd(BufferStream, Triple)) return Err; ++Input; } - return Error::success(); + + raw_fd_ostream OutputFile(BundlerConfig.OutputFileNames.front(), EC, + sys::fs::OF_None); + if (EC) + return createFileError(BundlerConfig.OutputFileNames.front(), EC); + + SmallVector CompressedBuffer; + if (BundlerConfig.Compress) { + std::unique_ptr BufferMemory = + llvm::MemoryBuffer::getMemBufferCopy( + llvm::StringRef(Buffer.data(), Buffer.size())); + auto CompressionResult = + CompressedOffloadBundle::compress(*BufferMemory, BundlerConfig.Verbose); + if (auto Error = CompressionResult.takeError()) + return Error; + + auto CompressedMemBuffer = std::move(CompressionResult.get()); + CompressedBuffer.assign(CompressedMemBuffer->getBufferStart(), + CompressedMemBuffer->getBufferEnd()); + } else + CompressedBuffer = Buffer; + + OutputFile.write(CompressedBuffer.data(), CompressedBuffer.size()); + + return FH->finalizeOutputFile(); } // Unbundle the files. Return true if an error was found. @@ -964,7 +1195,16 @@ Error OffloadBundler::UnbundleFiles() { if (std::error_code EC = CodeOrErr.getError()) return createFileError(BundlerConfig.InputFileNames.front(), EC); - MemoryBuffer &Input = **CodeOrErr; + // Decompress the input if necessary. + Expected> DecompressedBufferOrErr = + CompressedOffloadBundle::decompress(**CodeOrErr, BundlerConfig.Verbose); + if (!DecompressedBufferOrErr) + return createStringError( + inconvertibleErrorCode(), + "Failed to decompress input: " + + llvm::toString(DecompressedBufferOrErr.takeError())); + + MemoryBuffer &Input = **DecompressedBufferOrErr; // Select the right files handler. Expected> FileHandlerOrErr = @@ -1169,11 +1409,23 @@ Error OffloadBundler::UnbundleArchive() { if (!CodeObjectBufferRefOrErr) return CodeObjectBufferRefOrErr.takeError(); - auto CodeObjectBuffer = + auto TempCodeObjectBuffer = MemoryBuffer::getMemBuffer(*CodeObjectBufferRefOrErr, false); + // Decompress the buffer if necessary. + Expected> DecompressedBufferOrErr = + CompressedOffloadBundle::decompress(*TempCodeObjectBuffer, + BundlerConfig.Verbose); + if (!DecompressedBufferOrErr) + return createStringError( + inconvertibleErrorCode(), + "Failed to decompress code object: " + + llvm::toString(DecompressedBufferOrErr.takeError())); + + MemoryBuffer &CodeObjectBuffer = **DecompressedBufferOrErr; + Expected> FileHandlerOrErr = - CreateFileHandler(*CodeObjectBuffer, BundlerConfig); + CreateFileHandler(CodeObjectBuffer, BundlerConfig); if (!FileHandlerOrErr) return FileHandlerOrErr.takeError(); @@ -1181,11 +1433,11 @@ Error OffloadBundler::UnbundleArchive() { assert(FileHandler && "FileHandle creation failed for file in the archive!"); - if (Error ReadErr = FileHandler->ReadHeader(*CodeObjectBuffer)) + if (Error ReadErr = FileHandler->ReadHeader(CodeObjectBuffer)) return ReadErr; Expected> CurBundleIDOrErr = - FileHandler->ReadBundleStart(*CodeObjectBuffer); + FileHandler->ReadBundleStart(CodeObjectBuffer); if (!CurBundleIDOrErr) return CurBundleIDOrErr.takeError(); @@ -1206,7 +1458,7 @@ Error OffloadBundler::UnbundleArchive() { BundlerConfig)) { std::string BundleData; raw_string_ostream DataStream(BundleData); - if (Error Err = FileHandler->ReadBundle(DataStream, *CodeObjectBuffer)) + if (Error Err = FileHandler->ReadBundle(DataStream, CodeObjectBuffer)) return Err; for (auto &CompatibleTarget : CompatibleTargets) { @@ -1244,11 +1496,11 @@ Error OffloadBundler::UnbundleArchive() { } } - if (Error Err = FileHandler->ReadBundleEnd(*CodeObjectBuffer)) + if (Error Err = FileHandler->ReadBundleEnd(CodeObjectBuffer)) return Err; Expected> NextTripleOrErr = - FileHandler->ReadBundleStart(*CodeObjectBuffer); + FileHandler->ReadBundleStart(CodeObjectBuffer); if (!NextTripleOrErr) return NextTripleOrErr.takeError(); diff --git a/clang/lib/Driver/ToolChains/AMDGPU.cpp b/clang/lib/Driver/ToolChains/AMDGPU.cpp index 3f08c0ef5d6f00..d4b33ad551c433 100644 --- a/clang/lib/Driver/ToolChains/AMDGPU.cpp +++ b/clang/lib/Driver/ToolChains/AMDGPU.cpp @@ -329,6 +329,20 @@ RocmInstallationDetector::RocmInstallationDetector( RocmDeviceLibPathArg = Args.getAllArgValues(clang::driver::options::OPT_rocm_device_lib_path_EQ); HIPPathArg = Args.getLastArgValue(clang::driver::options::OPT_hip_path_EQ); + HIPStdParPathArg = + Args.getLastArgValue(clang::driver::options::OPT_hipstdpar_path_EQ); + HasHIPStdParLibrary = + !HIPStdParPathArg.empty() && D.getVFS().exists(HIPStdParPathArg + + "/hipstdpar_lib.hpp"); + HIPRocThrustPathArg = + Args.getLastArgValue(clang::driver::options::OPT_hipstdpar_thrust_path_EQ); + HasRocThrustLibrary = !HIPRocThrustPathArg.empty() && + D.getVFS().exists(HIPRocThrustPathArg + "/thrust"); + HIPRocPrimPathArg = + Args.getLastArgValue(clang::driver::options::OPT_hipstdpar_prim_path_EQ); + HasRocPrimLibrary = !HIPRocPrimPathArg.empty() && + D.getVFS().exists(HIPRocPrimPathArg + "/rocprim"); + if (auto *A = Args.getLastArg(clang::driver::options::OPT_hip_version_EQ)) { HIPVersionArg = A->getValue(); unsigned Major = ~0U; @@ -507,6 +521,7 @@ void RocmInstallationDetector::AddHIPIncludeArgs(const ArgList &DriverArgs, ArgStringList &CC1Args) const { bool UsesRuntimeWrapper = VersionMajorMinor > llvm::VersionTuple(3, 5) && !DriverArgs.hasArg(options::OPT_nohipwrapperinc); + bool HasHipStdPar = DriverArgs.hasArg(options::OPT_hipstdpar); if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) { // HIP header includes standard library wrapper headers under clang @@ -529,8 +544,45 @@ void RocmInstallationDetector::AddHIPIncludeArgs(const ArgList &DriverArgs, CC1Args.push_back(DriverArgs.MakeArgString(P)); } - if (DriverArgs.hasArg(options::OPT_nogpuinc)) + const auto HandleHipStdPar = [=, &DriverArgs, &CC1Args]() { + if (!hasHIPStdParLibrary()) { + D.Diag(diag::err_drv_no_hipstdpar_lib); + return; + } + if (!HasRocThrustLibrary && + !D.getVFS().exists(getIncludePath() + "/thrust")) { + D.Diag(diag::err_drv_no_hipstdpar_thrust_lib); + return; + } + if (!HasRocPrimLibrary && + !D.getVFS().exists(getIncludePath() + "/rocprim")) { + D.Diag(diag::err_drv_no_hipstdpar_prim_lib); + return; + } + + const char *ThrustPath; + if (HasRocThrustLibrary) + ThrustPath = DriverArgs.MakeArgString(HIPRocThrustPathArg); + else + ThrustPath = DriverArgs.MakeArgString(getIncludePath() + "/thrust"); + + const char *PrimPath; + if (HasRocPrimLibrary) + PrimPath = DriverArgs.MakeArgString(HIPRocPrimPathArg); + else + PrimPath = DriverArgs.MakeArgString(getIncludePath() + "/rocprim"); + + CC1Args.append({"-idirafter", ThrustPath, "-idirafter", PrimPath, + "-idirafter", DriverArgs.MakeArgString(HIPStdParPathArg), + "-include", "hipstdpar_lib.hpp"}); + }; + + if (DriverArgs.hasArg(options::OPT_nogpuinc)) { + if (HasHipStdPar) + HandleHipStdPar(); + return; + } if (!hasHIPRuntime()) { D.Diag(diag::err_drv_no_hip_runtime); @@ -541,6 +593,8 @@ void RocmInstallationDetector::AddHIPIncludeArgs(const ArgList &DriverArgs, CC1Args.push_back(DriverArgs.MakeArgString(getIncludePath())); if (UsesRuntimeWrapper) CC1Args.append({"-include", "__clang_hip_runtime_wrapper.h"}); + if (HasHipStdPar) + HandleHipStdPar(); } void amdgpu::Linker::ConstructJob(Compilation &C, const JobAction &JA, diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index a694d00b569a59..c74f6ff447261d 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -5150,9 +5150,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, const bool IsAssertBuild = true; #endif - // Disable the verification pass in -asserts builds. - if (!IsAssertBuild) + // Disable the verification pass in asserts builds unless otherwise specified. + if (Args.hasFlag(options::OPT_fno_verify_intermediate_code, + options::OPT_fverify_intermediate_code, !IsAssertBuild)) { CmdArgs.push_back("-disable-llvm-verifier"); + } // Discard value names in assert builds unless otherwise specified. if (Args.hasFlag(options::OPT_fdiscard_value_names, @@ -6580,6 +6582,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-fhip-new-launch-api"); Args.addOptInFlag(CmdArgs, options::OPT_fgpu_allow_device_init, options::OPT_fno_gpu_allow_device_init); + Args.AddLastArg(CmdArgs, options::OPT_hipstdpar); + Args.AddLastArg(CmdArgs, options::OPT_hipstdpar_interpose_alloc); Args.addOptInFlag(CmdArgs, options::OPT_fhip_kernel_arg_name, options::OPT_fno_hip_kernel_arg_name); } @@ -8468,6 +8472,11 @@ void OffloadBundler::ConstructJob(Compilation &C, const JobAction &JA, } CmdArgs.push_back(TCArgs.MakeArgString(UB)); } + if (TCArgs.hasFlag(options::OPT_offload_compress, + options::OPT_no_offload_compress, false)) + CmdArgs.push_back("-compress"); + if (TCArgs.hasArg(options::OPT_v)) + CmdArgs.push_back("-verbose"); // All the inputs are encoded as commands. C.addCommand(std::make_unique( JA, *this, ResponseFileSupport::None(), @@ -8551,6 +8560,8 @@ void OffloadBundler::ConstructJobMultipleOutputs( } CmdArgs.push_back("-unbundle"); CmdArgs.push_back("-allow-missing-bundles"); + if (TCArgs.hasArg(options::OPT_v)) + CmdArgs.push_back("-verbose"); // All the inputs are encoded as commands. C.addCommand(std::make_unique( diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp index 1ba031d42741cc..25fd940584624e 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -631,6 +631,7 @@ void tools::addLTOOptions(const ToolChain &ToolChain, const ArgList &Args, const char *PluginOptPrefix = IsOSAIX ? "-bplugin_opt:" : "-plugin-opt="; const char *ExtraDash = IsOSAIX ? "-" : ""; + const char *ParallelismOpt = IsOSAIX ? "-threads=" : "jobs="; // Note, this solution is far from perfect, better to encode it into IR // metadata, but this may not be worth it, since it looks like aranges is on @@ -690,8 +691,8 @@ void tools::addLTOOptions(const ToolChain &ToolChain, const ArgList &Args, StringRef Parallelism = getLTOParallelism(Args, D); if (!Parallelism.empty()) - CmdArgs.push_back( - Args.MakeArgString(Twine(PluginOptPrefix) + "jobs=" + Parallelism)); + CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) + + ParallelismOpt + Parallelism)); // If an explicit debugger tuning argument appeared, pass it along. if (Arg *A = @@ -969,41 +970,29 @@ void tools::addFortranRuntimeLibs(const ToolChain &TC, llvm::opt::ArgStringList &CmdArgs) { if (TC.getTriple().isKnownWindowsMSVCEnvironment()) { CmdArgs.push_back("Fortran_main.lib"); - CmdArgs.push_back("flang-rt.lib"); + CmdArgs.push_back("FortranRuntime.lib"); + CmdArgs.push_back("FortranDecimal.lib"); } else { CmdArgs.push_back("-lFortran_main"); - CmdArgs.push_back("-lflang-rt"); + CmdArgs.push_back("-lFortranRuntime"); + CmdArgs.push_back("-lFortranDecimal"); } } void tools::addFortranRuntimeLibraryPath(const ToolChain &TC, const llvm::opt::ArgList &Args, ArgStringList &CmdArgs) { - // Default to the /../lib, /../flang-rt/lib, and - // /../runtimes/runtimes-bins/flang-rt/lib directories. This - // works fine on the platforms that we have tested so far. We will probably - // have to re-fine this in the future. In particular, on some platforms, we - // may need to use lib64 instead of lib. - SmallString<256> BuildLibPath = - llvm::sys::path::parent_path(TC.getDriver().Dir); - SmallString<256> FlangRTLibPath = - llvm::sys::path::parent_path(TC.getDriver().Dir); - SmallString<256> RuntimesLibPath = + // Default to the /../lib directory. This works fine on the + // platforms that we have tested so far. We will probably have to re-fine + // this in the future. In particular, on some platforms, we may need to use + // lib64 instead of lib. + SmallString<256> DefaultLibPath = llvm::sys::path::parent_path(TC.getDriver().Dir); - // Search path for Fortran_main and Flang-rt libraries. - llvm::sys::path::append(BuildLibPath, "lib"); - llvm::sys::path::append(FlangRTLibPath, "flang-rt/lib"); - llvm::sys::path::append(RuntimesLibPath, - "runtimes/runtimes-bins/flang-rt/lib"); - if (TC.getTriple().isKnownWindowsMSVCEnvironment()) { - CmdArgs.push_back(Args.MakeArgString("-libpath:" + BuildLibPath)); - CmdArgs.push_back(Args.MakeArgString("-libpath:" + FlangRTLibPath)); - CmdArgs.push_back(Args.MakeArgString("-libpath:" + RuntimesLibPath)); - } else { - CmdArgs.push_back(Args.MakeArgString("-L" + BuildLibPath)); - CmdArgs.push_back(Args.MakeArgString("-L" + FlangRTLibPath)); - CmdArgs.push_back(Args.MakeArgString("-L" + RuntimesLibPath)); - } + llvm::sys::path::append(DefaultLibPath, "lib"); + if (TC.getTriple().isKnownWindowsMSVCEnvironment()) + CmdArgs.push_back(Args.MakeArgString("-libpath:" + DefaultLibPath)); + else + CmdArgs.push_back(Args.MakeArgString("-L" + DefaultLibPath)); } static void addSanitizerRuntime(const ToolChain &TC, const ArgList &Args, diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp index 10f785ce7ab907..fe44939741d8dd 100644 --- a/clang/lib/Driver/ToolChains/Flang.cpp +++ b/clang/lib/Driver/ToolChains/Flang.cpp @@ -6,7 +6,6 @@ // //===----------------------------------------------------------------------===// - #include "Flang.h" #include "CommonArgs.h" @@ -170,6 +169,38 @@ void Flang::addPicOptions(const ArgList &Args, ArgStringList &CmdArgs) const { } } +void Flang::AddAArch64TargetArgs(const ArgList &Args, + ArgStringList &CmdArgs) const { + // Handle -msve_vector_bits= + if (Arg *A = Args.getLastArg(options::OPT_msve_vector_bits_EQ)) { + StringRef Val = A->getValue(); + const Driver &D = getToolChain().getDriver(); + if (Val.equals("128") || Val.equals("256") || Val.equals("512") || + Val.equals("1024") || Val.equals("2048") || Val.equals("128+") || + Val.equals("256+") || Val.equals("512+") || Val.equals("1024+") || + Val.equals("2048+")) { + unsigned Bits = 0; + if (Val.endswith("+")) + Val = Val.substr(0, Val.size() - 1); + else { + [[maybe_unused]] bool Invalid = Val.getAsInteger(10, Bits); + assert(!Invalid && "Failed to parse value"); + CmdArgs.push_back( + Args.MakeArgString("-mvscale-max=" + llvm::Twine(Bits / 128))); + } + + [[maybe_unused]] bool Invalid = Val.getAsInteger(10, Bits); + assert(!Invalid && "Failed to parse value"); + CmdArgs.push_back( + Args.MakeArgString("-mvscale-min=" + llvm::Twine(Bits / 128))); + // Silently drop requests for vector-length agnostic code as it's implied. + } else if (!Val.equals("scalable")) + // Handle the unsupported values passed to msve-vector-bits. + D.Diag(diag::err_drv_unsupported_option_argument) + << A->getSpelling() << Val; + } +} + void Flang::addTargetOptions(const ArgList &Args, ArgStringList &CmdArgs) const { const ToolChain &TC = getToolChain(); @@ -186,9 +217,13 @@ void Flang::addTargetOptions(const ArgList &Args, switch (TC.getArch()) { default: break; + case llvm::Triple::aarch64: + getTargetFeatures(D, Triple, Args, CmdArgs, /*ForAs*/ false); + AddAArch64TargetArgs(Args, CmdArgs); + break; + case llvm::Triple::r600: case llvm::Triple::amdgcn: - case llvm::Triple::aarch64: case llvm::Triple::riscv64: case llvm::Triple::x86_64: getTargetFeatures(D, Triple, Args, CmdArgs, /*ForAs*/ false); diff --git a/clang/lib/Driver/ToolChains/Flang.h b/clang/lib/Driver/ToolChains/Flang.h index 962b4ae601726a..0141240b5d3ac9 100644 --- a/clang/lib/Driver/ToolChains/Flang.h +++ b/clang/lib/Driver/ToolChains/Flang.h @@ -56,6 +56,13 @@ class LLVM_LIBRARY_VISIBILITY Flang : public Tool { void addTargetOptions(const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs) const; + /// Add specific options for AArch64 target. + /// + /// \param [in] Args The list of input driver arguments + /// \param [out] CmdArgs The list of output command arguments + void AddAArch64TargetArgs(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/HIPAMD.cpp b/clang/lib/Driver/ToolChains/HIPAMD.cpp index 3fc5669c06c399..ccb36a6c846c80 100644 --- a/clang/lib/Driver/ToolChains/HIPAMD.cpp +++ b/clang/lib/Driver/ToolChains/HIPAMD.cpp @@ -113,6 +113,8 @@ void AMDGCN::Linker::constructLldCommand(Compilation &C, const JobAction &JA, "--no-undefined", "-shared", "-plugin-opt=-amdgpu-internalize-symbols"}; + if (Args.hasArg(options::OPT_hipstdpar)) + LldArgs.push_back("-plugin-opt=-amdgpu-enable-hipstdpar"); auto &TC = getToolChain(); auto &D = TC.getDriver(); @@ -242,6 +244,8 @@ void HIPAMDToolChain::addClangTargetOptions( if (!DriverArgs.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc, false)) CC1Args.append({"-mllvm", "-amdgpu-internalize-symbols"}); + if (DriverArgs.hasArgNoClaim(options::OPT_hipstdpar)) + CC1Args.append({"-mllvm", "-amdgpu-enable-hipstdpar"}); StringRef MaxThreadsPerBlock = DriverArgs.getLastArgValue(options::OPT_gpu_max_threads_per_block_EQ); diff --git a/clang/lib/Driver/ToolChains/HIPUtility.cpp b/clang/lib/Driver/ToolChains/HIPUtility.cpp index 8b9d8db90ffab7..04efdcba20ea74 100644 --- a/clang/lib/Driver/ToolChains/HIPUtility.cpp +++ b/clang/lib/Driver/ToolChains/HIPUtility.cpp @@ -84,6 +84,12 @@ void HIP::constructHIPFatbinCommand(Compilation &C, const JobAction &JA, Args.MakeArgString(std::string("-output=").append(Output)); BundlerArgs.push_back(BundlerOutputArg); + if (Args.hasFlag(options::OPT_offload_compress, + options::OPT_no_offload_compress, false)) + BundlerArgs.push_back("-compress"); + if (Args.hasArg(options::OPT_v)) + BundlerArgs.push_back("-verbose"); + const char *Bundler = Args.MakeArgString( T.getToolChain().GetProgramPath("clang-offload-bundler")); C.addCommand(std::make_unique( diff --git a/clang/lib/Driver/ToolChains/MinGW.cpp b/clang/lib/Driver/ToolChains/MinGW.cpp index 5af7ea985a28a1..5872e13bda358f 100644 --- a/clang/lib/Driver/ToolChains/MinGW.cpp +++ b/clang/lib/Driver/ToolChains/MinGW.cpp @@ -709,8 +709,11 @@ void toolchains::MinGW::addClangTargetOptions( } } - if (Arg *A = DriverArgs.getLastArgNoClaim(options::OPT_mthreads)) - A->ignoreTargetSpecific(); + for (auto Opt : {options::OPT_mthreads, options::OPT_mwindows, + options::OPT_mconsole, options::OPT_mdll}) { + if (Arg *A = DriverArgs.getLastArgNoClaim(Opt)) + A->ignoreTargetSpecific(); + } } void toolchains::MinGW::AddClangCXXStdlibIncludeArgs( diff --git a/clang/lib/Driver/ToolChains/ROCm.h b/clang/lib/Driver/ToolChains/ROCm.h index 554d8a6929ac59..dceb0ab0366933 100644 --- a/clang/lib/Driver/ToolChains/ROCm.h +++ b/clang/lib/Driver/ToolChains/ROCm.h @@ -77,6 +77,9 @@ class RocmInstallationDetector { const Driver &D; bool HasHIPRuntime = false; bool HasDeviceLibrary = false; + bool HasHIPStdParLibrary = false; + bool HasRocThrustLibrary = false; + bool HasRocPrimLibrary = false; // Default version if not detected or specified. const unsigned DefaultVersionMajor = 3; @@ -96,6 +99,13 @@ class RocmInstallationDetector { std::vector RocmDeviceLibPathArg; // HIP runtime path specified by --hip-path. StringRef HIPPathArg; + // HIP Standard Parallel Algorithm acceleration library specified by + // --hipstdpar-path + StringRef HIPStdParPathArg; + // rocThrust algorithm library specified by --hipstdpar-thrust-path + StringRef HIPRocThrustPathArg; + // rocPrim algorithm library specified by --hipstdpar-prim-path + StringRef HIPRocPrimPathArg; // HIP version specified by --hip-version. StringRef HIPVersionArg; // Wheter -nogpulib is specified. @@ -180,6 +190,9 @@ class RocmInstallationDetector { /// Check whether we detected a valid ROCm device library. bool hasDeviceLibrary() const { return HasDeviceLibrary; } + /// Check whether we detected a valid HIP STDPAR Acceleration library. + bool hasHIPStdParLibrary() const { return HasHIPStdParLibrary; } + /// Print information about the detected ROCm installation. void print(raw_ostream &OS) const; diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index 8a34b4d9431b62..7b0ebe2cf621b1 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -3914,7 +3914,7 @@ llvm::Expected getStyle(StringRef StyleName, StringRef FileName, FormatStyle FallbackStyle = getNoStyle(); if (!getPredefinedStyle(FallbackStyleName, Style.Language, &FallbackStyle)) - return make_string_error("Invalid fallback style \"" + FallbackStyleName); + return make_string_error("Invalid fallback style: " + FallbackStyleName); llvm::SmallVector, 1> ChildFormatTextToApply; diff --git a/clang/lib/Format/FormatToken.h b/clang/lib/Format/FormatToken.h index dbd3a6e70f037e..5877b0a6124742 100644 --- a/clang/lib/Format/FormatToken.h +++ b/clang/lib/Format/FormatToken.h @@ -61,6 +61,7 @@ namespace format { TYPE(CSharpStringLiteral) \ TYPE(CtorInitializerColon) \ TYPE(CtorInitializerComma) \ + TYPE(CtorDtorDeclName) \ TYPE(DesignatedInitializerLSquare) \ TYPE(DesignatedInitializerPeriod) \ TYPE(DictLiteral) \ diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index ae2cbbdce93461..6f879006465ecf 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -2016,8 +2016,7 @@ class AnnotatingParser { Style.Language == FormatStyle::LK_Java) { Current.setType(TT_LambdaArrow); } else if (Current.is(tok::arrow) && AutoFound && - (Line.MightBeFunctionDecl || Line.InPPDirective) && - Current.NestingLevel == 0 && + Line.MightBeFunctionDecl && Current.NestingLevel == 0 && !Current.Previous->isOneOf(tok::kw_operator, tok::identifier)) { // not auto operator->() -> xxx; Current.setType(TT_TrailingReturnArrow); @@ -3211,12 +3210,12 @@ static bool isCtorOrDtorName(const FormatToken *Tok) { } void TokenAnnotator::annotate(AnnotatedLine &Line) { - for (auto &Child : Line.Children) - annotate(*Child); - AnnotatingParser Parser(Style, Line, Keywords, Scopes); Line.Type = Parser.parseLine(); + for (auto &Child : Line.Children) + annotate(*Child); + // With very deep nesting, ExpressionParser uses lots of stack and the // formatting algorithm is very slow. We're not going to do a good job here // anyway - it's probably generated code being formatted by mistake. @@ -3234,7 +3233,7 @@ void TokenAnnotator::annotate(AnnotatedLine &Line) { auto *Tok = getFunctionName(Line); if (Tok && ((!Scopes.empty() && Scopes.back() == ST_Class) || Line.endsWith(TT_FunctionLBrace) || isCtorOrDtorName(Tok))) { - Tok->setFinalizedType(TT_FunctionDeclarationName); + Tok->setFinalizedType(TT_CtorDtorDeclName); } } @@ -3252,7 +3251,8 @@ void TokenAnnotator::annotate(AnnotatedLine &Line) { // This function heuristically determines whether 'Current' starts the name of a // function declaration. static bool isFunctionDeclarationName(bool IsCpp, const FormatToken &Current, - const AnnotatedLine &Line) { + const AnnotatedLine &Line, + FormatToken *&ClosingParen) { assert(Current.Previous); if (Current.is(TT_FunctionDeclarationName)) @@ -3344,16 +3344,16 @@ static bool isFunctionDeclarationName(bool IsCpp, const FormatToken &Current, // Check whether parameter list can belong to a function declaration. if (!Next || Next->isNot(tok::l_paren) || !Next->MatchingParen) return false; + ClosingParen = Next->MatchingParen; + assert(ClosingParen->is(tok::r_paren)); // If the lines ends with "{", this is likely a function definition. if (Line.Last->is(tok::l_brace)) return true; - if (Next->Next == Next->MatchingParen) + if (Next->Next == ClosingParen) return true; // Empty parentheses. // If there is an &/&& after the r_paren, this is likely a function. - if (Next->MatchingParen->Next && - Next->MatchingParen->Next->is(TT_PointerOrReference)) { + if (ClosingParen->Next && ClosingParen->Next->is(TT_PointerOrReference)) return true; - } // Check for K&R C function definitions (and C++ function definitions with // unnamed parameters), e.g.: @@ -3370,7 +3370,7 @@ static bool isFunctionDeclarationName(bool IsCpp, const FormatToken &Current, return true; } - for (const FormatToken *Tok = Next->Next; Tok && Tok != Next->MatchingParen; + for (const FormatToken *Tok = Next->Next; Tok && Tok != ClosingParen; Tok = Tok->Next) { if (Tok->is(TT_TypeDeclarationParen)) return true; @@ -3442,13 +3442,18 @@ void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) const { calculateArrayInitializerColumnList(Line); bool LineIsFunctionDeclaration = false; + FormatToken *ClosingParen = nullptr; for (FormatToken *Tok = Current, *AfterLastAttribute = nullptr; Tok; Tok = Tok->Next) { if (Tok->Previous->EndsCppAttributeGroup) AfterLastAttribute = Tok; - if (isFunctionDeclarationName(Style.isCpp(), *Tok, Line)) { - LineIsFunctionDeclaration = true; - Tok->setFinalizedType(TT_FunctionDeclarationName); + if (const bool IsCtorOrDtor = Tok->is(TT_CtorDtorDeclName); + IsCtorOrDtor || + isFunctionDeclarationName(Style.isCpp(), *Tok, Line, ClosingParen)) { + if (!IsCtorOrDtor) { + LineIsFunctionDeclaration = true; + Tok->setFinalizedType(TT_FunctionDeclarationName); + } if (AfterLastAttribute && mustBreakAfterAttributes(*AfterLastAttribute, Style)) { AfterLastAttribute->MustBreakBefore = true; @@ -3458,29 +3463,38 @@ void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) const { } } - if (Style.isCpp() && !LineIsFunctionDeclaration) { - // Annotate */&/&& in `operator` function calls as binary operators. - for (const auto *Tok = Line.First; Tok; Tok = Tok->Next) { - if (Tok->isNot(tok::kw_operator)) - continue; - do { - Tok = Tok->Next; - } while (Tok && Tok->isNot(TT_OverloadedOperatorLParen)); - if (!Tok) - break; - const auto *LeftParen = Tok; - for (Tok = Tok->Next; Tok && Tok != LeftParen->MatchingParen; - Tok = Tok->Next) { - if (Tok->isNot(tok::identifier)) - continue; - auto *Next = Tok->Next; - const bool NextIsBinaryOperator = - Next && Next->isOneOf(tok::star, tok::amp, tok::ampamp) && - Next->Next && Next->Next->is(tok::identifier); - if (!NextIsBinaryOperator) + if (Style.isCpp()) { + if (!LineIsFunctionDeclaration) { + // Annotate */&/&& in `operator` function calls as binary operators. + for (const auto *Tok = Line.First; Tok; Tok = Tok->Next) { + if (Tok->isNot(tok::kw_operator)) continue; - Next->setType(TT_BinaryOperator); - Tok = Next; + do { + Tok = Tok->Next; + } while (Tok && Tok->isNot(TT_OverloadedOperatorLParen)); + if (!Tok) + break; + const auto *LeftParen = Tok; + for (Tok = Tok->Next; Tok && Tok != LeftParen->MatchingParen; + Tok = Tok->Next) { + if (Tok->isNot(tok::identifier)) + continue; + auto *Next = Tok->Next; + const bool NextIsBinaryOperator = + Next && Next->isOneOf(tok::star, tok::amp, tok::ampamp) && + Next->Next && Next->Next->is(tok::identifier); + if (!NextIsBinaryOperator) + continue; + Next->setType(TT_BinaryOperator); + Tok = Next; + } + } + } else if (ClosingParen) { + for (auto *Tok = ClosingParen->Next; Tok; Tok = Tok->Next) { + if (Tok->is(tok::arrow)) { + Tok->setType(TT_TrailingReturnArrow); + break; + } } } } diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp index bf38ed73c4a0b4..dda5fd077e590e 100644 --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -173,10 +173,12 @@ void UnwrappedLineParser::reset() { CommentsBeforeNextToken.clear(); FormatTok = nullptr; MustBreakBeforeNextToken = false; + IsDecltypeAutoFunction = false; PreprocessorDirectives.clear(); CurrentLines = &Lines; DeclarationScopeStack.clear(); NestedTooDeep.clear(); + NestedLambdas.clear(); PPStack.clear(); Line->FirstStartColumn = FirstStartColumn; @@ -1766,6 +1768,17 @@ void UnwrappedLineParser::parseStructuralElement( if (parseStructLike()) return; break; + case tok::kw_decltype: + nextToken(); + if (FormatTok->is(tok::l_paren)) { + parseParens(); + assert(FormatTok->Previous); + if (FormatTok->Previous->endsSequence(tok::r_paren, tok::kw_auto, + tok::l_paren)) { + Line->SeenDecltypeAuto = true; + } + } + break; case tok::period: nextToken(); // In Java, classes have an implicit static member "class". @@ -1827,6 +1840,7 @@ void UnwrappedLineParser::parseStructuralElement( if (InRequiresExpression) FormatTok->setFinalizedType(TT_BracedListLBrace); if (!tryToParsePropertyAccessor() && !tryToParseBracedList()) { + IsDecltypeAutoFunction = Line->SeenDecltypeAuto; // A block outside of parentheses must be the last part of a // structural element. // FIXME: Figure out cases where this is not true, and add projections @@ -1844,6 +1858,7 @@ void UnwrappedLineParser::parseStructuralElement( } FormatTok->setFinalizedType(TT_FunctionLBrace); parseBlock(); + IsDecltypeAutoFunction = false; addUnwrappedLine(); return; } @@ -2249,9 +2264,15 @@ bool UnwrappedLineParser::tryToParseLambda() { return true; } } + FormatTok->setFinalizedType(TT_LambdaLBrace); LSquare.setFinalizedType(TT_LambdaLSquare); + + NestedLambdas.push_back(Line->SeenDecltypeAuto); parseChildBlock(); + assert(!NestedLambdas.empty()); + NestedLambdas.pop_back(); + return true; } @@ -2469,6 +2490,8 @@ bool UnwrappedLineParser::parseParens(TokenType AmpAmpTokenType) { PrevPrev->endsSequence(tok::kw_constexpr, tok::kw_if)))); const bool ReturnParens = Style.RemoveParentheses == FormatStyle::RPS_ReturnStatement && + ((NestedLambdas.empty() && !IsDecltypeAutoFunction) || + (!NestedLambdas.empty() && !NestedLambdas.back())) && Prev && Prev->isOneOf(tok::kw_return, tok::kw_co_return) && Next && Next->is(tok::semi); if ((DoubleParens && !Blacklisted) || ReturnParens) { @@ -4379,6 +4402,7 @@ void UnwrappedLineParser::addUnwrappedLine(LineLevel AdjustLevel) { Line->MatchingOpeningBlockLineIndex = UnwrappedLine::kInvalidIndex; Line->FirstStartColumn = 0; Line->IsContinuation = false; + Line->SeenDecltypeAuto = false; if (ClosesWhitesmithsBlock && AdjustLevel == LineLevel::Remove) --Line->Level; diff --git a/clang/lib/Format/UnwrappedLineParser.h b/clang/lib/Format/UnwrappedLineParser.h index 4138baaabe2693..a4f150d1957126 100644 --- a/clang/lib/Format/UnwrappedLineParser.h +++ b/clang/lib/Format/UnwrappedLineParser.h @@ -61,6 +61,9 @@ struct UnwrappedLine { bool MustBeDeclaration = false; + /// Whether the parser has seen \c decltype(auto) in this line. + bool SeenDecltypeAuto = false; + /// \c True if this line should be indented by ContinuationIndent in /// addition to the normal indention level. bool IsContinuation = false; @@ -335,6 +338,14 @@ class UnwrappedLineParser { // statement contains more than some predefined number of nested statements). SmallVector NestedTooDeep; + // Keeps a stack of the states of nested lambdas (true if the return type of + // the lambda is `decltype(auto)`). + SmallVector NestedLambdas; + + // Whether the parser is parsing the body of a function whose return type is + // `decltype(auto)`. + bool IsDecltypeAutoFunction = false; + // Represents preprocessor branch type, so we can find matching // #if/#else/#endif directives. enum PPBranchKind { diff --git a/clang/lib/Format/WhitespaceManager.cpp b/clang/lib/Format/WhitespaceManager.cpp index 762729d1c4166a..dc81060671c171 100644 --- a/clang/lib/Format/WhitespaceManager.cpp +++ b/clang/lib/Format/WhitespaceManager.cpp @@ -307,8 +307,9 @@ AlignTokenSequence(const FormatStyle &Style, unsigned Start, unsigned End, SmallVector ScopeStack; for (unsigned i = Start; i != End; ++i) { + auto &CurrentChange = Changes[i]; if (ScopeStack.size() != 0 && - Changes[i].indentAndNestingLevel() < + CurrentChange.indentAndNestingLevel() < Changes[ScopeStack.back()].indentAndNestingLevel()) { ScopeStack.pop_back(); } @@ -320,18 +321,18 @@ AlignTokenSequence(const FormatStyle &Style, unsigned Start, unsigned End, Changes[PreviousNonComment].Tok->is(tok::comment)) { --PreviousNonComment; } - if (i != Start && Changes[i].indentAndNestingLevel() > + if (i != Start && CurrentChange.indentAndNestingLevel() > Changes[PreviousNonComment].indentAndNestingLevel()) { ScopeStack.push_back(i); } bool InsideNestedScope = ScopeStack.size() != 0; bool ContinuedStringLiteral = i > Start && - Changes[i].Tok->is(tok::string_literal) && + CurrentChange.Tok->is(tok::string_literal) && Changes[i - 1].Tok->is(tok::string_literal); bool SkipMatchCheck = InsideNestedScope || ContinuedStringLiteral; - if (Changes[i].NewlinesBefore > 0 && !SkipMatchCheck) { + if (CurrentChange.NewlinesBefore > 0 && !SkipMatchCheck) { Shift = 0; FoundMatchOnLine = false; } @@ -339,23 +340,26 @@ AlignTokenSequence(const FormatStyle &Style, unsigned Start, unsigned End, // If this is the first matching token to be aligned, remember by how many // spaces it has to be shifted, so the rest of the changes on the line are // shifted by the same amount - if (!FoundMatchOnLine && !SkipMatchCheck && Matches(Changes[i])) { + if (!FoundMatchOnLine && !SkipMatchCheck && Matches(CurrentChange)) { FoundMatchOnLine = true; - Shift = Column - (RightJustify ? Changes[i].TokenLength : 0) - - Changes[i].StartOfTokenColumn; - Changes[i].Spaces += Shift; + Shift = Column - (RightJustify ? CurrentChange.TokenLength : 0) - + CurrentChange.StartOfTokenColumn; + CurrentChange.Spaces += Shift; // FIXME: This is a workaround that should be removed when we fix // http://llvm.org/PR53699. An assertion later below verifies this. - if (Changes[i].NewlinesBefore == 0) { - Changes[i].Spaces = - std::max(Changes[i].Spaces, - static_cast(Changes[i].Tok->SpacesRequiredBefore)); + if (CurrentChange.NewlinesBefore == 0) { + CurrentChange.Spaces = + std::max(CurrentChange.Spaces, + static_cast(CurrentChange.Tok->SpacesRequiredBefore)); } } + if (Shift == 0) + continue; + // This is for function parameters that are split across multiple lines, // as mentioned in the ScopeStack comment. - if (InsideNestedScope && Changes[i].NewlinesBefore > 0) { + if (InsideNestedScope && CurrentChange.NewlinesBefore > 0) { unsigned ScopeStart = ScopeStack.back(); auto ShouldShiftBeAdded = [&] { // Function declaration @@ -372,35 +376,36 @@ AlignTokenSequence(const FormatStyle &Style, unsigned Start, unsigned End, return true; } - // Continued function call + // Continued (template) function call. if (ScopeStart > Start + 1 && - Changes[ScopeStart - 2].Tok->is(tok::identifier) && + Changes[ScopeStart - 2].Tok->isOneOf(tok::identifier, + TT_TemplateCloser) && Changes[ScopeStart - 1].Tok->is(tok::l_paren) && Changes[ScopeStart].Tok->isNot(TT_LambdaLSquare)) { - if (Changes[i].Tok->MatchingParen && - Changes[i].Tok->MatchingParen->is(TT_LambdaLBrace)) { + if (CurrentChange.Tok->MatchingParen && + CurrentChange.Tok->MatchingParen->is(TT_LambdaLBrace)) { return false; } if (Changes[ScopeStart].NewlinesBefore > 0) return false; - if (Changes[i].Tok->is(tok::l_brace) && - Changes[i].Tok->is(BK_BracedInit)) { + if (CurrentChange.Tok->is(tok::l_brace) && + CurrentChange.Tok->is(BK_BracedInit)) { return true; } return Style.BinPackArguments; } // Ternary operator - if (Changes[i].Tok->is(TT_ConditionalExpr)) + if (CurrentChange.Tok->is(TT_ConditionalExpr)) return true; // Period Initializer .XXX = 1. - if (Changes[i].Tok->is(TT_DesignatedInitializerPeriod)) + if (CurrentChange.Tok->is(TT_DesignatedInitializerPeriod)) return true; // Continued ternary operator - if (Changes[i].Tok->Previous && - Changes[i].Tok->Previous->is(TT_ConditionalExpr)) { + if (CurrentChange.Tok->Previous && + CurrentChange.Tok->Previous->is(TT_ConditionalExpr)) { return true; } @@ -408,8 +413,8 @@ AlignTokenSequence(const FormatStyle &Style, unsigned Start, unsigned End, if (ScopeStart > Start + 1 && Changes[ScopeStart - 2].Tok->is(tok::identifier) && Changes[ScopeStart - 1].Tok->is(tok::l_brace) && - Changes[i].Tok->is(tok::l_brace) && - Changes[i].Tok->is(BK_BracedInit)) { + CurrentChange.Tok->is(tok::l_brace) && + CurrentChange.Tok->is(BK_BracedInit)) { return true; } @@ -417,7 +422,7 @@ AlignTokenSequence(const FormatStyle &Style, unsigned Start, unsigned End, if (ScopeStart > Start + 1 && Changes[ScopeStart - 2].Tok->isNot(tok::identifier) && Changes[ScopeStart - 1].Tok->is(tok::l_brace) && - Changes[i].Tok->isNot(tok::r_brace)) { + CurrentChange.Tok->isNot(tok::r_brace)) { for (unsigned OuterScopeStart : llvm::reverse(ScopeStack)) { // Lambda. if (OuterScopeStart > Start && @@ -438,26 +443,26 @@ AlignTokenSequence(const FormatStyle &Style, unsigned Start, unsigned End, }; if (ShouldShiftBeAdded()) - Changes[i].Spaces += Shift; + CurrentChange.Spaces += Shift; } if (ContinuedStringLiteral) - Changes[i].Spaces += Shift; + CurrentChange.Spaces += Shift; // We should not remove required spaces unless we break the line before. - assert(Shift >= 0 || Changes[i].NewlinesBefore > 0 || - Changes[i].Spaces >= + assert(Shift > 0 || Changes[i].NewlinesBefore > 0 || + CurrentChange.Spaces >= static_cast(Changes[i].Tok->SpacesRequiredBefore) || - Changes[i].Tok->is(tok::eof)); + CurrentChange.Tok->is(tok::eof)); - Changes[i].StartOfTokenColumn += Shift; + CurrentChange.StartOfTokenColumn += Shift; if (i + 1 != Changes.size()) Changes[i + 1].PreviousEndOfTokenColumn += Shift; // If PointerAlignment is PAS_Right, keep *s or &s next to the token if ((Style.PointerAlignment == FormatStyle::PAS_Right || Style.ReferenceAlignment == FormatStyle::RAS_Right) && - Changes[i].Spaces != 0) { + CurrentChange.Spaces != 0) { const bool ReferenceNotRightAligned = Style.ReferenceAlignment != FormatStyle::RAS_Right && Style.ReferenceAlignment != FormatStyle::RAS_Pointer; @@ -578,16 +583,17 @@ static unsigned AlignTokens(const FormatStyle &Style, F &&Matches, unsigned i = StartAt; for (unsigned e = Changes.size(); i != e; ++i) { - if (Changes[i].indentAndNestingLevel() < IndentAndNestingLevel) + auto &CurrentChange = Changes[i]; + if (CurrentChange.indentAndNestingLevel() < IndentAndNestingLevel) break; - if (Changes[i].NewlinesBefore != 0) { + if (CurrentChange.NewlinesBefore != 0) { CommasBeforeMatch = 0; EndOfSequence = i; // Whether to break the alignment sequence because of an empty line. bool EmptyLineBreak = - (Changes[i].NewlinesBefore > 1) && !ACS.AcrossEmptyLines; + (CurrentChange.NewlinesBefore > 1) && !ACS.AcrossEmptyLines; // Whether to break the alignment sequence because of a line without a // match. @@ -599,19 +605,19 @@ static unsigned AlignTokens(const FormatStyle &Style, F &&Matches, // A new line starts, re-initialize line status tracking bools. // Keep the match state if a string literal is continued on this line. - if (i == 0 || Changes[i].Tok->isNot(tok::string_literal) || + if (i == 0 || CurrentChange.Tok->isNot(tok::string_literal) || Changes[i - 1].Tok->isNot(tok::string_literal)) { FoundMatchOnLine = false; } LineIsComment = true; } - if (Changes[i].Tok->isNot(tok::comment)) + if (CurrentChange.Tok->isNot(tok::comment)) LineIsComment = false; - if (Changes[i].Tok->is(tok::comma)) { + if (CurrentChange.Tok->is(tok::comma)) { ++CommasBeforeMatch; - } else if (Changes[i].indentAndNestingLevel() > IndentAndNestingLevel) { + } else if (CurrentChange.indentAndNestingLevel() > IndentAndNestingLevel) { // Call AlignTokens recursively, skipping over this scope block. unsigned StoppedAt = AlignTokens(Style, Matches, Changes, i, ACS, RightJustify); @@ -619,7 +625,7 @@ static unsigned AlignTokens(const FormatStyle &Style, F &&Matches, continue; } - if (!Matches(Changes[i])) + if (!Matches(CurrentChange)) continue; // If there is more than one matching token per line, or if the number of @@ -633,16 +639,16 @@ static unsigned AlignTokens(const FormatStyle &Style, F &&Matches, if (StartOfSequence == 0) StartOfSequence = i; - unsigned ChangeWidthLeft = Changes[i].StartOfTokenColumn; + unsigned ChangeWidthLeft = CurrentChange.StartOfTokenColumn; unsigned ChangeWidthAnchor = 0; unsigned ChangeWidthRight = 0; if (RightJustify) if (ACS.PadOperators) - ChangeWidthAnchor = Changes[i].TokenLength; + ChangeWidthAnchor = CurrentChange.TokenLength; else - ChangeWidthLeft += Changes[i].TokenLength; + ChangeWidthLeft += CurrentChange.TokenLength; else - ChangeWidthRight = Changes[i].TokenLength; + ChangeWidthRight = CurrentChange.TokenLength; for (unsigned j = i + 1; j != e && Changes[j].NewlinesBefore == 0; ++j) { ChangeWidthRight += Changes[j].Spaces; // Changes are generally 1:1 with the tokens, but a change could also be @@ -974,11 +980,7 @@ void WhitespaceManager::alignConsecutiveDeclarations() { AlignTokens( Style, [](Change const &C) { - if (C.Tok->is(TT_FunctionDeclarationName) && C.Tok->Previous && - C.Tok->Previous->isNot(tok::tilde)) { - return true; - } - if (C.Tok->is(TT_FunctionTypeLParen)) + if (C.Tok->isOneOf(TT_FunctionDeclarationName, TT_FunctionTypeLParen)) return true; if (C.Tok->isNot(TT_StartOfName)) return false; diff --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp index e5db8a654e6707..846e5fce6de7b2 100644 --- a/clang/lib/Frontend/InitPreprocessor.cpp +++ b/clang/lib/Frontend/InitPreprocessor.cpp @@ -585,6 +585,11 @@ static void InitializeStandardPredefinedMacros(const TargetInfo &TI, Builder.defineMacro("__HIP_MEMORY_SCOPE_WORKGROUP", "3"); Builder.defineMacro("__HIP_MEMORY_SCOPE_AGENT", "4"); Builder.defineMacro("__HIP_MEMORY_SCOPE_SYSTEM", "5"); + if (LangOpts.HIPStdPar) { + Builder.defineMacro("__HIPSTDPAR__"); + if (LangOpts.HIPStdParInterposeAlloc) + Builder.defineMacro("__HIPSTDPAR_INTERPOSE_ALLOC__"); + } if (LangOpts.CUDAIsDevice) { Builder.defineMacro("__HIP_DEVICE_COMPILE__"); if (!TI.hasHIPImageSupport()) { diff --git a/clang/lib/Headers/__clang_hip_math.h b/clang/lib/Headers/__clang_hip_math.h index 58aa55d7476903..11e1e7d032586f 100644 --- a/clang/lib/Headers/__clang_hip_math.h +++ b/clang/lib/Headers/__clang_hip_math.h @@ -14,9 +14,6 @@ #endif #if !defined(__HIPCC_RTC__) -#if defined(__cplusplus) -#include -#endif #include #include #ifdef __OPENMP_AMDGCN__ @@ -1311,11 +1308,11 @@ double min(double __x, double __y) { return __builtin_fmin(__x, __y); } #if !defined(__HIPCC_RTC__) && !defined(__OPENMP_AMDGCN__) __host__ inline static int min(int __arg1, int __arg2) { - return std::min(__arg1, __arg2); + return __arg1 < __arg2 ? __arg1 : __arg2; } __host__ inline static int max(int __arg1, int __arg2) { - return std::max(__arg1, __arg2); + return __arg1 > __arg2 ? __arg1 : __arg2; } #endif // !defined(__HIPCC_RTC__) && !defined(__OPENMP_AMDGCN__) #endif diff --git a/clang/lib/Headers/__stddef_max_align_t.h b/clang/lib/Headers/__stddef_max_align_t.h index e3b439285d0fd0..512606a877288b 100644 --- a/clang/lib/Headers/__stddef_max_align_t.h +++ b/clang/lib/Headers/__stddef_max_align_t.h @@ -1,4 +1,4 @@ -/*===---- __stddef_max_align_t.h - Definition of max_align_t for modules ---=== +/*===---- __stddef_max_align_t.h - Definition of max_align_t ---------------=== * * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. * See https://llvm.org/LICENSE.txt for license information. diff --git a/clang/lib/Headers/__stddef_null.h b/clang/lib/Headers/__stddef_null.h index 77d7a54025380b..7336fdab389723 100644 --- a/clang/lib/Headers/__stddef_null.h +++ b/clang/lib/Headers/__stddef_null.h @@ -7,7 +7,15 @@ *===-----------------------------------------------------------------------=== */ +#if !defined(NULL) || !__has_feature(modules) + +/* linux/stddef.h will define NULL to 0. glibc (and other) headers then define + * __need_NULL and rely on stddef.h to redefine NULL to the correct value again. + * Modules don't support redefining macros like that, but support that pattern + * in the non-modules case. + */ #undef NULL + #ifdef __cplusplus #if !defined(__MINGW32__) && !defined(_MSC_VER) #define NULL __null @@ -17,3 +25,5 @@ #else #define NULL ((void*)0) #endif + +#endif diff --git a/clang/lib/Headers/__stddef_nullptr_t.h b/clang/lib/Headers/__stddef_nullptr_t.h index 8d23ed6dc8c697..183d394d56c1b7 100644 --- a/clang/lib/Headers/__stddef_nullptr_t.h +++ b/clang/lib/Headers/__stddef_nullptr_t.h @@ -7,11 +7,9 @@ *===-----------------------------------------------------------------------=== */ -#if !defined(_NULLPTR_T) || __has_feature(modules) -/* Always define nullptr_t when modules are available. */ -#if !__has_feature(modules) +#ifndef _NULLPTR_T #define _NULLPTR_T -#endif + #ifdef __cplusplus #if defined(_MSC_EXTENSIONS) && defined(_NATIVE_NULLPTR_SUPPORTED) namespace std { @@ -19,7 +17,8 @@ typedef decltype(nullptr) nullptr_t; } using ::std::nullptr_t; #endif -#else +#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L typedef typeof(nullptr) nullptr_t; #endif + #endif diff --git a/clang/lib/Headers/__stddef_offsetof.h b/clang/lib/Headers/__stddef_offsetof.h index 84af8357c285b5..3b347b3b92f62c 100644 --- a/clang/lib/Headers/__stddef_offsetof.h +++ b/clang/lib/Headers/__stddef_offsetof.h @@ -7,7 +7,6 @@ *===-----------------------------------------------------------------------=== */ -#if !defined(offsetof) || __has_feature(modules) -/* Always define offsetof when modules are available. */ +#ifndef offsetof #define offsetof(t, d) __builtin_offsetof(t, d) #endif diff --git a/clang/lib/Headers/__stddef_ptrdiff_t.h b/clang/lib/Headers/__stddef_ptrdiff_t.h index 853cee5e09799b..3ea6d7d2852e1c 100644 --- a/clang/lib/Headers/__stddef_ptrdiff_t.h +++ b/clang/lib/Headers/__stddef_ptrdiff_t.h @@ -7,10 +7,9 @@ *===-----------------------------------------------------------------------=== */ -#if !defined(_PTRDIFF_T) || __has_feature(modules) -/* Always define ptrdiff_t when modules are available. */ -#if !__has_feature(modules) +#ifndef _PTRDIFF_T #define _PTRDIFF_T -#endif + typedef __PTRDIFF_TYPE__ ptrdiff_t; + #endif diff --git a/clang/lib/Headers/__stddef_rsize_t.h b/clang/lib/Headers/__stddef_rsize_t.h index f9c31cf8f9746a..b6428d0c12b62a 100644 --- a/clang/lib/Headers/__stddef_rsize_t.h +++ b/clang/lib/Headers/__stddef_rsize_t.h @@ -7,10 +7,9 @@ *===-----------------------------------------------------------------------=== */ -#if !defined(_RSIZE_T) || __has_feature(modules) -/* Always define rsize_t when modules are available. */ -#if !__has_feature(modules) +#ifndef _RSIZE_T #define _RSIZE_T -#endif + typedef __SIZE_TYPE__ rsize_t; + #endif diff --git a/clang/lib/Headers/__stddef_size_t.h b/clang/lib/Headers/__stddef_size_t.h index b30e245e0eb5c9..e4a389510bcdbf 100644 --- a/clang/lib/Headers/__stddef_size_t.h +++ b/clang/lib/Headers/__stddef_size_t.h @@ -7,10 +7,9 @@ *===-----------------------------------------------------------------------=== */ -#if !defined(_SIZE_T) || __has_feature(modules) -/* Always define size_t when modules are available. */ -#if !__has_feature(modules) +#ifndef _SIZE_T #define _SIZE_T -#endif + typedef __SIZE_TYPE__ size_t; + #endif diff --git a/clang/lib/Headers/__stddef_unreachable.h b/clang/lib/Headers/__stddef_unreachable.h index 5252932cd27698..3e7fe01979662a 100644 --- a/clang/lib/Headers/__stddef_unreachable.h +++ b/clang/lib/Headers/__stddef_unreachable.h @@ -7,7 +7,6 @@ *===-----------------------------------------------------------------------=== */ -#if !defined(unreachable) || __has_feature(modules) -/* Always define unreachable when modules are available. */ +#ifndef unreachable #define unreachable() __builtin_unreachable() #endif diff --git a/clang/lib/Headers/__stddef_wchar_t.h b/clang/lib/Headers/__stddef_wchar_t.h index c3f0516a4b1edf..16a6186512c0c3 100644 --- a/clang/lib/Headers/__stddef_wchar_t.h +++ b/clang/lib/Headers/__stddef_wchar_t.h @@ -8,14 +8,16 @@ */ #if !defined(__cplusplus) || (defined(_MSC_VER) && !_NATIVE_WCHAR_T_DEFINED) -/* Always define wchar_t when modules are available. */ -#if !defined(_WCHAR_T) || __has_feature(modules) -#if !__has_feature(modules) + +#ifndef _WCHAR_T #define _WCHAR_T -#if defined(_MSC_EXTENSIONS) + +#ifdef _MSC_EXTENSIONS #define _WCHAR_T_DEFINED #endif -#endif + typedef __WCHAR_TYPE__ wchar_t; + #endif + #endif diff --git a/clang/lib/Headers/__stddef_wint_t.h b/clang/lib/Headers/__stddef_wint_t.h index d0582ef971efda..0aa2915079571a 100644 --- a/clang/lib/Headers/__stddef_wint_t.h +++ b/clang/lib/Headers/__stddef_wint_t.h @@ -7,10 +7,9 @@ *===-----------------------------------------------------------------------=== */ -/* Always define wint_t when modules are available. */ -#if !defined(_WINT_T) || __has_feature(modules) -#if !__has_feature(modules) +#ifndef _WINT_T #define _WINT_T -#endif + typedef __WINT_TYPE__ wint_t; + #endif diff --git a/clang/lib/Headers/avxintrin.h b/clang/lib/Headers/avxintrin.h index 9729786923c2d5..b796bb773ec11f 100644 --- a/clang/lib/Headers/avxintrin.h +++ b/clang/lib/Headers/avxintrin.h @@ -1569,6 +1569,15 @@ _mm256_blendv_ps(__m256 __a, __m256 __b, __m256 __c) ((__m256d)__builtin_ia32_shufpd256((__v4df)(__m256d)(a), \ (__v4df)(__m256d)(b), (int)(mask))) +/* Compare */ +#define _CMP_EQ_OQ 0x00 /* Equal (ordered, non-signaling) */ +#define _CMP_LT_OS 0x01 /* Less-than (ordered, signaling) */ +#define _CMP_LE_OS 0x02 /* Less-than-or-equal (ordered, signaling) */ +#define _CMP_UNORD_Q 0x03 /* Unordered (non-signaling) */ +#define _CMP_NEQ_UQ 0x04 /* Not-equal (unordered, non-signaling) */ +#define _CMP_NLT_US 0x05 /* Not-less-than (unordered, signaling) */ +#define _CMP_NLE_US 0x06 /* Not-less-than-or-equal (unordered, signaling) */ +#define _CMP_ORD_Q 0x07 /* Ordered (non-signaling) */ #define _CMP_EQ_UQ 0x08 /* Equal (unordered, non-signaling) */ #define _CMP_NGE_US 0x09 /* Not-greater-than-or-equal (unordered, signaling) */ #define _CMP_NGT_US 0x0a /* Not-greater-than (unordered, signaling) */ @@ -1594,6 +1603,126 @@ _mm256_blendv_ps(__m256 __a, __m256 __b, __m256 __c) #define _CMP_GT_OQ 0x1e /* Greater-than (ordered, non-signaling) */ #define _CMP_TRUE_US 0x1f /* True (unordered, signaling) */ +/// Compares each of the corresponding double-precision values of two +/// 128-bit vectors of [2 x double], using the operation specified by the +/// immediate integer operand. +/// +/// Returns a [2 x double] vector consisting of two doubles corresponding to +/// the two comparison results: zero if the comparison is false, and all 1's +/// if the comparison is true. +/// +/// \headerfile +/// +/// \code +/// __m128d _mm_cmp_pd(__m128d a, __m128d b, const int c); +/// \endcode +/// +/// This intrinsic corresponds to the VCMPPD instruction. +/// +/// \param a +/// A 128-bit vector of [2 x double]. +/// \param b +/// A 128-bit vector of [2 x double]. +/// \param c +/// An immediate integer operand, with bits [4:0] specifying which comparison +/// operation to use: \n +/// 0x00: Equal (ordered, non-signaling) \n +/// 0x01: Less-than (ordered, signaling) \n +/// 0x02: Less-than-or-equal (ordered, signaling) \n +/// 0x03: Unordered (non-signaling) \n +/// 0x04: Not-equal (unordered, non-signaling) \n +/// 0x05: Not-less-than (unordered, signaling) \n +/// 0x06: Not-less-than-or-equal (unordered, signaling) \n +/// 0x07: Ordered (non-signaling) \n +/// 0x08: Equal (unordered, non-signaling) \n +/// 0x09: Not-greater-than-or-equal (unordered, signaling) \n +/// 0x0A: Not-greater-than (unordered, signaling) \n +/// 0x0B: False (ordered, non-signaling) \n +/// 0x0C: Not-equal (ordered, non-signaling) \n +/// 0x0D: Greater-than-or-equal (ordered, signaling) \n +/// 0x0E: Greater-than (ordered, signaling) \n +/// 0x0F: True (unordered, non-signaling) \n +/// 0x10: Equal (ordered, signaling) \n +/// 0x11: Less-than (ordered, non-signaling) \n +/// 0x12: Less-than-or-equal (ordered, non-signaling) \n +/// 0x13: Unordered (signaling) \n +/// 0x14: Not-equal (unordered, signaling) \n +/// 0x15: Not-less-than (unordered, non-signaling) \n +/// 0x16: Not-less-than-or-equal (unordered, non-signaling) \n +/// 0x17: Ordered (signaling) \n +/// 0x18: Equal (unordered, signaling) \n +/// 0x19: Not-greater-than-or-equal (unordered, non-signaling) \n +/// 0x1A: Not-greater-than (unordered, non-signaling) \n +/// 0x1B: False (ordered, signaling) \n +/// 0x1C: Not-equal (ordered, signaling) \n +/// 0x1D: Greater-than-or-equal (ordered, non-signaling) \n +/// 0x1E: Greater-than (ordered, non-signaling) \n +/// 0x1F: True (unordered, signaling) +/// \returns A 128-bit vector of [2 x double] containing the comparison results. +#define _mm_cmp_pd(a, b, c) \ + ((__m128d)__builtin_ia32_cmppd((__v2df)(__m128d)(a), \ + (__v2df)(__m128d)(b), (c))) + +/// Compares each of the corresponding values of two 128-bit vectors of +/// [4 x float], using the operation specified by the immediate integer +/// operand. +/// +/// Returns a [4 x float] vector consisting of four floats corresponding to +/// the four comparison results: zero if the comparison is false, and all 1's +/// if the comparison is true. +/// +/// \headerfile +/// +/// \code +/// __m128 _mm_cmp_ps(__m128 a, __m128 b, const int c); +/// \endcode +/// +/// This intrinsic corresponds to the VCMPPS instruction. +/// +/// \param a +/// A 128-bit vector of [4 x float]. +/// \param b +/// A 128-bit vector of [4 x float]. +/// \param c +/// An immediate integer operand, with bits [4:0] specifying which comparison +/// operation to use: \n +/// 0x00: Equal (ordered, non-signaling) \n +/// 0x01: Less-than (ordered, signaling) \n +/// 0x02: Less-than-or-equal (ordered, signaling) \n +/// 0x03: Unordered (non-signaling) \n +/// 0x04: Not-equal (unordered, non-signaling) \n +/// 0x05: Not-less-than (unordered, signaling) \n +/// 0x06: Not-less-than-or-equal (unordered, signaling) \n +/// 0x07: Ordered (non-signaling) \n +/// 0x08: Equal (unordered, non-signaling) \n +/// 0x09: Not-greater-than-or-equal (unordered, signaling) \n +/// 0x0A: Not-greater-than (unordered, signaling) \n +/// 0x0B: False (ordered, non-signaling) \n +/// 0x0C: Not-equal (ordered, non-signaling) \n +/// 0x0D: Greater-than-or-equal (ordered, signaling) \n +/// 0x0E: Greater-than (ordered, signaling) \n +/// 0x0F: True (unordered, non-signaling) \n +/// 0x10: Equal (ordered, signaling) \n +/// 0x11: Less-than (ordered, non-signaling) \n +/// 0x12: Less-than-or-equal (ordered, non-signaling) \n +/// 0x13: Unordered (signaling) \n +/// 0x14: Not-equal (unordered, signaling) \n +/// 0x15: Not-less-than (unordered, non-signaling) \n +/// 0x16: Not-less-than-or-equal (unordered, non-signaling) \n +/// 0x17: Ordered (signaling) \n +/// 0x18: Equal (unordered, signaling) \n +/// 0x19: Not-greater-than-or-equal (unordered, non-signaling) \n +/// 0x1A: Not-greater-than (unordered, non-signaling) \n +/// 0x1B: False (ordered, signaling) \n +/// 0x1C: Not-equal (ordered, signaling) \n +/// 0x1D: Greater-than-or-equal (ordered, non-signaling) \n +/// 0x1E: Greater-than (ordered, non-signaling) \n +/// 0x1F: True (unordered, signaling) +/// \returns A 128-bit vector of [4 x float] containing the comparison results. +#define _mm_cmp_ps(a, b, c) \ + ((__m128)__builtin_ia32_cmpps((__v4sf)(__m128)(a), \ + (__v4sf)(__m128)(b), (c))) + /// Compares each of the corresponding double-precision values of two /// 256-bit vectors of [4 x double], using the operation specified by the /// immediate integer operand. @@ -1714,6 +1843,124 @@ _mm256_blendv_ps(__m256 __a, __m256 __b, __m256 __c) ((__m256)__builtin_ia32_cmpps256((__v8sf)(__m256)(a), \ (__v8sf)(__m256)(b), (c))) +/// Compares each of the corresponding scalar double-precision values of +/// two 128-bit vectors of [2 x double], using the operation specified by the +/// immediate integer operand. +/// +/// If the result is true, all 64 bits of the destination vector are set; +/// otherwise they are cleared. +/// +/// \headerfile +/// +/// \code +/// __m128d _mm_cmp_sd(__m128d a, __m128d b, const int c); +/// \endcode +/// +/// This intrinsic corresponds to the VCMPSD instruction. +/// +/// \param a +/// A 128-bit vector of [2 x double]. +/// \param b +/// A 128-bit vector of [2 x double]. +/// \param c +/// An immediate integer operand, with bits [4:0] specifying which comparison +/// operation to use: \n +/// 0x00: Equal (ordered, non-signaling) \n +/// 0x01: Less-than (ordered, signaling) \n +/// 0x02: Less-than-or-equal (ordered, signaling) \n +/// 0x03: Unordered (non-signaling) \n +/// 0x04: Not-equal (unordered, non-signaling) \n +/// 0x05: Not-less-than (unordered, signaling) \n +/// 0x06: Not-less-than-or-equal (unordered, signaling) \n +/// 0x07: Ordered (non-signaling) \n +/// 0x08: Equal (unordered, non-signaling) \n +/// 0x09: Not-greater-than-or-equal (unordered, signaling) \n +/// 0x0A: Not-greater-than (unordered, signaling) \n +/// 0x0B: False (ordered, non-signaling) \n +/// 0x0C: Not-equal (ordered, non-signaling) \n +/// 0x0D: Greater-than-or-equal (ordered, signaling) \n +/// 0x0E: Greater-than (ordered, signaling) \n +/// 0x0F: True (unordered, non-signaling) \n +/// 0x10: Equal (ordered, signaling) \n +/// 0x11: Less-than (ordered, non-signaling) \n +/// 0x12: Less-than-or-equal (ordered, non-signaling) \n +/// 0x13: Unordered (signaling) \n +/// 0x14: Not-equal (unordered, signaling) \n +/// 0x15: Not-less-than (unordered, non-signaling) \n +/// 0x16: Not-less-than-or-equal (unordered, non-signaling) \n +/// 0x17: Ordered (signaling) \n +/// 0x18: Equal (unordered, signaling) \n +/// 0x19: Not-greater-than-or-equal (unordered, non-signaling) \n +/// 0x1A: Not-greater-than (unordered, non-signaling) \n +/// 0x1B: False (ordered, signaling) \n +/// 0x1C: Not-equal (ordered, signaling) \n +/// 0x1D: Greater-than-or-equal (ordered, non-signaling) \n +/// 0x1E: Greater-than (ordered, non-signaling) \n +/// 0x1F: True (unordered, signaling) +/// \returns A 128-bit vector of [2 x double] containing the comparison results. +#define _mm_cmp_sd(a, b, c) \ + ((__m128d)__builtin_ia32_cmpsd((__v2df)(__m128d)(a), \ + (__v2df)(__m128d)(b), (c))) + +/// Compares each of the corresponding scalar values of two 128-bit +/// vectors of [4 x float], using the operation specified by the immediate +/// integer operand. +/// +/// If the result is true, all 32 bits of the destination vector are set; +/// otherwise they are cleared. +/// +/// \headerfile +/// +/// \code +/// __m128 _mm_cmp_ss(__m128 a, __m128 b, const int c); +/// \endcode +/// +/// This intrinsic corresponds to the VCMPSS instruction. +/// +/// \param a +/// A 128-bit vector of [4 x float]. +/// \param b +/// A 128-bit vector of [4 x float]. +/// \param c +/// An immediate integer operand, with bits [4:0] specifying which comparison +/// operation to use: \n +/// 0x00: Equal (ordered, non-signaling) \n +/// 0x01: Less-than (ordered, signaling) \n +/// 0x02: Less-than-or-equal (ordered, signaling) \n +/// 0x03: Unordered (non-signaling) \n +/// 0x04: Not-equal (unordered, non-signaling) \n +/// 0x05: Not-less-than (unordered, signaling) \n +/// 0x06: Not-less-than-or-equal (unordered, signaling) \n +/// 0x07: Ordered (non-signaling) \n +/// 0x08: Equal (unordered, non-signaling) \n +/// 0x09: Not-greater-than-or-equal (unordered, signaling) \n +/// 0x0A: Not-greater-than (unordered, signaling) \n +/// 0x0B: False (ordered, non-signaling) \n +/// 0x0C: Not-equal (ordered, non-signaling) \n +/// 0x0D: Greater-than-or-equal (ordered, signaling) \n +/// 0x0E: Greater-than (ordered, signaling) \n +/// 0x0F: True (unordered, non-signaling) \n +/// 0x10: Equal (ordered, signaling) \n +/// 0x11: Less-than (ordered, non-signaling) \n +/// 0x12: Less-than-or-equal (ordered, non-signaling) \n +/// 0x13: Unordered (signaling) \n +/// 0x14: Not-equal (unordered, signaling) \n +/// 0x15: Not-less-than (unordered, non-signaling) \n +/// 0x16: Not-less-than-or-equal (unordered, non-signaling) \n +/// 0x17: Ordered (signaling) \n +/// 0x18: Equal (unordered, signaling) \n +/// 0x19: Not-greater-than-or-equal (unordered, non-signaling) \n +/// 0x1A: Not-greater-than (unordered, non-signaling) \n +/// 0x1B: False (ordered, signaling) \n +/// 0x1C: Not-equal (ordered, signaling) \n +/// 0x1D: Greater-than-or-equal (ordered, non-signaling) \n +/// 0x1E: Greater-than (ordered, non-signaling) \n +/// 0x1F: True (unordered, signaling) +/// \returns A 128-bit vector of [4 x float] containing the comparison results. +#define _mm_cmp_ss(a, b, c) \ + ((__m128)__builtin_ia32_cmpss((__v4sf)(__m128)(a), \ + (__v4sf)(__m128)(b), (c))) + /// Takes a [8 x i32] vector and returns the vector element value /// indexed by the immediate constant operand. /// diff --git a/clang/lib/Headers/emmintrin.h b/clang/lib/Headers/emmintrin.h index 20cd1d4d732fca..8de2864b110653 100644 --- a/clang/lib/Headers/emmintrin.h +++ b/clang/lib/Headers/emmintrin.h @@ -4742,127 +4742,6 @@ static __inline__ __m128d __DEFAULT_FN_ATTRS _mm_castsi128_pd(__m128i __a) { return (__m128d)__a; } -/// Compares each of the corresponding double-precision values of two -/// 128-bit vectors of [2 x double], using the operation specified by the -/// immediate integer operand. -/// -/// Returns a [2 x double] vector consisting of two doubles corresponding to -/// the two comparison results: zero if the comparison is false, and all 1's -/// if the comparison is true. -/// -/// \headerfile -/// -/// \code -/// __m128d _mm_cmp_pd(__m128d a, __m128d b, const int c); -/// \endcode -/// -/// This intrinsic corresponds to the (V)CMPPD instruction. -/// -/// \param a -/// A 128-bit vector of [2 x double]. -/// \param b -/// A 128-bit vector of [2 x double]. -/// \param c -/// An immediate integer operand, with bits [4:0] specifying which comparison -/// operation to use: \n -/// (Note that without avx enabled, only bits [2:0] are supported) \n -/// 0x00: Equal (ordered, non-signaling) \n -/// 0x01: Less-than (ordered, signaling) \n -/// 0x02: Less-than-or-equal (ordered, signaling) \n -/// 0x03: Unordered (non-signaling) \n -/// 0x04: Not-equal (unordered, non-signaling) \n -/// 0x05: Not-less-than (unordered, signaling) \n -/// 0x06: Not-less-than-or-equal (unordered, signaling) \n -/// 0x07: Ordered (non-signaling) \n -/// 0x08: Equal (unordered, non-signaling) \n -/// 0x09: Not-greater-than-or-equal (unordered, signaling) \n -/// 0x0A: Not-greater-than (unordered, signaling) \n -/// 0x0B: False (ordered, non-signaling) \n -/// 0x0C: Not-equal (ordered, non-signaling) \n -/// 0x0D: Greater-than-or-equal (ordered, signaling) \n -/// 0x0E: Greater-than (ordered, signaling) \n -/// 0x0F: True (unordered, non-signaling) \n -/// 0x10: Equal (ordered, signaling) \n -/// 0x11: Less-than (ordered, non-signaling) \n -/// 0x12: Less-than-or-equal (ordered, non-signaling) \n -/// 0x13: Unordered (signaling) \n -/// 0x14: Not-equal (unordered, signaling) \n -/// 0x15: Not-less-than (unordered, non-signaling) \n -/// 0x16: Not-less-than-or-equal (unordered, non-signaling) \n -/// 0x17: Ordered (signaling) \n -/// 0x18: Equal (unordered, signaling) \n -/// 0x19: Not-greater-than-or-equal (unordered, non-signaling) \n -/// 0x1A: Not-greater-than (unordered, non-signaling) \n -/// 0x1B: False (ordered, signaling) \n -/// 0x1C: Not-equal (ordered, signaling) \n -/// 0x1D: Greater-than-or-equal (ordered, non-signaling) \n -/// 0x1E: Greater-than (ordered, non-signaling) \n -/// 0x1F: True (unordered, signaling) -/// \returns A 128-bit vector of [2 x double] containing the comparison results. -#define _mm_cmp_pd(a, b, c) \ - ((__m128d)__builtin_ia32_cmppd((__v2df)(__m128d)(a), (__v2df)(__m128d)(b), \ - (c))) - -/// Compares each of the corresponding scalar double-precision values of -/// two 128-bit vectors of [2 x double], using the operation specified by the -/// immediate integer operand. -/// -/// If the result is true, all 64 bits of the destination vector are set; -/// otherwise they are cleared. -/// -/// \headerfile -/// -/// \code -/// __m128d _mm_cmp_sd(__m128d a, __m128d b, const int c); -/// \endcode -/// -/// This intrinsic corresponds to the (V)CMPSD instruction. -/// -/// \param a -/// A 128-bit vector of [2 x double]. -/// \param b -/// A 128-bit vector of [2 x double]. -/// \param c -/// An immediate integer operand, with bits [4:0] specifying which comparison -/// operation to use: \n -/// (Note that without avx enabled, only bits [2:0] are supported) \n -/// 0x00: Equal (ordered, non-signaling) \n -/// 0x01: Less-than (ordered, signaling) \n -/// 0x02: Less-than-or-equal (ordered, signaling) \n -/// 0x03: Unordered (non-signaling) \n -/// 0x04: Not-equal (unordered, non-signaling) \n -/// 0x05: Not-less-than (unordered, signaling) \n -/// 0x06: Not-less-than-or-equal (unordered, signaling) \n -/// 0x07: Ordered (non-signaling) \n -/// 0x08: Equal (unordered, non-signaling) \n -/// 0x09: Not-greater-than-or-equal (unordered, signaling) \n -/// 0x0A: Not-greater-than (unordered, signaling) \n -/// 0x0B: False (ordered, non-signaling) \n -/// 0x0C: Not-equal (ordered, non-signaling) \n -/// 0x0D: Greater-than-or-equal (ordered, signaling) \n -/// 0x0E: Greater-than (ordered, signaling) \n -/// 0x0F: True (unordered, non-signaling) \n -/// 0x10: Equal (ordered, signaling) \n -/// 0x11: Less-than (ordered, non-signaling) \n -/// 0x12: Less-than-or-equal (ordered, non-signaling) \n -/// 0x13: Unordered (signaling) \n -/// 0x14: Not-equal (unordered, signaling) \n -/// 0x15: Not-less-than (unordered, non-signaling) \n -/// 0x16: Not-less-than-or-equal (unordered, non-signaling) \n -/// 0x17: Ordered (signaling) \n -/// 0x18: Equal (unordered, signaling) \n -/// 0x19: Not-greater-than-or-equal (unordered, non-signaling) \n -/// 0x1A: Not-greater-than (unordered, non-signaling) \n -/// 0x1B: False (ordered, signaling) \n -/// 0x1C: Not-equal (ordered, signaling) \n -/// 0x1D: Greater-than-or-equal (ordered, non-signaling) \n -/// 0x1E: Greater-than (ordered, non-signaling) \n -/// 0x1F: True (unordered, signaling) -/// \returns A 128-bit vector of [2 x double] containing the comparison results. -#define _mm_cmp_sd(a, b, c) \ - ((__m128d)__builtin_ia32_cmpsd((__v2df)(__m128d)(a), (__v2df)(__m128d)(b), \ - (c))) - #if defined(__cplusplus) extern "C" { #endif diff --git a/clang/lib/Headers/module.modulemap b/clang/lib/Headers/module.modulemap index 6894672ef0529b..a786689d391773 100644 --- a/clang/lib/Headers/module.modulemap +++ b/clang/lib/Headers/module.modulemap @@ -153,9 +153,164 @@ module _Builtin_intrinsics [system] [extern_c] { } } -module _Builtin_stddef_max_align_t [system] [extern_c] { - header "__stddef_max_align_t.h" +// Start -fbuiltin-headers-in-system-modules affected modules + +// The following modules all ignore their top level headers +// when -fbuiltin-headers-in-system-modules is passed, and +// most of those headers join system modules when present. + +// e.g. if -fbuiltin-headers-in-system-modules is passed, then +// float.h will not be in the _Builtin_float module (that module +// will be empty). If there is a system module that declares +// `header "float.h"`, then the builtin float.h will join +// that module. The system float.h (if present) will be treated +// as a textual header in the sytem module. +module _Builtin_float [system] { + header "float.h" + export * +} + +module _Builtin_inttypes [system] { + header "inttypes.h" + export * +} + +module _Builtin_iso646 [system] { + header "iso646.h" + export * +} + +module _Builtin_limits [system] { + header "limits.h" + export * +} + +module _Builtin_stdalign [system] { + header "stdalign.h" + export * +} + +// When -fbuiltin-headers-in-system-modules is passed, only +// the top level headers are removed, the implementation headers +// will always be in their submodules. That means when stdarg.h +// is included, it will still import this module and make the +// appropriate submodules visible. +module _Builtin_stdarg [system] { + textual header "stdarg.h" + + explicit module __gnuc_va_list { + header "__stdarg___gnuc_va_list.h" + export * + } + + explicit module __va_copy { + header "__stdarg___va_copy.h" + export * + } + + explicit module va_arg { + header "__stdarg_va_arg.h" + export * + } + + explicit module va_copy { + header "__stdarg_va_copy.h" + export * + } + + explicit module va_list { + header "__stdarg_va_list.h" + export * + } +} + +module _Builtin_stdatomic [system] { + header "stdatomic.h" + export * +} + +module _Builtin_stdbool [system] { + header "stdbool.h" + export * +} + +module _Builtin_stddef [system] { + textual header "stddef.h" + + explicit module max_align_t { + header "__stddef_max_align_t.h" + export * + } + + explicit module null { + header "__stddef_null.h" + export * + } + + explicit module nullptr_t { + header "__stddef_nullptr_t.h" + export * + } + + explicit module offsetof { + header "__stddef_offsetof.h" + export * + } + + explicit module ptrdiff_t { + header "__stddef_ptrdiff_t.h" + export * + } + + explicit module rsize_t { + header "__stddef_rsize_t.h" + export * + } + + explicit module size_t { + header "__stddef_size_t.h" + export * + } + + explicit module unreachable { + header "__stddef_unreachable.h" + export * + } + + explicit module wchar_t { + header "__stddef_wchar_t.h" + export * + } +} + +/* wint_t is provided by and not . It's here + * for compatibility, but must be explicitly requested. Therefore + * __stddef_wint_t.h is not part of _Builtin_stddef. */ +module _Builtin_stddef_wint_t [system] { + header "__stddef_wint_t.h" + export * +} + +module _Builtin_stdint [system] { + header "stdint.h" + export * +} + +module _Builtin_stdnoreturn [system] { + header "stdnoreturn.h" + export * +} + +module _Builtin_tgmath [system] { + header "tgmath.h" + export * +} + +module _Builtin_unwind [system] { + header "unwind.h" + export * } +// End -fbuiltin-headers-in-system-modules affected modules module opencl_c { requires opencl diff --git a/clang/lib/Headers/stdarg.h b/clang/lib/Headers/stdarg.h index 085e2bb861ceb5..94b066566f084e 100644 --- a/clang/lib/Headers/stdarg.h +++ b/clang/lib/Headers/stdarg.h @@ -7,9 +7,31 @@ *===-----------------------------------------------------------------------=== */ -#if !defined(__STDARG_H) || defined(__need___va_list) || \ - defined(__need_va_list) || defined(__need_va_arg) || \ - defined(__need___va_copy) || defined(__need_va_copy) +/* + * This header is designed to be included multiple times. If any of the __need_ + * macros are defined, then only that subset of interfaces are provided. This + * can be useful for POSIX headers that need to not expose all of stdarg.h, but + * need to use some of its interfaces. Otherwise this header provides all of + * the expected interfaces. + * + * When clang modules are enabled, this header is a textual header. It ignores + * its header guard so that multiple submodules can export its interfaces. + * Take module SM with submodules A and B, whose headers both include stdarg.h + * When SM.A builds, __STDARG_H will be defined. When SM.B builds, the + * definition from SM.A will leak when building without local submodule + * visibility. stdarg.h wouldn't include any of its implementation headers, and + * SM.B wouldn't import any of the stdarg modules, and SM.B's `export *` + * wouldn't export any stdarg interfaces as expected. However, since stdarg.h + * ignores its header guard when building with modules, it all works as + * expected. + * + * When clang modules are not enabled, the header guards can function in the + * normal simple fashion. + */ +#if !defined(__STDARG_H) || __has_feature(modules) || \ + defined(__need___va_list) || defined(__need_va_list) || \ + defined(__need_va_arg) || defined(__need___va_copy) || \ + defined(__need_va_copy) #if !defined(__need___va_list) && !defined(__need_va_list) && \ !defined(__need_va_arg) && !defined(__need___va_copy) && \ diff --git a/clang/lib/Headers/stddef.h b/clang/lib/Headers/stddef.h index 9c6dd0cd62dae1..e0ad7b8d17aff9 100644 --- a/clang/lib/Headers/stddef.h +++ b/clang/lib/Headers/stddef.h @@ -7,23 +7,41 @@ *===-----------------------------------------------------------------------=== */ -#if !defined(__STDDEF_H) || defined(__need_ptrdiff_t) || \ - defined(__need_size_t) || defined(__need_rsize_t) || \ - defined(__need_wchar_t) || defined(__need_NULL) || \ - defined(__need_nullptr_t) || defined(__need_unreachable) || \ - defined(__need_max_align_t) || defined(__need_offsetof) || \ - defined(__need_wint_t) || \ - (defined(__STDC_WANT_LIB_EXT1__) && __STDC_WANT_LIB_EXT1__ >= 1) +/* + * This header is designed to be included multiple times. If any of the __need_ + * macros are defined, then only that subset of interfaces are provided. This + * can be useful for POSIX headers that need to not expose all of stddef.h, but + * need to use some of its interfaces. Otherwise this header provides all of + * the expected interfaces. + * + * When clang modules are enabled, this header is a textual header. It ignores + * its header guard so that multiple submodules can export its interfaces. + * Take module SM with submodules A and B, whose headers both include stddef.h + * When SM.A builds, __STDDEF_H will be defined. When SM.B builds, the + * definition from SM.A will leak when building without local submodule + * visibility. stddef.h wouldn't include any of its implementation headers, and + * SM.B wouldn't import any of the stddef modules, and SM.B's `export *` + * wouldn't export any stddef interfaces as expected. However, since stddef.h + * ignores its header guard when building with modules, it all works as + * expected. + * + * When clang modules are not enabled, the header guards can function in the + * normal simple fashion. + */ +#if !defined(__STDDEF_H) || __has_feature(modules) || \ + (defined(__STDC_WANT_LIB_EXT1__) && __STDC_WANT_LIB_EXT1__ >= 1) || \ + defined(__need_ptrdiff_t) || defined(__need_size_t) || \ + defined(__need_rsize_t) || defined(__need_wchar_t) || \ + defined(__need_NULL) || defined(__need_nullptr_t) || \ + defined(__need_unreachable) || defined(__need_max_align_t) || \ + defined(__need_offsetof) || defined(__need_wint_t) #if !defined(__need_ptrdiff_t) && !defined(__need_size_t) && \ !defined(__need_rsize_t) && !defined(__need_wchar_t) && \ !defined(__need_NULL) && !defined(__need_nullptr_t) && \ !defined(__need_unreachable) && !defined(__need_max_align_t) && \ !defined(__need_offsetof) && !defined(__need_wint_t) -/* Always define miscellaneous pieces when modules are available. */ -#if !__has_feature(modules) #define __STDDEF_H -#endif #define __need_ptrdiff_t #define __need_size_t /* ISO9899:2011 7.20 (C11 Annex K): Define rsize_t if __STDC_WANT_LIB_EXT1__ is diff --git a/clang/lib/Headers/xmmintrin.h b/clang/lib/Headers/xmmintrin.h index 73b1ab4bb4a3d3..2d1d33c69f0bbd 100644 --- a/clang/lib/Headers/xmmintrin.h +++ b/clang/lib/Headers/xmmintrin.h @@ -2936,134 +2936,6 @@ _mm_movemask_ps(__m128 __a) return __builtin_ia32_movmskps((__v4sf)__a); } -/* Compare */ -#define _CMP_EQ_OQ 0x00 /* Equal (ordered, non-signaling) */ -#define _CMP_LT_OS 0x01 /* Less-than (ordered, signaling) */ -#define _CMP_LE_OS 0x02 /* Less-than-or-equal (ordered, signaling) */ -#define _CMP_UNORD_Q 0x03 /* Unordered (non-signaling) */ -#define _CMP_NEQ_UQ 0x04 /* Not-equal (unordered, non-signaling) */ -#define _CMP_NLT_US 0x05 /* Not-less-than (unordered, signaling) */ -#define _CMP_NLE_US 0x06 /* Not-less-than-or-equal (unordered, signaling) */ -#define _CMP_ORD_Q 0x07 /* Ordered (non-signaling) */ - -/// Compares each of the corresponding values of two 128-bit vectors of -/// [4 x float], using the operation specified by the immediate integer -/// operand. -/// -/// Returns a [4 x float] vector consisting of four floats corresponding to -/// the four comparison results: zero if the comparison is false, and all 1's -/// if the comparison is true. -/// -/// \headerfile -/// -/// \code -/// __m128 _mm_cmp_ps(__m128 a, __m128 b, const int c); -/// \endcode -/// -/// This intrinsic corresponds to the (V)CMPPS instruction. -/// -/// \param a -/// A 128-bit vector of [4 x float]. -/// \param b -/// A 128-bit vector of [4 x float]. -/// \param c -/// An immediate integer operand, with bits [4:0] specifying which comparison -/// operation to use: \n -/// (Note that without avx enabled, only bits [2:0] are supported) \n -/// 0x00: Equal (ordered, non-signaling) \n -/// 0x01: Less-than (ordered, signaling) \n -/// 0x02: Less-than-or-equal (ordered, signaling) \n -/// 0x03: Unordered (non-signaling) \n -/// 0x04: Not-equal (unordered, non-signaling) \n -/// 0x05: Not-less-than (unordered, signaling) \n -/// 0x06: Not-less-than-or-equal (unordered, signaling) \n -/// 0x07: Ordered (non-signaling) \n -/// 0x08: Equal (unordered, non-signaling) \n -/// 0x09: Not-greater-than-or-equal (unordered, signaling) \n -/// 0x0A: Not-greater-than (unordered, signaling) \n -/// 0x0B: False (ordered, non-signaling) \n -/// 0x0C: Not-equal (ordered, non-signaling) \n -/// 0x0D: Greater-than-or-equal (ordered, signaling) \n -/// 0x0E: Greater-than (ordered, signaling) \n -/// 0x0F: True (unordered, non-signaling) \n -/// 0x10: Equal (ordered, signaling) \n -/// 0x11: Less-than (ordered, non-signaling) \n -/// 0x12: Less-than-or-equal (ordered, non-signaling) \n -/// 0x13: Unordered (signaling) \n -/// 0x14: Not-equal (unordered, signaling) \n -/// 0x15: Not-less-than (unordered, non-signaling) \n -/// 0x16: Not-less-than-or-equal (unordered, non-signaling) \n -/// 0x17: Ordered (signaling) \n -/// 0x18: Equal (unordered, signaling) \n -/// 0x19: Not-greater-than-or-equal (unordered, non-signaling) \n -/// 0x1A: Not-greater-than (unordered, non-signaling) \n -/// 0x1B: False (ordered, signaling) \n -/// 0x1C: Not-equal (ordered, signaling) \n -/// 0x1D: Greater-than-or-equal (ordered, non-signaling) \n -/// 0x1E: Greater-than (ordered, non-signaling) \n -/// 0x1F: True (unordered, signaling) -/// \returns A 128-bit vector of [4 x float] containing the comparison results. -#define _mm_cmp_ps(a, b, c) \ - ((__m128)__builtin_ia32_cmpps((__v4sf)(__m128)(a), (__v4sf)(__m128)(b), (c))) - -/// Compares each of the corresponding scalar values of two 128-bit -/// vectors of [4 x float], using the operation specified by the immediate -/// integer operand. -/// -/// If the result is true, all 32 bits of the destination vector are set; -/// otherwise they are cleared. -/// -/// \headerfile -/// -/// \code -/// __m128 _mm_cmp_ss(__m128 a, __m128 b, const int c); -/// \endcode -/// -/// This intrinsic corresponds to the (V)CMPSS instruction. -/// -/// \param a -/// A 128-bit vector of [4 x float]. -/// \param b -/// A 128-bit vector of [4 x float]. -/// \param c -/// An immediate integer operand, with bits [4:0] specifying which comparison -/// operation to use: \n -/// (Note that without avx enabled, only bits [2:0] are supported) \n -/// 0x00: Equal (ordered, non-signaling) \n -/// 0x01: Less-than (ordered, signaling) \n -/// 0x02: Less-than-or-equal (ordered, signaling) \n -/// 0x03: Unordered (non-signaling) \n -/// 0x04: Not-equal (unordered, non-signaling) \n -/// 0x05: Not-less-than (unordered, signaling) \n -/// 0x06: Not-less-than-or-equal (unordered, signaling) \n -/// 0x07: Ordered (non-signaling) \n -/// 0x08: Equal (unordered, non-signaling) \n -/// 0x09: Not-greater-than-or-equal (unordered, signaling) \n -/// 0x0A: Not-greater-than (unordered, signaling) \n -/// 0x0B: False (ordered, non-signaling) \n -/// 0x0C: Not-equal (ordered, non-signaling) \n -/// 0x0D: Greater-than-or-equal (ordered, signaling) \n -/// 0x0E: Greater-than (ordered, signaling) \n -/// 0x0F: True (unordered, non-signaling) \n -/// 0x10: Equal (ordered, signaling) \n -/// 0x11: Less-than (ordered, non-signaling) \n -/// 0x12: Less-than-or-equal (ordered, non-signaling) \n -/// 0x13: Unordered (signaling) \n -/// 0x14: Not-equal (unordered, signaling) \n -/// 0x15: Not-less-than (unordered, non-signaling) \n -/// 0x16: Not-less-than-or-equal (unordered, non-signaling) \n -/// 0x17: Ordered (signaling) \n -/// 0x18: Equal (unordered, signaling) \n -/// 0x19: Not-greater-than-or-equal (unordered, non-signaling) \n -/// 0x1A: Not-greater-than (unordered, non-signaling) \n -/// 0x1B: False (ordered, signaling) \n -/// 0x1C: Not-equal (ordered, signaling) \n -/// 0x1D: Greater-than-or-equal (ordered, non-signaling) \n -/// 0x1E: Greater-than (ordered, non-signaling) \n -/// 0x1F: True (unordered, signaling) -/// \returns A 128-bit vector of [4 x float] containing the comparison results. -#define _mm_cmp_ss(a, b, c) \ - ((__m128)__builtin_ia32_cmpss((__v4sf)(__m128)(a), (__v4sf)(__m128)(b), (c))) #define _MM_ALIGN16 __attribute__((aligned(16))) diff --git a/clang/lib/Lex/ModuleMap.cpp b/clang/lib/Lex/ModuleMap.cpp index e8437572ebf4bf..f65a5f145c0439 100644 --- a/clang/lib/Lex/ModuleMap.cpp +++ b/clang/lib/Lex/ModuleMap.cpp @@ -1551,8 +1551,6 @@ namespace clang { /// (or the end of the file). void skipUntil(MMToken::TokenKind K); - using ModuleId = SmallVector, 2>; - bool parseModuleId(ModuleId &Id); void parseModuleDecl(); void parseExternModuleDecl(); diff --git a/clang/lib/Lex/Preprocessor.cpp b/clang/lib/Lex/Preprocessor.cpp index 73c37bc5161c4b..c16dd75fbbd3f5 100644 --- a/clang/lib/Lex/Preprocessor.cpp +++ b/clang/lib/Lex/Preprocessor.cpp @@ -998,6 +998,18 @@ void Preprocessor::Lex(Token &Result) { } } +void Preprocessor::LexTokensUntilEOF(std::vector *Tokens) { + while (1) { + Token Tok; + Lex(Tok); + if (Tok.isOneOf(tok::unknown, tok::eof, tok::eod, + tok::annot_repl_input_end)) + break; + if (Tokens != nullptr) + Tokens->push_back(Tok); + } +} + /// Lex a header-name token (including one formed from header-name-tokens if /// \p AllowConcatenation is \c true). /// diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 9bda4ec7d59bbf..bcc70c04dec91b 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -4038,7 +4038,7 @@ void Parser::ParseDeclarationSpecifiers( isStorageClass = true; break; case tok::kw_auto: - if (getLangOpts().CPlusPlus11) { + if (getLangOpts().CPlusPlus11 || getLangOpts().C23) { if (isKnownToBeTypeSpecifier(GetLookAheadToken(1))) { isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_auto, Loc, PrevSpec, DiagID, Policy); @@ -5009,7 +5009,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, BaseRange = SourceRange(ColonLoc, DeclaratorInfo.getSourceRange().getEnd()); - if (!getLangOpts().ObjC) { + if (!getLangOpts().ObjC && !getLangOpts().C23) { if (getLangOpts().CPlusPlus11) Diag(ColonLoc, diag::warn_cxx98_compat_enum_fixed_underlying_type) << BaseRange; @@ -5835,8 +5835,7 @@ bool Parser::isDeclarationSpecifier( bool Parser::isConstructorDeclarator(bool IsUnqualified, bool DeductionGuide, DeclSpec::FriendSpecified IsFriend, const ParsedTemplateInfo *TemplateInfo) { - TentativeParsingAction TPA(*this); - + RevertingTentativeParsingAction TPA(*this); // Parse the C++ scope specifier. CXXScopeSpec SS; if (TemplateInfo && TemplateInfo->TemplateParams) @@ -5845,7 +5844,6 @@ bool Parser::isConstructorDeclarator(bool IsUnqualified, bool DeductionGuide, if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr, /*ObjectHasErrors=*/false, /*EnteringContext=*/true)) { - TPA.Revert(); return false; } @@ -5857,7 +5855,6 @@ bool Parser::isConstructorDeclarator(bool IsUnqualified, bool DeductionGuide, } else if (Tok.is(tok::annot_template_id)) { ConsumeAnnotationToken(); } else { - TPA.Revert(); return false; } @@ -5867,7 +5864,6 @@ bool Parser::isConstructorDeclarator(bool IsUnqualified, bool DeductionGuide, // Current class name must be followed by a left parenthesis. if (Tok.isNot(tok::l_paren)) { - TPA.Revert(); return false; } ConsumeParen(); @@ -5876,7 +5872,6 @@ bool Parser::isConstructorDeclarator(bool IsUnqualified, bool DeductionGuide, // that we have a constructor. if (Tok.is(tok::r_paren) || (Tok.is(tok::ellipsis) && NextToken().is(tok::r_paren))) { - TPA.Revert(); return true; } @@ -5885,7 +5880,6 @@ bool Parser::isConstructorDeclarator(bool IsUnqualified, bool DeductionGuide, if (getLangOpts().CPlusPlus11 && isCXX11AttributeSpecifier(/*Disambiguate*/ false, /*OuterMightBeMessageSend*/ true)) { - TPA.Revert(); return true; } @@ -5906,9 +5900,17 @@ bool Parser::isConstructorDeclarator(bool IsUnqualified, bool DeductionGuide, // If we parsed a scope specifier as well as friend, // we might be parsing a friend constructor. bool IsConstructor = false; - if (isDeclarationSpecifier(IsFriend && !SS.isSet() - ? ImplicitTypenameContext::No - : ImplicitTypenameContext::Yes)) + ImplicitTypenameContext ITC = IsFriend && !SS.isSet() + ? ImplicitTypenameContext::No + : ImplicitTypenameContext::Yes; + // Constructors cannot have this parameters, but we support that scenario here + // to improve diagnostic. + if (Tok.is(tok::kw_this)) { + ConsumeToken(); + return isDeclarationSpecifier(ITC); + } + + if (isDeclarationSpecifier(ITC)) IsConstructor = true; else if (Tok.is(tok::identifier) || (Tok.is(tok::annot_cxxscope) && NextToken().is(tok::identifier))) { @@ -5977,8 +5979,6 @@ bool Parser::isConstructorDeclarator(bool IsUnqualified, bool DeductionGuide, break; } } - - TPA.Revert(); return IsConstructor; } @@ -7356,6 +7356,7 @@ void Parser::ParseFunctionDeclaratorIdentifierList( /// '=' assignment-expression /// [GNU] declaration-specifiers abstract-declarator[opt] attributes /// [C++11] attribute-specifier-seq parameter-declaration +/// [C++2b] attribute-specifier-seq 'this' parameter-declaration /// void Parser::ParseParameterDeclarationClause( DeclaratorContext DeclaratorCtx, ParsedAttributes &FirstArgAttrs, @@ -7420,9 +7421,16 @@ void Parser::ParseParameterDeclarationClause( SourceLocation DSStart = Tok.getLocation(); + // Parse a C++23 Explicit Object Parameter + // We do that in all language modes to produce a better diagnostic. + SourceLocation ThisLoc; + if (getLangOpts().CPlusPlus && Tok.is(tok::kw_this)) + ThisLoc = ConsumeToken(); + ParseDeclarationSpecifiers(DS, /*TemplateInfo=*/ParsedTemplateInfo(), AS_none, DeclSpecContext::DSC_normal, /*LateAttrs=*/nullptr, AllowImplicitTypename); + DS.takeAttributesFrom(ArgDeclSpecAttrs); // Parse the declarator. This is "PrototypeContext" or @@ -7436,6 +7444,9 @@ void Parser::ParseParameterDeclarationClause( : DeclaratorContext::Prototype); ParseDeclarator(ParmDeclarator); + if (ThisLoc.isValid()) + ParmDeclarator.SetRangeBegin(ThisLoc); + // Parse GNU attributes, if present. MaybeParseGNUAttributes(ParmDeclarator); if (getLangOpts().HLSL) @@ -7505,7 +7516,8 @@ void Parser::ParseParameterDeclarationClause( } // Inform the actions module about the parameter declarator, so it gets // added to the current scope. - Decl *Param = Actions.ActOnParamDeclarator(getCurScope(), ParmDeclarator); + Decl *Param = + Actions.ActOnParamDeclarator(getCurScope(), ParmDeclarator, ThisLoc); // Parse the default argument, if any. We parse the default // arguments in all dialects; the semantic analysis in // ActOnParamDefaultArgument will reject the default argument in @@ -7691,7 +7703,7 @@ void Parser::ParseBracketDeclarator(Declarator &D) { // Parse the constant-expression or assignment-expression now (depending // on dialect). if (getLangOpts().CPlusPlus) { - NumElements = ParseConstantExpression(); + NumElements = ParseArrayBoundExpression(); } else { EnterExpressionEvaluationContext Unevaluated( Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated); diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index 711990bff2851e..9dbfc1c8c5e9ff 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -221,6 +221,15 @@ ExprResult Parser::ParseConstantExpression() { return ParseConstantExpressionInExprEvalContext(NotTypeCast); } +ExprResult Parser::ParseArrayBoundExpression() { + EnterExpressionEvaluationContext ConstantEvaluated( + Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated); + // If we parse the bound of a VLA... we parse a non-constant + // constant-expression! + Actions.ExprEvalContexts.back().InConditionallyConstantEvaluateContext = true; + return ParseConstantExpressionInExprEvalContext(NotTypeCast); +} + ExprResult Parser::ParseCaseExpression(SourceLocation CaseLoc) { EnterExpressionEvaluationContext ConstantEvaluated( Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated); diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp index 8a8a126bf7244d..995834a78c795f 100644 --- a/clang/lib/Parse/ParseOpenMP.cpp +++ b/clang/lib/Parse/ParseOpenMP.cpp @@ -3416,6 +3416,17 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, case OMPC_ompx_attribute: Clause = ParseOpenMPOMPXAttributesClause(WrongDirective); break; + case OMPC_ompx_bare: + if (WrongDirective) + Diag(Tok, diag::note_ompx_bare_clause) + << getOpenMPClauseName(CKind) << "target teams"; + if (!ErrorFound && !getLangOpts().OpenMPExtensions) { + Diag(Tok, diag::err_omp_unexpected_clause_extension_only) + << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind); + ErrorFound = true; + } + Clause = ParseOpenMPClause(CKind, WrongDirective); + break; default: break; } diff --git a/clang/lib/Parse/ParseTentative.cpp b/clang/lib/Parse/ParseTentative.cpp index 03c19bf5d96e38..8b653b1c4f8eaf 100644 --- a/clang/lib/Parse/ParseTentative.cpp +++ b/clang/lib/Parse/ParseTentative.cpp @@ -1571,6 +1571,17 @@ Parser::isCXXDeclarationSpecifier(ImplicitTypenameContext AllowImplicitTypename, case tok::kw___vector: return TPResult::True; + case tok::kw_this: { + // Try to parse a C++23 Explicit Object Parameter + // We do that in all language modes to produce a better diagnostic. + if (getLangOpts().CPlusPlus) { + RevertingTentativeParsingAction PA(*this); + ConsumeToken(); + return isCXXDeclarationSpecifier(AllowImplicitTypename, BracedCastResult, + InvalidAsDeclSpec); + } + return TPResult::False; + } case tok::annot_template_id: { TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok); // If lookup for the template-name found nothing, don't assume we have a diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp index 77bb560eb6288f..0947e8b0f526a3 100644 --- a/clang/lib/Sema/AnalysisBasedWarnings.cpp +++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp @@ -1983,6 +1983,12 @@ class ThreadSafetyReporter : public clang::threadSafety::ThreadSafetyHandler { case POK_PtPassByRef: DiagID = diag::warn_pt_guarded_pass_by_reference; break; + case POK_ReturnByRef: + DiagID = diag::warn_guarded_return_by_reference; + break; + case POK_PtReturnByRef: + DiagID = diag::warn_pt_guarded_return_by_reference; + break; } PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID) << Kind << D @@ -2013,6 +2019,12 @@ class ThreadSafetyReporter : public clang::threadSafety::ThreadSafetyHandler { case POK_PtPassByRef: DiagID = diag::warn_pt_guarded_pass_by_reference; break; + case POK_ReturnByRef: + DiagID = diag::warn_guarded_return_by_reference; + break; + case POK_PtReturnByRef: + DiagID = diag::warn_pt_guarded_return_by_reference; + break; } PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID) << Kind << D diff --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp index d59778b5b614b7..781f24cb71ae99 100644 --- a/clang/lib/Sema/DeclSpec.cpp +++ b/clang/lib/Sema/DeclSpec.cpp @@ -420,6 +420,18 @@ bool Declarator::isStaticMember() { getName().OperatorFunctionId.Operator)); } +bool Declarator::isExplicitObjectMemberFunction() { + if (!isFunctionDeclarator()) + return false; + DeclaratorChunk::FunctionTypeInfo &Fun = getFunctionTypeInfo(); + if (Fun.NumParams) { + auto *P = dyn_cast_or_null(Fun.Params[0].Param); + if (P && P->isExplicitObjectParameter()) + return true; + } + return false; +} + bool Declarator::isCtorOrDtor() { return (getName().getKind() == UnqualifiedIdKind::IK_ConstructorName) || (getName().getKind() == UnqualifiedIdKind::IK_DestructorName); @@ -1363,8 +1375,9 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) { StorageClassSpecLoc = SourceLocation(); } // Diagnose if we've recovered from an ill-formed 'auto' storage class - // specifier in a pre-C++11 dialect of C++. - if (!S.getLangOpts().CPlusPlus11 && TypeSpecType == TST_auto) + // specifier in a pre-C++11 dialect of C++ or in a pre-C23 dialect of C. + if (!S.getLangOpts().CPlusPlus11 && !S.getLangOpts().C23 && + TypeSpecType == TST_auto) S.Diag(TSTLoc, diag::ext_auto_type_specifier); if (S.getLangOpts().CPlusPlus && !S.getLangOpts().CPlusPlus11 && StorageClassSpec == SCS_auto) diff --git a/clang/lib/Sema/HLSLExternalSemaSource.cpp b/clang/lib/Sema/HLSLExternalSemaSource.cpp index af24d727c2bdbd..fd86a5f8b49c0a 100644 --- a/clang/lib/Sema/HLSLExternalSemaSource.cpp +++ b/clang/lib/Sema/HLSLExternalSemaSource.cpp @@ -175,8 +175,8 @@ struct BuiltinTypeDeclBuilder { SourceLocation(), FPOptionsOverride()); CXXThisExpr *This = CXXThisExpr::Create( - AST, SourceLocation(), - Constructor->getThisObjectType(), true); + AST, SourceLocation(), Constructor->getFunctionObjectParameterType(), + true); Expr *Handle = MemberExpr::CreateImplicit(AST, This, false, Fields["h"], Fields["h"]->getType(), VK_LValue, OK_Ordinary); @@ -260,9 +260,9 @@ struct BuiltinTypeDeclBuilder { auto FnProtoLoc = TSInfo->getTypeLoc().getAs(); FnProtoLoc.setParam(0, IdxParam); - auto *This = CXXThisExpr::Create( - AST, SourceLocation(), - MethodDecl->getThisObjectType(), true); + auto *This = + CXXThisExpr::Create(AST, SourceLocation(), + MethodDecl->getFunctionObjectParameterType(), true); auto *HandleAccess = MemberExpr::CreateImplicit( AST, This, false, Handle, Handle->getType(), VK_LValue, OK_Ordinary); diff --git a/clang/lib/Sema/ScopeInfo.cpp b/clang/lib/Sema/ScopeInfo.cpp index 92ce5137f4f311..ce90451f2613bf 100644 --- a/clang/lib/Sema/ScopeInfo.cpp +++ b/clang/lib/Sema/ScopeInfo.cpp @@ -248,6 +248,14 @@ void LambdaScopeInfo::visitPotentialCaptures( } } +bool LambdaScopeInfo::lambdaCaptureShouldBeConst() const { + if (ExplicitObjectParameter) + return ExplicitObjectParameter->getType() + .getNonReferenceType() + .isConstQualified(); + return !Mutable; +} + FunctionScopeInfo::~FunctionScopeInfo() { } BlockScopeInfo::~BlockScopeInfo() { } CapturedRegionScopeInfo::~CapturedRegionScopeInfo() { } diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index 4489cb0deae4c8..67533ccbdf347c 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -221,7 +221,6 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, CurScope(nullptr), Ident_super(nullptr) { assert(pp.TUKind == TUKind); TUScope = nullptr; - isConstantEvaluatedOverride = false; LoadedExternalKnownNamespaces = false; for (unsigned I = 0; I != NSAPI::NumNSNumberLiteralMethods; ++I) @@ -2072,7 +2071,7 @@ void Sema::checkTypeSupport(QualType Ty, SourceLocation Loc, ValueDecl *D) { targetDiag(D->getLocation(), diag::note_defined_here, FD) << D; } - if (Ty->isRVVType()) + if (TI.hasRISCVVTypes() && Ty->isRVVType()) checkRVVTypeSupport(Ty, Loc, D); // Don't allow SVE types in functions without a SVE target. diff --git a/clang/lib/Sema/SemaCUDA.cpp b/clang/lib/Sema/SemaCUDA.cpp index 88f5484575db17..7c4083e4ec4d4b 100644 --- a/clang/lib/Sema/SemaCUDA.cpp +++ b/clang/lib/Sema/SemaCUDA.cpp @@ -249,6 +249,15 @@ Sema::IdentifyCUDAPreference(const FunctionDecl *Caller, (CallerTarget == CFT_Global && CalleeTarget == CFT_Device)) return CFP_Native; + // HipStdPar mode is special, in that assessing whether a device side call to + // a host target is deferred to a subsequent pass, and cannot unambiguously be + // adjudicated in the AST, hence we optimistically allow them to pass here. + if (getLangOpts().HIPStdPar && + (CallerTarget == CFT_Global || CallerTarget == CFT_Device || + CallerTarget == CFT_HostDevice) && + CalleeTarget == CFT_Host) + return CFP_HostDevice; + // (d) HostDevice behavior depends on compilation mode. if (CallerTarget == CFT_HostDevice) { // It's OK to call a compilation-mode matching function from an HD one. @@ -803,7 +812,7 @@ bool Sema::CheckCUDACall(SourceLocation Loc, FunctionDecl *Callee) { assert(getLangOpts().CUDA && "Should only be called during CUDA compilation"); assert(Callee && "Callee may not be null."); - auto &ExprEvalCtx = ExprEvalContexts.back(); + const auto &ExprEvalCtx = currentEvaluationContext(); if (ExprEvalCtx.isUnevaluated() || ExprEvalCtx.isConstantEvaluated()) return true; @@ -895,7 +904,7 @@ void Sema::CUDACheckLambdaCapture(CXXMethodDecl *Callee, if (!ShouldCheck || !Capture.isReferenceCapture()) return; auto DiagKind = SemaDiagnosticBuilder::K_Deferred; - if (Capture.isVariableCapture()) { + if (Capture.isVariableCapture() && !getLangOpts().HIPStdPar) { SemaDiagnosticBuilder(DiagKind, Capture.getLocation(), diag::err_capture_bad_target, Callee, *this) << Capture.getVariable(); diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 6a3b5fa61d5945..446e35218bff0a 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -126,7 +126,7 @@ static bool checkArgCountAtLeast(Sema &S, CallExpr *Call, return S.Diag(Call->getEndLoc(), diag::err_typecheck_call_too_few_args) << 0 /*function call*/ << MinArgCount << ArgCount - << Call->getSourceRange(); + << /*is non object*/ 0 << Call->getSourceRange(); } /// Checks that a call expression's argument count is at most the desired @@ -139,7 +139,7 @@ static bool checkArgCountAtMost(Sema &S, CallExpr *Call, unsigned MaxArgCount) { return S.Diag(Call->getEndLoc(), diag::err_typecheck_call_too_many_args_at_most) << 0 /*function call*/ << MaxArgCount << ArgCount - << Call->getSourceRange(); + << /*is non object*/ 0 << Call->getSourceRange(); } /// Checks that a call expression's argument count is in the desired range. This @@ -168,7 +168,7 @@ static bool checkArgCount(Sema &S, CallExpr *Call, unsigned DesiredArgCount) { return S.Diag(Range.getBegin(), diag::err_typecheck_call_too_many_args) << 0 /*function call*/ << DesiredArgCount << ArgCount - << Call->getArg(1)->getSourceRange(); + << /*is non object*/ 0 << Call->getArg(1)->getSourceRange(); } static bool convertArgumentToType(Sema &S, Expr *&Value, QualType Ty) { @@ -217,7 +217,7 @@ static bool SemaBuiltinMSVCAnnotation(Sema &S, CallExpr *TheCall) { // We need at least one argument. if (TheCall->getNumArgs() < 1) { S.Diag(TheCall->getEndLoc(), diag::err_typecheck_call_too_few_args_at_least) - << 0 << 1 << TheCall->getNumArgs() + << 0 << 1 << TheCall->getNumArgs() << /*is non object*/ 0 << TheCall->getCallee()->getSourceRange(); return true; } @@ -1076,7 +1076,7 @@ static bool ProcessFormatStringLiteral(const Expr *FormatExpr, void Sema::checkFortifiedBuiltinMemoryFunction(FunctionDecl *FD, CallExpr *TheCall) { if (TheCall->isValueDependent() || TheCall->isTypeDependent() || - isConstantEvaluated()) + isConstantEvaluatedContext()) return; bool UseDABAttr = false; @@ -1578,7 +1578,7 @@ static bool SemaOpenCLBuiltinEnqueueKernel(Sema &S, CallExpr *TheCall) { if (NumArgs < 4) { S.Diag(TheCall->getBeginLoc(), diag::err_typecheck_call_too_few_args_at_least) - << 0 << 4 << NumArgs; + << 0 << 4 << NumArgs << /*is non object*/ 0; return true; } @@ -3192,7 +3192,7 @@ bool Sema::CheckCDEBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, bool Sema::CheckARMCoprocessorImmediate(const TargetInfo &TI, const Expr *CoprocArg, bool WantCDE) { - if (isConstantEvaluated()) + if (isConstantEvaluatedContext()) return false; // We can't check the value of a dependent argument. @@ -6276,10 +6276,6 @@ bool Sema::CheckX86BuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, case X86::BI__builtin_ia32_cmpss: case X86::BI__builtin_ia32_cmppd: case X86::BI__builtin_ia32_cmpsd: - i = 2; - l = 0; - u = TI.hasFeature("avx") ? 31 : 7; - break; case X86::BI__builtin_ia32_cmpps256: case X86::BI__builtin_ia32_cmppd256: case X86::BI__builtin_ia32_cmpps128_mask: @@ -6616,7 +6612,7 @@ static void CheckNonNullArguments(Sema &S, assert((FDecl || Proto) && "Need a function declaration or prototype"); // Already checked by constant evaluator. - if (S.isConstantEvaluated()) + if (S.isConstantEvaluatedContext()) return; // Check the attributes attached to the method/function itself. llvm::SmallBitVector NonNullArgs; @@ -6924,8 +6920,9 @@ void Sema::CheckConstructorCall(FunctionDecl *FDecl, QualType ThisType, Proto->isVariadic() ? VariadicConstructor : VariadicDoesNotApply; auto *Ctor = cast(FDecl); - CheckArgAlignment(Loc, FDecl, "'this'", Context.getPointerType(ThisType), - Context.getPointerType(Ctor->getThisObjectType())); + CheckArgAlignment( + Loc, FDecl, "'this'", Context.getPointerType(ThisType), + Context.getPointerType(Ctor->getFunctionObjectParameterType())); checkCall(FDecl, Proto, /*ThisArg=*/nullptr, Args, /*IsMemberFunction=*/true, Loc, SourceRange(), CallType); @@ -6945,14 +6942,16 @@ bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall, unsigned NumArgs = TheCall->getNumArgs(); Expr *ImplicitThis = nullptr; - if (IsMemberOperatorCall && !FDecl->isStatic()) { + if (IsMemberOperatorCall && !FDecl->isStatic() && + !FDecl->hasCXXExplicitFunctionObjectParameter()) { // If this is a call to a non-static member operator, hide the first // argument from checkCall. // FIXME: Our choice of AST representation here is less than ideal. ImplicitThis = Args[0]; ++Args; --NumArgs; - } else if (IsMemberFunction && !FDecl->isStatic()) + } else if (IsMemberFunction && !FDecl->isStatic() && + !FDecl->hasCXXExplicitFunctionObjectParameter()) ImplicitThis = cast(TheCall)->getImplicitObjectArgument(); @@ -6965,8 +6964,8 @@ bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall, ThisType = Context.getPointerType(ThisType); } - QualType ThisTypeFromDecl = - Context.getPointerType(cast(FDecl)->getThisObjectType()); + QualType ThisTypeFromDecl = Context.getPointerType( + cast(FDecl)->getFunctionObjectParameterType()); CheckArgAlignment(TheCall->getRParenLoc(), FDecl, "'this'", ThisType, ThisTypeFromDecl); @@ -7293,13 +7292,13 @@ ExprResult Sema::BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange, if (Args.size() < AdjustedNumArgs) { Diag(CallRange.getEnd(), diag::err_typecheck_call_too_few_args) << 0 << AdjustedNumArgs << static_cast(Args.size()) - << ExprRange; + << /*is non object*/ 0 << ExprRange; return ExprError(); } else if (Args.size() > AdjustedNumArgs) { Diag(Args[AdjustedNumArgs]->getBeginLoc(), diag::err_typecheck_call_too_many_args) << 0 << AdjustedNumArgs << static_cast(Args.size()) - << ExprRange; + << /*is non object*/ 0 << ExprRange; return ExprError(); } @@ -7662,7 +7661,8 @@ bool Sema::BuiltinWasmRefNullExtern(CallExpr *TheCall) { bool Sema::BuiltinWasmRefNullFunc(CallExpr *TheCall) { if (TheCall->getNumArgs() != 0) { Diag(TheCall->getBeginLoc(), diag::err_typecheck_call_too_many_args) - << 0 /*function call*/ << 0 << TheCall->getNumArgs(); + << 0 /*function call*/ << /*expected*/ 0 << TheCall->getNumArgs() + << /*is non object*/ 0; return true; } @@ -7695,7 +7695,8 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) { // Ensure that we have at least one argument to do type inference from. if (TheCall->getNumArgs() < 1) { Diag(TheCall->getEndLoc(), diag::err_typecheck_call_too_few_args_at_least) - << 0 << 1 << TheCall->getNumArgs() << Callee->getSourceRange(); + << 0 << 1 << TheCall->getNumArgs() << /*is non object*/ 0 + << Callee->getSourceRange(); return ExprError(); } @@ -7971,7 +7972,7 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) { // have at least that many. if (TheCall->getNumArgs() < 1+NumFixed) { Diag(TheCall->getEndLoc(), diag::err_typecheck_call_too_few_args_at_least) - << 0 << 1 + NumFixed << TheCall->getNumArgs() + << 0 << 1 + NumFixed << TheCall->getNumArgs() << /*is non object*/ 0 << Callee->getSourceRange(); return ExprError(); } @@ -8361,7 +8362,8 @@ bool Sema::SemaBuiltinVAStartARMMicrosoft(CallExpr *Call) { if (Call->getNumArgs() < 3) return Diag(Call->getEndLoc(), diag::err_typecheck_call_too_few_args_at_least) - << 0 /*function call*/ << 3 << Call->getNumArgs(); + << 0 /*function call*/ << 3 << Call->getNumArgs() + << /*is non object*/ 0; // Type-check the first argument normally. if (checkBuiltinArgument(*this, Call, 0)) @@ -8622,7 +8624,7 @@ ExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) { return ExprError(Diag(TheCall->getEndLoc(), diag::err_typecheck_call_too_few_args_at_least) << 0 /*function call*/ << 2 << TheCall->getNumArgs() - << TheCall->getSourceRange()); + << /*is non object*/ 0 << TheCall->getSourceRange()); // Determine which of the following types of shufflevector we're checking: // 1) unary, vector mask: (lhs, mask) @@ -8742,7 +8744,8 @@ bool Sema::SemaBuiltinPrefetch(CallExpr *TheCall) { if (NumArgs > 3) return Diag(TheCall->getEndLoc(), diag::err_typecheck_call_too_many_args_at_most) - << 0 /*function call*/ << 3 << NumArgs << TheCall->getSourceRange(); + << 0 /*function call*/ << 3 << NumArgs << /*is non object*/ 0 + << TheCall->getSourceRange(); // Argument 0 is checked for us and the remaining arguments must be // constant integers. @@ -8881,13 +8884,13 @@ bool Sema::SemaBuiltinOSLogFormat(CallExpr *TheCall) { if (NumArgs < NumRequiredArgs) { return Diag(TheCall->getEndLoc(), diag::err_typecheck_call_too_few_args) << 0 /* function call */ << NumRequiredArgs << NumArgs - << TheCall->getSourceRange(); + << /*is non object*/ 0 << TheCall->getSourceRange(); } if (NumArgs >= NumRequiredArgs + 0x100) { return Diag(TheCall->getEndLoc(), diag::err_typecheck_call_too_many_args_at_most) << 0 /* function call */ << (NumRequiredArgs + 0xff) << NumArgs - << TheCall->getSourceRange(); + << /*is non object*/ 0 << TheCall->getSourceRange(); } unsigned i = 0; @@ -8973,7 +8976,7 @@ bool Sema::SemaBuiltinConstantArg(CallExpr *TheCall, int ArgNum, /// TheCall is a constant expression in the range [Low, High]. bool Sema::SemaBuiltinConstantArgRange(CallExpr *TheCall, int ArgNum, int Low, int High, bool RangeIsError) { - if (isConstantEvaluated()) + if (isConstantEvaluatedContext()) return false; llvm::APSInt Result; @@ -9687,7 +9690,7 @@ checkFormatStringExpr(Sema &S, const Expr *E, ArrayRef Args, llvm::SmallBitVector &CheckedVarArgs, UncoveredArgHandler &UncoveredArg, llvm::APSInt Offset, bool IgnoreStringsWithoutSpecifiers = false) { - if (S.isConstantEvaluated()) + if (S.isConstantEvaluatedContext()) return SLCT_NotALiteral; tryAgain: assert(Offset.isSigned() && "invalid offset"); @@ -9727,8 +9730,8 @@ checkFormatStringExpr(Sema &S, const Expr *E, ArrayRef Args, bool CheckLeft = true, CheckRight = true; bool Cond; - if (C->getCond()->EvaluateAsBooleanCondition(Cond, S.getASTContext(), - S.isConstantEvaluated())) { + if (C->getCond()->EvaluateAsBooleanCondition( + Cond, S.getASTContext(), S.isConstantEvaluatedContext())) { if (Cond) CheckRight = false; else @@ -9992,9 +9995,11 @@ checkFormatStringExpr(Sema &S, const Expr *E, ArrayRef Args, Expr::EvalResult LResult, RResult; bool LIsInt = BinOp->getLHS()->EvaluateAsInt( - LResult, S.Context, Expr::SE_NoSideEffects, S.isConstantEvaluated()); + LResult, S.Context, Expr::SE_NoSideEffects, + S.isConstantEvaluatedContext()); bool RIsInt = BinOp->getRHS()->EvaluateAsInt( - RResult, S.Context, Expr::SE_NoSideEffects, S.isConstantEvaluated()); + RResult, S.Context, Expr::SE_NoSideEffects, + S.isConstantEvaluatedContext()); if (LIsInt != RIsInt) { BinaryOperatorKind BinOpKind = BinOp->getOpcode(); @@ -10022,7 +10027,7 @@ checkFormatStringExpr(Sema &S, const Expr *E, ArrayRef Args, Expr::EvalResult IndexResult; if (ASE->getRHS()->EvaluateAsInt(IndexResult, S.Context, Expr::SE_NoSideEffects, - S.isConstantEvaluated())) { + S.isConstantEvaluatedContext())) { sumOffsets(Offset, IndexResult.Val.getInt(), BO_Add, /*RHS is int*/ true); E = ASE->getBase(); @@ -11349,12 +11354,15 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS, ImplicitMatch == ArgType::NoMatchTypeConfusion) Match = ImplicitMatch; assert(Match != ArgType::MatchPromotion); + // Look through unscoped enums to their underlying type. bool IsEnum = false; bool IsScopedEnum = false; + QualType IntendedTy = ExprTy; if (auto EnumTy = ExprTy->getAs()) { + IntendedTy = EnumTy->getDecl()->getIntegerType(); if (EnumTy->isUnscopedEnumerationType()) { - ExprTy = EnumTy->getDecl()->getIntegerType(); + ExprTy = IntendedTy; // This controls whether we're talking about the underlying type or not, // which we only want to do when it's an unscoped enum. IsEnum = true; @@ -11366,7 +11374,6 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS, // %C in an Objective-C context prints a unichar, not a wchar_t. // If the argument is an integer of some kind, believe the %C and suggest // a cast instead of changing the conversion specifier. - QualType IntendedTy = ExprTy; if (isObjCContext() && FS.getConversionSpecifier().getKind() == ConversionSpecifier::CArg) { if (ExprTy->isIntegralOrUnscopedEnumerationType() && @@ -11402,8 +11409,10 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS, std::tie(CastTy, CastTyName) = shouldNotPrintDirectly(S.Context, IntendedTy, E); if (!CastTy.isNull()) { // %zi/%zu and %td/%tu are OK to use for NSInteger/NSUInteger of type int - // (long in ASTContext). Only complain to pedants. - if ((CastTyName == "NSInteger" || CastTyName == "NSUInteger") && + // (long in ASTContext). Only complain to pedants or when they're the + // underlying type of a scoped enum (which always needs a cast). + if (!IsScopedEnum && + (CastTyName == "NSInteger" || CastTyName == "NSUInteger") && (AT.isSizeT() || AT.isPtrdiffT()) && AT.matchesType(S.Context, CastTy)) Match = ArgType::NoMatchPedantic; @@ -11458,20 +11467,15 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS, // should be printed as 'long' for 64-bit compatibility.) // Rather than emitting a normal format/argument mismatch, we want to // add a cast to the recommended type (and correct the format string - // if necessary). + // if necessary). We should also do so for scoped enumerations. SmallString<16> CastBuf; llvm::raw_svector_ostream CastFix(CastBuf); CastFix << (S.LangOpts.CPlusPlus ? "static_cast<" : "("); - if (IsScopedEnum) { - CastFix << AT.getRepresentativeType(S.Context).getAsString( - S.Context.getPrintingPolicy()); - } else { - IntendedTy.print(CastFix, S.Context.getPrintingPolicy()); - } + IntendedTy.print(CastFix, S.Context.getPrintingPolicy()); CastFix << (S.LangOpts.CPlusPlus ? ">" : ")"); SmallVector Hints; - if ((!AT.matchesType(S.Context, IntendedTy) && !IsScopedEnum) || + if (AT.matchesType(S.Context, IntendedTy) != ArgType::Match || ShouldNotPrintDirectly) Hints.push_back(FixItHint::CreateReplacement(SpecRange, os.str())); @@ -11499,7 +11503,7 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS, Hints.push_back(FixItHint::CreateInsertion(After, ")")); } - if (ShouldNotPrintDirectly) { + if (ShouldNotPrintDirectly && !IsScopedEnum) { // The expression has a type that should not be printed directly. // We extract the name from the typedef because we don't want to show // the underlying type in the diagnostic. @@ -13953,7 +13957,7 @@ static bool CheckTautologicalComparison(Sema &S, BinaryOperator *E, return false; IntRange OtherValueRange = GetExprRange( - S.Context, Other, S.isConstantEvaluated(), /*Approximate*/ false); + S.Context, Other, S.isConstantEvaluatedContext(), /*Approximate=*/false); QualType OtherT = Other->getType(); if (const auto *AT = OtherT->getAs()) @@ -14168,8 +14172,9 @@ static void AnalyzeComparison(Sema &S, BinaryOperator *E) { } // Otherwise, calculate the effective range of the signed operand. - IntRange signedRange = GetExprRange( - S.Context, signedOperand, S.isConstantEvaluated(), /*Approximate*/ true); + IntRange signedRange = + GetExprRange(S.Context, signedOperand, S.isConstantEvaluatedContext(), + /*Approximate=*/true); // Go ahead and analyze implicit conversions in the operands. Note // that we skip the implicit conversions on both sides. @@ -14187,8 +14192,8 @@ static void AnalyzeComparison(Sema &S, BinaryOperator *E) { if (E->isEqualityOp()) { unsigned comparisonWidth = S.Context.getIntWidth(T); IntRange unsignedRange = - GetExprRange(S.Context, unsignedOperand, S.isConstantEvaluated(), - /*Approximate*/ true); + GetExprRange(S.Context, unsignedOperand, S.isConstantEvaluatedContext(), + /*Approximate=*/true); // We should never be unable to prove that the unsigned operand is // non-negative. @@ -15051,7 +15056,7 @@ static void CheckImplicitConversion(Sema &S, Expr *E, QualType T, if (Target->isUnsaturatedFixedPointType()) { Expr::EvalResult Result; if (E->EvaluateAsFixedPoint(Result, S.Context, Expr::SE_AllowSideEffects, - S.isConstantEvaluated())) { + S.isConstantEvaluatedContext())) { llvm::APFixedPoint Value = Result.Val.getFixedPoint(); llvm::APFixedPoint MaxVal = S.Context.getFixedPointMax(T); llvm::APFixedPoint MinVal = S.Context.getFixedPointMin(T); @@ -15066,7 +15071,7 @@ static void CheckImplicitConversion(Sema &S, Expr *E, QualType T, } } else if (Target->isIntegerType()) { Expr::EvalResult Result; - if (!S.isConstantEvaluated() && + if (!S.isConstantEvaluatedContext() && E->EvaluateAsFixedPoint(Result, S.Context, Expr::SE_AllowSideEffects)) { llvm::APFixedPoint FXResult = Result.Val.getFixedPoint(); @@ -15089,7 +15094,7 @@ static void CheckImplicitConversion(Sema &S, Expr *E, QualType T, } else if (Target->isUnsaturatedFixedPointType()) { if (Source->isIntegerType()) { Expr::EvalResult Result; - if (!S.isConstantEvaluated() && + if (!S.isConstantEvaluatedContext() && E->EvaluateAsInt(Result, S.Context, Expr::SE_AllowSideEffects)) { llvm::APSInt Value = Result.Val.getInt(); @@ -15115,8 +15120,9 @@ static void CheckImplicitConversion(Sema &S, Expr *E, QualType T, if (SourceBT && TargetBT && SourceBT->isIntegerType() && TargetBT->isFloatingType() && !IsListInit) { // Determine the number of precision bits in the source integer type. - IntRange SourceRange = GetExprRange(S.Context, E, S.isConstantEvaluated(), - /*Approximate*/ true); + IntRange SourceRange = + GetExprRange(S.Context, E, S.isConstantEvaluatedContext(), + /*Approximate=*/true); unsigned int SourcePrecision = SourceRange.Width; // Determine the number of precision bits in the @@ -15184,8 +15190,8 @@ static void CheckImplicitConversion(Sema &S, Expr *E, QualType T, IntRange SourceTypeRange = IntRange::forTargetOfCanonicalType(S.Context, Source); - IntRange LikelySourceRange = - GetExprRange(S.Context, E, S.isConstantEvaluated(), /*Approximate*/ true); + IntRange LikelySourceRange = GetExprRange( + S.Context, E, S.isConstantEvaluatedContext(), /*Approximate=*/true); IntRange TargetRange = IntRange::forTargetOfCanonicalType(S.Context, Target); if (LikelySourceRange.Width > TargetRange.Width) { @@ -15193,7 +15199,7 @@ static void CheckImplicitConversion(Sema &S, Expr *E, QualType T, // TODO: this should happen for bitfield stores, too. Expr::EvalResult Result; if (E->EvaluateAsInt(Result, S.Context, Expr::SE_AllowSideEffects, - S.isConstantEvaluated())) { + S.isConstantEvaluatedContext())) { llvm::APSInt Value(32); Value = Result.Val.getInt(); @@ -16057,7 +16063,8 @@ class SequenceChecker : public ConstEvaluatedExprVisitor { if (!EvalOK || E->isValueDependent()) return false; EvalOK = E->EvaluateAsBooleanCondition( - Result, Self.SemaRef.Context, Self.SemaRef.isConstantEvaluated()); + Result, Self.SemaRef.Context, + Self.SemaRef.isConstantEvaluatedContext()); return EvalOK; } @@ -17184,7 +17191,7 @@ void Sema::CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr, const ArraySubscriptExpr *ASE, bool AllowOnePastEnd, bool IndexNegated) { // Already diagnosed by the constant evaluator. - if (isConstantEvaluated()) + if (isConstantEvaluatedContext()) return; IndexExpr = IndexExpr->IgnoreParenImpCasts(); @@ -18573,7 +18580,7 @@ void Sema::CheckArgumentWithTypeTag(const ArgumentWithTypeTagAttr *Attr, TypeTagData TypeInfo; if (!GetMatchingCType(ArgumentKind, TypeTagExpr, Context, TypeTagForDatatypeMagicValues.get(), FoundWrongKind, - TypeInfo, isConstantEvaluated())) { + TypeInfo, isConstantEvaluatedContext())) { if (FoundWrongKind) Diag(TypeTagExpr->getExprLoc(), diag::warn_type_tag_for_datatype_wrong_kind) diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp index 036548b68247bf..0ef03293b46ffb 100644 --- a/clang/lib/Sema/SemaConcept.cpp +++ b/clang/lib/Sema/SemaConcept.cpp @@ -702,8 +702,7 @@ bool Sema::CheckFunctionConstraints(const FunctionDecl *FD, } ContextRAII SavedContext{*this, CtxToSave}; - LocalInstantiationScope Scope(*this, !ForOverloadResolution || - isLambdaCallOperator(FD)); + LocalInstantiationScope Scope(*this, !ForOverloadResolution); std::optional MLTAL = SetupConstraintCheckingTemplateArgumentsAndScope( const_cast(FD), {}, Scope); @@ -720,7 +719,8 @@ bool Sema::CheckFunctionConstraints(const FunctionDecl *FD, CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr); LambdaScopeForCallOperatorInstantiationRAII LambdaScope( - *this, const_cast(FD), *MLTAL, Scope); + *this, const_cast(FD), *MLTAL, Scope, + ForOverloadResolution); return CheckConstraintSatisfaction( FD, {FD->getTrailingRequiresClause()}, *MLTAL, diff --git a/clang/lib/Sema/SemaCoroutine.cpp b/clang/lib/Sema/SemaCoroutine.cpp index cfbe176d8300c2..d2b0922a4bb9c4 100644 --- a/clang/lib/Sema/SemaCoroutine.cpp +++ b/clang/lib/Sema/SemaCoroutine.cpp @@ -70,7 +70,7 @@ static QualType lookupPromiseType(Sema &S, const FunctionDecl *FD, // If the function is a non-static member function, add the type // of the implicit object parameter before the formal parameters. if (auto *MD = dyn_cast(FD)) { - if (MD->isInstance()) { + if (MD->isImplicitObjectMemberFunction()) { // [over.match.funcs]4 // For non-static member functions, the type of the implicit object // parameter is @@ -78,7 +78,7 @@ static QualType lookupPromiseType(Sema &S, const FunctionDecl *FD, // ref-qualifier or with the & ref-qualifier // -- "rvalue reference to cv X" for functions declared with the && // ref-qualifier - QualType T = MD->getThisObjectType(); + QualType T = MD->getFunctionObjectParameterType(); T = FnType->getRefQualifier() == RQ_RValue ? S.Context.getRValueReferenceType(T) : S.Context.getLValueReferenceType(T, /*SpelledAsLValue*/ true); @@ -564,10 +564,10 @@ VarDecl *Sema::buildCoroutinePromise(SourceLocation Loc) { assert(isa(CurContext) && "not in a function scope"); auto *FD = cast(CurContext); bool IsThisDependentType = [&] { - if (auto *MD = dyn_cast_or_null(FD)) - return MD->isInstance() && MD->getThisObjectType()->isDependentType(); - else - return false; + if (const auto *MD = dyn_cast_if_present(FD)) + return MD->isImplicitObjectMemberFunction() && + MD->getThisType()->isDependentType(); + return false; }(); QualType T = FD->getType()->isDependentType() || IsThisDependentType @@ -592,7 +592,7 @@ VarDecl *Sema::buildCoroutinePromise(SourceLocation Loc) { // Add implicit object parameter. if (auto *MD = dyn_cast(FD)) { - if (MD->isInstance() && !isLambdaCallOperator(MD)) { + if (MD->isImplicitObjectMemberFunction() && !isLambdaCallOperator(MD)) { ExprResult ThisExpr = ActOnCXXThis(Loc); if (ThisExpr.isInvalid()) return nullptr; @@ -1367,7 +1367,7 @@ bool CoroutineStmtBuilder::makeReturnOnAllocFailure() { static bool collectPlacementArgs(Sema &S, FunctionDecl &FD, SourceLocation Loc, SmallVectorImpl &PlacementArgs) { if (auto *MD = dyn_cast(&FD)) { - if (MD->isInstance() && !isLambdaCallOperator(MD)) { + if (MD->isImplicitObjectMemberFunction() && !isLambdaCallOperator(MD)) { ExprResult ThisExpr = S.ActOnCXXThis(Loc); if (ThisExpr.isInvalid()) return false; diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 9c2f1e83ed3fbe..324a3674732aa0 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -8924,13 +8924,11 @@ bool Sema::AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) { CXXMethodDecl *BaseMD = dyn_cast(BaseND->getCanonicalDecl()); if (!BaseMD || !BaseMD->isVirtual() || - IsOverload(MD, BaseMD, /*UseMemberUsingDeclRules=*/false, - /*ConsiderCudaAttrs=*/true, - // C++2a [class.virtual]p2 does not consider requires - // clauses when overriding. - /*ConsiderRequiresClauses=*/false)) + IsOverride(MD, BaseMD, /*UseMemberUsingDeclRules=*/false, + /*ConsiderCudaAttrs=*/true)) + continue; + if (!CheckExplicitObjectOverride(MD, BaseMD)) continue; - if (Overridden.insert(BaseMD).second) { MD->addOverriddenMethod(BaseMD); CheckOverridingFunctionReturnType(MD, BaseMD); @@ -9265,6 +9263,8 @@ static FunctionDecl *CreateNewFunctionDecl(Sema &SemaRef, Declarator &D, } Expr *TrailingRequiresClause = D.getTrailingRequiresClause(); + SemaRef.CheckExplicitObjectMemberFunction(DC, D, Name, R); + if (Name.getNameKind() == DeclarationName::CXXConstructorName) { // This is a C++ constructor declaration. assert(DC->isRecord() && @@ -9766,8 +9766,9 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, << DeclSpec::getSpecifierName(TSCS); if (D.isFirstDeclarationOfMember()) - adjustMemberFunctionCC(R, D.isStaticMember(), D.isCtorOrDtor(), - D.getIdentifierLoc()); + adjustMemberFunctionCC( + R, !(D.isStaticMember() || D.isExplicitObjectMemberFunction()), + D.isCtorOrDtor(), D.getIdentifierLoc()); bool isFriend = false; FunctionTemplateDecl *FunctionTemplate = nullptr; @@ -11971,7 +11972,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, // struct B { struct Y { ~Y(); }; using X = Y; }; // template struct A; if (NewFD->getFriendObjectKind() == Decl::FriendObjectKind::FOK_None || - !Destructor->getThisObjectType()->isDependentType()) { + !Destructor->getFunctionObjectParameterType()->isDependentType()) { CXXRecordDecl *Record = Destructor->getParent(); QualType ClassType = Context.getTypeDeclType(Record); @@ -12862,6 +12863,15 @@ QualType Sema::deduceVarTypeFromInitializer(VarDecl *VDecl, DeducedType *Deduced = Type->getContainedDeducedType(); assert(Deduced && "deduceVarTypeFromInitializer for non-deduced type"); + // Diagnose auto array declarations in C23, unless it's a supported extension. + if (getLangOpts().C23 && Type->isArrayType() && + !isa_and_present(Init)) { + Diag(Range.getBegin(), diag::err_auto_not_allowed) + << (int)Deduced->getContainedAutoType()->getKeyword() + << /*in array decl*/ 23 << Range; + return QualType(); + } + // C++11 [dcl.spec.auto]p3 if (!Init) { assert(VDecl && "no init for init capture deduction?"); @@ -14918,9 +14928,32 @@ void Sema::CheckFunctionOrTemplateParamDeclarator(Scope *S, Declarator &D) { } } +static void CheckExplicitObjectParameter(Sema &S, ParmVarDecl *P, + SourceLocation ExplicitThisLoc) { + if (!ExplicitThisLoc.isValid()) + return; + assert(S.getLangOpts().CPlusPlus && + "explicit parameter in non-cplusplus mode"); + if (!S.getLangOpts().CPlusPlus23) + S.Diag(ExplicitThisLoc, diag::err_cxx20_deducing_this) + << P->getSourceRange(); + + // C++2b [dcl.fct/7] An explicit object parameter shall not be a function + // parameter pack. + if (P->isParameterPack()) { + S.Diag(P->getBeginLoc(), diag::err_explicit_object_parameter_pack) + << P->getSourceRange(); + return; + } + P->setExplicitObjectParameterLoc(ExplicitThisLoc); + if (LambdaScopeInfo *LSI = S.getCurLambda()) + LSI->ExplicitObjectParameter = P; +} + /// ActOnParamDeclarator - Called from Parser::ParseFunctionDeclarator() /// to introduce parameters into function prototype scope. -Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) { +Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D, + SourceLocation ExplicitThisLoc) { const DeclSpec &DS = D.getDeclSpec(); // Verify C99 6.7.5.3p2: The only SCS allowed is 'register'. @@ -14998,6 +15031,8 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) { if (D.isInvalidType()) New->setInvalidDecl(); + CheckExplicitObjectParameter(*this, New, ExplicitThisLoc); + assert(S->isFunctionPrototypeScope()); assert(S->getFunctionPrototypeDepth() >= 1); New->setScopeInfo(S->getFunctionPrototypeDepth() - 1, @@ -15395,6 +15430,8 @@ LambdaScopeInfo *Sema::RebuildLambdaScopeInfo(CXXMethodDecl *CallOperator) { LSI->IntroducerRange = DNI.getCXXOperatorNameRange(); LSI->Mutable = !CallOperator->isConst(); + if (CallOperator->isExplicitObjectMemberFunction()) + LSI->ExplicitObjectParameter = CallOperator->getParamDecl(0); // Add the captures to the LSI so they can be noted as already // captured within tryCaptureVar. @@ -18048,6 +18085,18 @@ void Sema::ActOnTagFinishDefinition(Scope *S, Decl *TagD, [](const FieldDecl *FD) { return FD->isBitField(); })) Diag(BraceRange.getBegin(), diag::warn_pragma_align_not_xl_compatible); } + + // Check the "counted_by" attribute to ensure that the count field exists in + // the struct. + if (const auto *RD = dyn_cast(Tag)) { + auto Pred = [](const Decl *D) { + if (const auto *FD = dyn_cast(D)) + return FD->hasAttr(); + return false; + }; + if (const FieldDecl *FD = RD->findFieldIf(Pred)) + CheckCountedByAttr(S, FD); + } } void Sema::ActOnObjCContainerFinishDefinition() { @@ -18121,7 +18170,8 @@ ExprResult Sema::VerifyBitField(SourceLocation FieldLoc, // Zero-width bitfield is ok for anonymous field. if (Value == 0 && FieldName) - return Diag(FieldLoc, diag::err_bitfield_has_zero_width) << FieldName; + return Diag(FieldLoc, diag::err_bitfield_has_zero_width) + << FieldName << BitWidth->getSourceRange(); if (Value.isSigned() && Value.isNegative()) { if (FieldName) @@ -18175,8 +18225,8 @@ ExprResult Sema::VerifyBitField(SourceLocation FieldLoc, /// to create a FieldDecl object for it. Decl *Sema::ActOnField(Scope *S, Decl *TagD, SourceLocation DeclStart, Declarator &D, Expr *BitfieldWidth) { - FieldDecl *Res = HandleField(S, cast_or_null(TagD), - DeclStart, D, static_cast(BitfieldWidth), + FieldDecl *Res = HandleField(S, cast_if_present(TagD), DeclStart, + D, BitfieldWidth, /*InitStyle=*/ICIS_NoInit, AS_public); return Res; } @@ -18622,6 +18672,9 @@ Decl *Sema::ActOnIvar(Scope *S, SourceLocation DeclStart, Declarator &D, ObjCIvarDecl *NewID = ObjCIvarDecl::Create( Context, EnclosingContext, DeclStart, Loc, II, T, TInfo, ac, BitWidth); + if (T->containsErrors()) + NewID->setInvalidDecl(); + if (II) { NamedDecl *PrevDecl = LookupSingleName(S, II, Loc, LookupMemberName, ForVisibleRedeclaration); @@ -18781,10 +18834,13 @@ static bool AreSpecialMemberFunctionsSameKind(ASTContext &Context, if (CSM == Sema::CXXDefaultConstructor) return bool(M1->getDescribedFunctionTemplate()) == bool(M2->getDescribedFunctionTemplate()); - if (!Context.hasSameType(M1->getParamDecl(0)->getType(), - M2->getParamDecl(0)->getType())) + // FIXME: better resolve CWG + // https://cplusplus.github.io/CWG/issues/2787.html + if (!Context.hasSameType(M1->getNonObjectParameter(0)->getType(), + M2->getNonObjectParameter(0)->getType())) return false; - if (!Context.hasSameType(M1->getThisType(), M2->getThisType())) + if (!Context.hasSameType(M1->getFunctionObjectParameterReferenceType(), + M2->getFunctionObjectParameterReferenceType())) return false; return true; diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 2d7e69946a39e4..47e072ace072b4 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -1234,7 +1234,7 @@ static void handleConsumableAttr(Sema &S, Decl *D, const ParsedAttr &AL) { static bool checkForConsumableClass(Sema &S, const CXXMethodDecl *MD, const ParsedAttr &AL) { - QualType ThisType = MD->getThisObjectType(); + QualType ThisType = MD->getFunctionObjectParameterType(); if (const CXXRecordDecl *RD = ThisType->getAsCXXRecordDecl()) { if (!RD->hasAttr()) { @@ -1336,23 +1336,23 @@ static void handleReturnTypestateAttr(Sema &S, Decl *D, const ParsedAttr &AL) { // FIXME: This check is currently being done in the analysis. It can be // enabled here only after the parser propagates attributes at // template specialization definition, not declaration. - //QualType ReturnType; + // QualType ReturnType; // - //if (const ParmVarDecl *Param = dyn_cast(D)) { + // if (const ParmVarDecl *Param = dyn_cast(D)) { // ReturnType = Param->getType(); // //} else if (const CXXConstructorDecl *Constructor = // dyn_cast(D)) { - // ReturnType = Constructor->getThisObjectType(); + // ReturnType = Constructor->getFunctionObjectParameterType(); // //} else { // // ReturnType = cast(D)->getCallResultType(); //} // - //const CXXRecordDecl *RD = ReturnType->getAsCXXRecordDecl(); + // const CXXRecordDecl *RD = ReturnType->getAsCXXRecordDecl(); // - //if (!RD || !RD->hasAttr()) { + // if (!RD || !RD->hasAttr()) { // S.Diag(Attr.getLoc(), diag::warn_return_state_for_unconsumable_type) << // ReturnType.getAsString(); // return; @@ -8361,6 +8361,134 @@ 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); +} + +namespace { + +// Callback to only accept typo corrections that are for field members of +// the given struct or union. +class FieldDeclValidatorCCC final : public CorrectionCandidateCallback { +public: + explicit FieldDeclValidatorCCC(const RecordDecl *RD) : Record(RD) {} + + bool ValidateCandidate(const TypoCorrection &candidate) override { + FieldDecl *FD = candidate.getCorrectionDeclAs(); + return FD && FD->getDeclContext()->getRedeclContext()->Equals(Record); + } + + std::unique_ptr clone() override { + return std::make_unique(*this); + } + +private: + const RecordDecl *Record; +}; + +} // end anonymous namespace + +bool Sema::CheckCountedByAttr(Scope *S, const FieldDecl *FD) { + const RecordDecl *RD = FD->getParent(); + const auto *CBA = FD->getAttr(); + const IdentifierInfo *FieldName = CBA->getCountedByField(); + + auto Pred = [&](const Decl *D) { + if (const auto *Field = dyn_cast(D)) + return Field->getName() == FieldName->getName(); + return false; + }; + const FieldDecl *Field = RD->findFieldIf(Pred); + + if (!Field) { + // The "counted_by" field needs to exist within the struct. + DeclarationNameInfo NameInfo(FieldName, + CBA->getCountedByFieldLoc().getBegin()); + LookupResult Result(*this, NameInfo, Sema::LookupOrdinaryName); + + LookupName(Result, S); + if (Result.getResultKind() == LookupResult::Found) { + SourceRange SR = CBA->getCountedByFieldLoc(); + Diag(SR.getBegin(), + diag::err_flexible_array_counted_by_attr_field_not_found_in_struct) + << CBA->getCountedByField() << SR; + + SR = Result.getAsSingle()->getSourceRange(); + Diag(SR.getBegin(), diag::note_var_declared_here) + << Result.getAsSingle() << SR; + } else { + SourceRange SR = CBA->getCountedByFieldLoc(); + FieldDeclValidatorCCC CCC(RD); + + if (TypoCorrection Corrected = + CorrectTypo(NameInfo, Sema::LookupMemberName, /*Scope=*/nullptr, + /*SS=*/nullptr, CCC, Sema::CTK_ErrorRecovery, + const_cast(RD))) { + diagnoseTypo( + Corrected, + PDiag( + diag:: + err_flexible_array_counted_by_attr_field_not_found_suggest) + << FieldName); + } else { + Diag(SR.getBegin(), + diag::err_flexible_array_counted_by_attr_field_not_found) + << CBA->getCountedByField() << SR; + } + } + + return true; + } + + LangOptions::StrictFlexArraysLevelKind StrictFlexArraysLevel = + Context.getLangOpts().getStrictFlexArraysLevel(); + + 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; + } + + if (Field->hasAttr()) { + // The "counted_by" field can't point to the flexible array member. + SourceRange SR = CBA->getCountedByFieldLoc(); + Diag(SR.getBegin(), + diag::err_flexible_array_counted_by_attr_refers_to_self) + << CBA->getCountedByField() << SR; + return true; + } + + if (!Field->getType()->isIntegerType() || + Field->getType()->isBooleanType()) { + // The "counted_by" field must have an integer type. + SourceRange SR = Field->getLocation(); + Diag(SR.getBegin(), + diag::err_flexible_array_counted_by_attr_field_not_integer) + << Field << SR; + + SR = CBA->getCountedByFieldLoc(); + Diag(SR.getBegin(), diag::note_flexible_array_counted_by_attr_field) + << CBA->getCountedByField() << SR; + return true; + } + + return false; +} + static void handleFunctionReturnThunksAttr(Sema &S, Decl *D, const ParsedAttr &AL) { StringRef KindStr; @@ -9314,6 +9442,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/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 302e944d5d74f1..f9c010b1a00248 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -49,6 +49,7 @@ #include "llvm/ADT/ScopeExit.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/Support/ConvertUTF.h" #include "llvm/Support/SaveAndRestore.h" #include #include @@ -7692,7 +7693,7 @@ bool Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD, unsigned ExpectedParams = 1; if (CSM == CXXDefaultConstructor || CSM == CXXDestructor) ExpectedParams = 0; - if (MD->getNumParams() != ExpectedParams) { + if (MD->getNumExplicitParams() != ExpectedParams) { // This checks for default arguments: a copy or move constructor with a // default argument is classified as a default constructor, and assignment // operations and destructors can't have default arguments. @@ -7721,10 +7722,12 @@ bool Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD, if (CSM == CXXCopyAssignment || CSM == CXXMoveAssignment) { // Check for return type matching. ReturnType = Type->getReturnType(); + QualType ThisType = MD->getFunctionObjectParameterType(); QualType DeclType = Context.getTypeDeclType(RD); DeclType = Context.getElaboratedType(ETK_None, nullptr, DeclType, nullptr); - DeclType = Context.getAddrSpaceQualType(DeclType, MD->getMethodQualifiers().getAddressSpace()); + DeclType = Context.getAddrSpaceQualType( + DeclType, ThisType.getQualifiers().getAddressSpace()); QualType ExpectedReturnType = Context.getLValueReferenceType(DeclType); if (!Context.hasSameType(ReturnType, ExpectedReturnType)) { @@ -7734,7 +7737,7 @@ bool Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD, } // A defaulted special member cannot have cv-qualifiers. - if (Type->getMethodQuals().hasConst() || Type->getMethodQuals().hasVolatile()) { + if (ThisType.isConstQualified() || ThisType.isVolatileQualified()) { if (DeleteOnTypeMismatch) ShouldDeleteForTypeMismatch = true; else { @@ -7746,7 +7749,10 @@ bool Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD, } // Check for parameter type matching. - QualType ArgType = ExpectedParams ? Type->getParamType(0) : QualType(); + QualType ArgType = + ExpectedParams + ? Type->getParamType(MD->isExplicitObjectMemberFunction() ? 1 : 0) + : QualType(); bool HasConstParam = false; if (ExpectedParams && ArgType->isReferenceType()) { // Argument must be reference to possibly-const T. @@ -7814,10 +7820,17 @@ bool Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD, : isa(MD))) && MD->isConstexpr() && !Constexpr && MD->getTemplatedKind() == FunctionDecl::TK_NonTemplate) { - Diag(MD->getBeginLoc(), MD->isConsteval() - ? diag::err_incorrect_defaulted_consteval - : diag::err_incorrect_defaulted_constexpr) - << CSM; + if (!MD->isConsteval() && RD->getNumVBases()) { + Diag(MD->getBeginLoc(), diag::err_incorrect_defaulted_constexpr_with_vb) + << CSM; + for (const auto &I : RD->vbases()) + Diag(I.getBeginLoc(), diag::note_constexpr_virtual_base_here); + } else { + Diag(MD->getBeginLoc(), MD->isConsteval() + ? diag::err_incorrect_defaulted_consteval + : diag::err_incorrect_defaulted_constexpr) + << CSM; + } // FIXME: Explain why the special member can't be constexpr. HadError = true; } @@ -7840,8 +7853,8 @@ bool Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD, FunctionProtoType::ExtProtoInfo EPI = Type->getExtProtoInfo(); EPI.ExceptionSpec.Type = EST_Unevaluated; EPI.ExceptionSpec.SourceDecl = MD; - MD->setType(Context.getFunctionType( - ReturnType, llvm::ArrayRef(&ArgType, ExpectedParams), EPI)); + MD->setType( + Context.getFunctionType(ReturnType, Type->getParamTypes(), EPI)); } } @@ -8492,7 +8505,8 @@ class DefaultedComparisonSynthesizer ExprPair getCompleteObject() { unsigned Param = 0; ExprResult LHS; - if (isa(FD)) { + if (const auto *MD = dyn_cast(FD); + MD && MD->isImplicitObjectMemberFunction()) { // LHS is '*this'. LHS = S.ActOnCXXThis(Loc); if (!LHS.isInvalid()) @@ -8798,15 +8812,22 @@ bool Sema::CheckExplicitlyDefaultedComparison(Scope *S, FunctionDecl *FD, // If we're out-of-class, this is the class we're comparing. if (!RD) RD = MD->getParent(); - - if (!MD->isConst()) { - SourceLocation InsertLoc; - if (FunctionTypeLoc Loc = MD->getFunctionTypeLoc()) - InsertLoc = getLocForEndOfToken(Loc.getRParenLoc()); + QualType T = MD->getFunctionObjectParameterType(); + if (!T.isConstQualified()) { + SourceLocation Loc, InsertLoc; + if (MD->isExplicitObjectMemberFunction()) { + Loc = MD->getParamDecl(0)->getBeginLoc(); + InsertLoc = getLocForEndOfToken( + MD->getParamDecl(0)->getExplicitObjectParamThisLoc()); + } else { + Loc = MD->getLocation(); + if (FunctionTypeLoc Loc = MD->getFunctionTypeLoc()) + InsertLoc = Loc.getRParenLoc(); + } // Don't diagnose an implicit 'operator=='; we will have diagnosed the // corresponding defaulted 'operator<=>' already. if (!MD->isImplicit()) { - Diag(MD->getLocation(), diag::err_defaulted_comparison_non_const) + Diag(Loc, diag::err_defaulted_comparison_non_const) << (int)DCK << FixItHint::CreateInsertion(InsertLoc, " const"); } @@ -8830,7 +8851,9 @@ bool Sema::CheckExplicitlyDefaultedComparison(Scope *S, FunctionDecl *FD, } } - if (FD->getNumParams() != (IsMethod ? 1 : 2)) { + if ((FD->getNumParams() - + (unsigned)FD->hasCXXExplicitFunctionObjectParameter()) != + (IsMethod ? 1 : 2)) { // Let's not worry about using a variadic template pack here -- who would do // such a thing? Diag(FD->getLocation(), diag::err_defaulted_comparison_num_args) @@ -8840,6 +8863,8 @@ bool Sema::CheckExplicitlyDefaultedComparison(Scope *S, FunctionDecl *FD, const ParmVarDecl *KnownParm = nullptr; for (const ParmVarDecl *Param : FD->parameters()) { + if (Param->isExplicitObjectParameter()) + continue; QualType ParmTy = Param->getType(); if (!KnownParm) { @@ -9223,9 +9248,9 @@ struct SpecialMemberVisitor { llvm_unreachable("invalid special member kind"); } - if (MD->getNumParams()) { + if (MD->getNumExplicitParams()) { if (const ReferenceType *RT = - MD->getParamDecl(0)->getType()->getAs()) + MD->getNonObjectParameter(0)->getType()->getAs()) ConstArg = RT->getPointeeType().isConstQualified(); } } @@ -10105,7 +10130,7 @@ bool Sema::SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMember CSM, case CXXCopyConstructor: case CXXCopyAssignment: { - const ParmVarDecl *Param0 = MD->getParamDecl(0); + const ParmVarDecl *Param0 = MD->getNonObjectParameter(0); const ReferenceType *RT = Param0->getType()->getAs(); // When ClangABICompat14 is true, CXX copy constructors will only be trivial @@ -10136,7 +10161,7 @@ bool Sema::SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMember CSM, case CXXMoveConstructor: case CXXMoveAssignment: { // Trivial move operations always have non-cv-qualified parameters. - const ParmVarDecl *Param0 = MD->getParamDecl(0); + const ParmVarDecl *Param0 = MD->getNonObjectParameter(0); const RValueReferenceType *RT = Param0->getType()->getAs(); if (!RT || RT->getPointeeType().getCVRQualifiers()) { @@ -11102,15 +11127,25 @@ void Sema::CheckConversionDeclarator(Declarator &D, QualType &R, << SourceRange(D.getIdentifierLoc()) << 0; D.setInvalidType(); } - const auto *Proto = R->castAs(); - // Make sure we don't have any parameters. - if (Proto->getNumParams() > 0) { - Diag(D.getIdentifierLoc(), diag::err_conv_function_with_params); + DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo(); + unsigned NumParam = Proto->getNumParams(); + + // [C++2b] + // A conversion function shall have no non-object parameters. + if (NumParam == 1) { + DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo(); + if (const auto *First = + dyn_cast_if_present(FTI.Params[0].Param); + First && First->isExplicitObjectParameter()) + NumParam--; + } + if (NumParam != 0) { + Diag(D.getIdentifierLoc(), diag::err_conv_function_with_params); // Delete the parameters. - D.getFunctionTypeInfo().freeParams(); + FTI.freeParams(); D.setInvalidType(); } else if (Proto->isVariadic()) { Diag(D.getIdentifierLoc(), diag::err_conv_function_variadic); @@ -11268,6 +11303,87 @@ Decl *Sema::ActOnConversionDeclarator(CXXConversionDecl *Conversion) { return Conversion; } +void Sema::CheckExplicitObjectMemberFunction(DeclContext *DC, Declarator &D, + DeclarationName Name, QualType R) { + CheckExplicitObjectMemberFunction(D, Name, R, false, DC); +} + +void Sema::CheckExplicitObjectLambda(Declarator &D) { + CheckExplicitObjectMemberFunction(D, {}, {}, true); +} + +void Sema::CheckExplicitObjectMemberFunction(Declarator &D, + DeclarationName Name, QualType R, + bool IsLambda, DeclContext *DC) { + if (!D.isFunctionDeclarator()) + return; + + DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo(); + if (FTI.NumParams == 0) + return; + ParmVarDecl *ExplicitObjectParam = nullptr; + for (unsigned Idx = 0; Idx < FTI.NumParams; Idx++) { + const auto &ParamInfo = FTI.Params[Idx]; + if (!ParamInfo.Param) + continue; + ParmVarDecl *Param = cast(ParamInfo.Param); + if (!Param->isExplicitObjectParameter()) + continue; + if (Idx == 0) { + ExplicitObjectParam = Param; + continue; + } else { + Diag(Param->getLocation(), + diag::err_explicit_object_parameter_must_be_first) + << IsLambda << Param->getSourceRange(); + } + } + if (!ExplicitObjectParam) + return; + + if (ExplicitObjectParam->hasDefaultArg()) { + Diag(ExplicitObjectParam->getLocation(), + diag::err_explicit_object_default_arg) + << ExplicitObjectParam->getSourceRange(); + } + + if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static) { + Diag(ExplicitObjectParam->getBeginLoc(), + diag::err_explicit_object_parameter_nonmember) + << D.getSourceRange() << /*static=*/0 << IsLambda; + } + + if (D.getDeclSpec().isVirtualSpecified()) { + Diag(ExplicitObjectParam->getBeginLoc(), + diag::err_explicit_object_parameter_nonmember) + << D.getSourceRange() << /*virtual=*/1 << IsLambda; + } + + if (IsLambda && FTI.hasMutableQualifier()) { + Diag(ExplicitObjectParam->getBeginLoc(), + diag::err_explicit_object_parameter_mutable) + << D.getSourceRange(); + } + + if (IsLambda) + return; + + if (!DC || !DC->isRecord()) { + Diag(ExplicitObjectParam->getLocation(), + diag::err_explicit_object_parameter_nonmember) + << D.getSourceRange() << /*non-member=*/2 << IsLambda; + return; + } + + // CWG2674: constructors and destructors cannot have explicit parameters. + if (Name.getNameKind() == DeclarationName::CXXConstructorName || + Name.getNameKind() == DeclarationName::CXXDestructorName) + Diag(ExplicitObjectParam->getBeginLoc(), + diag::err_explicit_object_parameter_constructor) + << (Name.getNameKind() == DeclarationName::CXXDestructorName) + << D.getSourceRange(); +} + namespace { /// Utility class to accumulate and print a diagnostic listing the invalid /// specifier(s) on a declaration. @@ -14862,12 +14978,11 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, SmallVector Statements; // The parameter for the "other" object, which we are copying from. - ParmVarDecl *Other = CopyAssignOperator->getParamDecl(0); + ParmVarDecl *Other = CopyAssignOperator->getNonObjectParameter(0); Qualifiers OtherQuals = Other->getType().getQualifiers(); QualType OtherRefType = Other->getType(); - if (const LValueReferenceType *OtherRef - = OtherRefType->getAs()) { - OtherRefType = OtherRef->getPointeeType(); + if (OtherRefType->isLValueReferenceType()) { + OtherRefType = OtherRefType->getPointeeType(); OtherQuals = OtherRefType.getQualifiers(); } @@ -14879,8 +14994,26 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, // Builds a DeclRefExpr for the "other" object. RefBuilder OtherRef(Other, OtherRefType); - // Builds the "this" pointer. - ThisBuilder This; + // Builds the function object parameter. + std::optional This; + std::optional DerefThis; + std::optional ExplicitObject; + bool IsArrow = false; + QualType ObjectType; + if (CopyAssignOperator->isExplicitObjectMemberFunction()) { + ObjectType = CopyAssignOperator->getParamDecl(0)->getType(); + if (ObjectType->isReferenceType()) + ObjectType = ObjectType->getPointeeType(); + ExplicitObject.emplace(CopyAssignOperator->getParamDecl(0), ObjectType); + } else { + ObjectType = getCurrentThisType(); + This.emplace(); + DerefThis.emplace(*This); + IsArrow = !LangOpts.HLSL; + } + ExprBuilder &ObjectParameter = + ExplicitObject ? static_cast(*ExplicitObject) + : static_cast(*This); // Assign base classes. bool Invalid = false; @@ -14902,11 +15035,11 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, VK_LValue, BasePath); // Dereference "this". - DerefBuilder DerefThis(This); - CastBuilder To(DerefThis, - Context.getQualifiedType( - BaseType, CopyAssignOperator->getMethodQualifiers()), - VK_LValue, BasePath); + CastBuilder To( + ExplicitObject ? static_cast(*ExplicitObject) + : static_cast(*DerefThis), + Context.getQualifiedType(BaseType, ObjectType.getQualifiers()), + VK_LValue, BasePath); // Build the copy. StmtResult Copy = buildSingleCopyAssign(*this, Loc, BaseType, @@ -14972,10 +15105,7 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, MemberLookup.resolveKind(); MemberBuilder From(OtherRef, OtherRefType, /*IsArrow=*/false, MemberLookup); - - MemberBuilder To(This, getCurrentThisType(), /*IsArrow=*/!LangOpts.HLSL, - MemberLookup); - + MemberBuilder To(ObjectParameter, ObjectType, IsArrow, MemberLookup); // Build the copy of this field. StmtResult Copy = buildSingleCopyAssign(*this, Loc, FieldType, To, From, @@ -14992,15 +15122,11 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, if (!Invalid) { // Add a "return *this;" - Expr *ThisExpr = nullptr; - if (!LangOpts.HLSL) { - ExprResult ThisObj = - CreateBuiltinUnaryOp(Loc, UO_Deref, This.build(*this, Loc)); - ThisExpr = ThisObj.get(); - } else { - ThisExpr = This.build(*this, Loc); - } - + Expr *ThisExpr = + (ExplicitObject ? static_cast(*ExplicitObject) + : LangOpts.HLSL ? static_cast(*This) + : static_cast(*DerefThis)) + .build(*this, Loc); StmtResult Return = BuildReturnStmt(Loc, ThisExpr); if (Return.isInvalid()) Invalid = true; @@ -15231,7 +15357,7 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation, SmallVector Statements; // The parameter for the "other" object, which we are move from. - ParmVarDecl *Other = MoveAssignOperator->getParamDecl(0); + ParmVarDecl *Other = MoveAssignOperator->getNonObjectParameter(0); QualType OtherRefType = Other->getType()->castAs()->getPointeeType(); @@ -15245,8 +15371,23 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation, // Cast to rvalue. MoveCastBuilder MoveOther(OtherRef); - // Builds the "this" pointer. - ThisBuilder This; + // Builds the function object parameter. + std::optional This; + std::optional DerefThis; + std::optional ExplicitObject; + QualType ObjectType; + if (MoveAssignOperator->isExplicitObjectMemberFunction()) { + ObjectType = MoveAssignOperator->getParamDecl(0)->getType(); + if (ObjectType->isReferenceType()) + ObjectType = ObjectType->getPointeeType(); + ExplicitObject.emplace(MoveAssignOperator->getParamDecl(0), ObjectType); + } else { + ObjectType = getCurrentThisType(); + This.emplace(); + DerefThis.emplace(*This); + } + ExprBuilder &ObjectParameter = + ExplicitObject ? *ExplicitObject : static_cast(*This); // Assign base classes. bool Invalid = false; @@ -15274,14 +15415,13 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation, // appropriately-qualified base type. CastBuilder From(OtherRef, BaseType, VK_XValue, BasePath); - // Dereference "this". - DerefBuilder DerefThis(This); - // Implicitly cast "this" to the appropriately-qualified base type. - CastBuilder To(DerefThis, - Context.getQualifiedType( - BaseType, MoveAssignOperator->getMethodQualifiers()), - VK_LValue, BasePath); + // Dereference "this". + CastBuilder To( + ExplicitObject ? static_cast(*ExplicitObject) + : static_cast(*DerefThis), + Context.getQualifiedType(BaseType, ObjectType.getQualifiers()), + VK_LValue, BasePath); // Build the move. StmtResult Move = buildSingleCopyAssign(*this, Loc, BaseType, @@ -15346,8 +15486,8 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation, MemberLookup.resolveKind(); MemberBuilder From(MoveOther, OtherRefType, /*IsArrow=*/false, MemberLookup); - MemberBuilder To(This, getCurrentThisType(), - /*IsArrow=*/true, MemberLookup); + MemberBuilder To(ObjectParameter, ObjectType, /*IsArrow=*/!ExplicitObject, + MemberLookup); assert(!From.build(*this, Loc)->isLValue() && // could be xvalue or prvalue "Member reference with rvalue base must be rvalue except for reference " @@ -15369,10 +15509,12 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation, if (!Invalid) { // Add a "return *this;" - ExprResult ThisObj = - CreateBuiltinUnaryOp(Loc, UO_Deref, This.build(*this, Loc)); + Expr *ThisExpr = + (ExplicitObject ? static_cast(*ExplicitObject) + : static_cast(*DerefThis)) + .build(*this, Loc); - StmtResult Return = BuildReturnStmt(Loc, ThisObj.get()); + StmtResult Return = BuildReturnStmt(Loc, ThisExpr); if (Return.isInvalid()) Invalid = true; else @@ -15691,7 +15833,9 @@ void Sema::DefineImplicitLambdaToFunctionPointerConversion( CXXRecordDecl *Lambda = Conv->getParent(); FunctionDecl *CallOp = Lambda->getLambdaCallOperator(); FunctionDecl *Invoker = - CallOp->isStatic() ? CallOp : Lambda->getLambdaStaticInvoker(CC); + CallOp->hasCXXExplicitFunctionObjectParameter() || CallOp->isStatic() + ? CallOp + : Lambda->getLambdaStaticInvoker(CC); if (auto *TemplateArgs = Conv->getTemplateSpecializationArgs()) { CallOp = InstantiateFunctionDeclaration( @@ -16297,8 +16441,11 @@ bool Sema::CheckOverloadedOperatorDeclaration(FunctionDecl *FnDecl) { // [...] Operator functions cannot have more or fewer parameters // than the number required for the corresponding operator, as // described in the rest of this subclause. - unsigned NumParams = FnDecl->getNumParams() - + (isa(FnDecl)? 1 : 0); + unsigned NumParams = FnDecl->getNumParams() + + (isa(FnDecl) && + !FnDecl->hasCXXExplicitFunctionObjectParameter() + ? 1 + : 0); if (Op != OO_Call && Op != OO_Subscript && ((NumParams == 1 && !CanBeUnaryOperator) || (NumParams == 2 && !CanBeBinaryOperator) || (NumParams < 1) || @@ -16880,10 +17027,74 @@ Decl *Sema::ActOnStaticAssertDeclaration(SourceLocation StaticAssertLoc, AssertMessageExpr, RParenLoc, false); } +static void WriteCharTypePrefix(BuiltinType::Kind BTK, llvm::raw_ostream &OS) { + switch (BTK) { + case BuiltinType::Char_S: + case BuiltinType::Char_U: + break; + case BuiltinType::Char8: + OS << "u8"; + break; + case BuiltinType::Char16: + OS << 'u'; + break; + case BuiltinType::Char32: + OS << 'U'; + break; + case BuiltinType::WChar_S: + case BuiltinType::WChar_U: + OS << 'L'; + break; + default: + llvm_unreachable("Non-character type"); + } +} + +/// Convert character's value, interpreted as a code unit, to a string. +/// The value needs to be zero-extended to 32-bits. +/// FIXME: This assumes Unicode literal encodings +static void WriteCharValueForDiagnostic(uint32_t Value, const BuiltinType *BTy, + unsigned TyWidth, + SmallVectorImpl &Str) { + char Arr[UNI_MAX_UTF8_BYTES_PER_CODE_POINT]; + char *Ptr = Arr; + BuiltinType::Kind K = BTy->getKind(); + llvm::raw_svector_ostream OS(Str); + + // This should catch Char_S, Char_U, Char8, and use of escaped characters in + // other types. + if (K == BuiltinType::Char_S || K == BuiltinType::Char_U || + K == BuiltinType::Char8 || Value <= 0x7F) { + StringRef Escaped = escapeCStyle(Value); + if (!Escaped.empty()) + EscapeStringForDiagnostic(Escaped, Str); + else + OS << static_cast(Value); + return; + } + + switch (K) { + case BuiltinType::Char16: + case BuiltinType::Char32: + case BuiltinType::WChar_S: + case BuiltinType::WChar_U: { + if (llvm::ConvertCodePointToUTF8(Value, Ptr)) + EscapeStringForDiagnostic(StringRef(Arr, Ptr - Arr), Str); + else + OS << "\\x" + << llvm::format_hex_no_prefix(Value, TyWidth / 4, /*Upper=*/true); + break; + } + default: + llvm_unreachable("Non-character type is passed"); + } +} + /// Convert \V to a string we can present to the user in a diagnostic /// \T is the type of the expression that has been evaluated into \V static bool ConvertAPValueToString(const APValue &V, QualType T, - SmallVectorImpl &Str) { + SmallVectorImpl &Str, + ASTContext &Context) { if (!V.hasValue()) return false; @@ -16898,13 +17109,38 @@ static bool ConvertAPValueToString(const APValue &V, QualType T, "Bool type, but value is not 0 or 1"); llvm::raw_svector_ostream OS(Str); OS << (BoolValue ? "true" : "false"); - } else if (T->isCharType()) { + } else { + llvm::raw_svector_ostream OS(Str); // Same is true for chars. - Str.push_back('\''); - Str.push_back(V.getInt().getExtValue()); - Str.push_back('\''); - } else + // We want to print the character representation for textual types + const auto *BTy = T->getAs(); + if (BTy) { + switch (BTy->getKind()) { + case BuiltinType::Char_S: + case BuiltinType::Char_U: + case BuiltinType::Char8: + case BuiltinType::Char16: + case BuiltinType::Char32: + case BuiltinType::WChar_S: + case BuiltinType::WChar_U: { + unsigned TyWidth = Context.getIntWidth(T); + assert(8 <= TyWidth && TyWidth <= 32 && "Unexpected integer width"); + uint32_t CodeUnit = static_cast(V.getInt().getZExtValue()); + WriteCharTypePrefix(BTy->getKind(), OS); + OS << '\''; + WriteCharValueForDiagnostic(CodeUnit, BTy, TyWidth, Str); + OS << "' (0x" + << llvm::format_hex_no_prefix(CodeUnit, /*Width=*/2, + /*Upper=*/true) + << ", " << V.getInt() << ')'; + return true; + } + default: + break; + } + } V.getInt().toString(Str); + } break; @@ -17001,8 +17237,9 @@ void Sema::DiagnoseStaticAssertDetails(const Expr *E) { Side->EvaluateAsRValue(DiagSide[I].Result, Context, true); - DiagSide[I].Print = ConvertAPValueToString( - DiagSide[I].Result.Val, Side->getType(), DiagSide[I].ValueString); + DiagSide[I].Print = + ConvertAPValueToString(DiagSide[I].Result.Val, Side->getType(), + DiagSide[I].ValueString, Context); } if (DiagSide[0].Print && DiagSide[1].Print) { Diag(Op->getExprLoc(), diag::note_expr_evaluates_to) @@ -18106,6 +18343,20 @@ bool Sema::CheckOverridingFunctionAttributes(const CXXMethodDecl *New, return true; } +bool Sema::CheckExplicitObjectOverride(CXXMethodDecl *New, + const CXXMethodDecl *Old) { + // CWG2553 + // A virtual function shall not be an explicit object member function. + if (!New->isExplicitObjectMemberFunction()) + return true; + Diag(New->getParamDecl(0)->getBeginLoc(), + diag::err_explicit_object_parameter_nonmember) + << New->getSourceRange() << /*virtual*/ 1 << /*IsLambda*/ false; + Diag(Old->getLocation(), diag::note_overridden_virtual_function); + New->setInvalidDecl(); + return false; +} + bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New, const CXXMethodDecl *Old) { QualType NewTy = New->getType()->castAs()->getReturnType(); diff --git a/clang/lib/Sema/SemaExceptionSpec.cpp b/clang/lib/Sema/SemaExceptionSpec.cpp index 72304e51ea8ef3..75730ea888afb4 100644 --- a/clang/lib/Sema/SemaExceptionSpec.cpp +++ b/clang/lib/Sema/SemaExceptionSpec.cpp @@ -769,14 +769,12 @@ bool Sema::handlerCanCatch(QualType HandlerType, QualType ExceptionType) { /// CheckExceptionSpecSubset - Check whether the second function type's /// exception specification is a subset (or equivalent) of the first function /// type. This is used by override and pointer assignment checks. -bool Sema::CheckExceptionSpecSubset(const PartialDiagnostic &DiagID, - const PartialDiagnostic &NestedDiagID, - const PartialDiagnostic &NoteID, - const PartialDiagnostic &NoThrowDiagID, - const FunctionProtoType *Superset, - SourceLocation SuperLoc, - const FunctionProtoType *Subset, - SourceLocation SubLoc) { +bool Sema::CheckExceptionSpecSubset( + const PartialDiagnostic &DiagID, const PartialDiagnostic &NestedDiagID, + const PartialDiagnostic &NoteID, const PartialDiagnostic &NoThrowDiagID, + const FunctionProtoType *Superset, bool SkipSupersetFirstParameter, + SourceLocation SuperLoc, const FunctionProtoType *Subset, + bool SkipSubsetFirstParameter, SourceLocation SubLoc) { // Just auto-succeed under -fno-exceptions. if (!getLangOpts().CXXExceptions) @@ -816,8 +814,9 @@ bool Sema::CheckExceptionSpecSubset(const PartialDiagnostic &DiagID, // done. if ((SuperCanThrow == CT_Can && SuperEST != EST_Dynamic) || SubCanThrow == CT_Cannot) - return CheckParamExceptionSpec(NestedDiagID, NoteID, Superset, SuperLoc, - Subset, SubLoc); + return CheckParamExceptionSpec(NestedDiagID, NoteID, Superset, + SkipSupersetFirstParameter, SuperLoc, Subset, + SkipSubsetFirstParameter, SubLoc); // Allow __declspec(nothrow) to be missing on redeclaration as an extension in // some cases. @@ -869,8 +868,9 @@ bool Sema::CheckExceptionSpecSubset(const PartialDiagnostic &DiagID, } } // We've run half the gauntlet. - return CheckParamExceptionSpec(NestedDiagID, NoteID, Superset, SuperLoc, - Subset, SubLoc); + return CheckParamExceptionSpec(NestedDiagID, NoteID, Superset, + SkipSupersetFirstParameter, SuperLoc, Subset, + SkipSupersetFirstParameter, SubLoc); } static bool @@ -894,12 +894,11 @@ CheckSpecForTypesEquivalent(Sema &S, const PartialDiagnostic &DiagID, /// assignment and override compatibility check. We do not check the parameters /// of parameter function pointers recursively, as no sane programmer would /// even be able to write such a function type. -bool Sema::CheckParamExceptionSpec(const PartialDiagnostic &DiagID, - const PartialDiagnostic &NoteID, - const FunctionProtoType *Target, - SourceLocation TargetLoc, - const FunctionProtoType *Source, - SourceLocation SourceLoc) { +bool Sema::CheckParamExceptionSpec( + const PartialDiagnostic &DiagID, const PartialDiagnostic &NoteID, + const FunctionProtoType *Target, bool SkipTargetFirstParameter, + SourceLocation TargetLoc, const FunctionProtoType *Source, + bool SkipSourceFirstParameter, SourceLocation SourceLoc) { auto RetDiag = DiagID; RetDiag << 0; if (CheckSpecForTypesEquivalent( @@ -910,14 +909,16 @@ bool Sema::CheckParamExceptionSpec(const PartialDiagnostic &DiagID, // We shouldn't even be testing this unless the arguments are otherwise // compatible. - assert(Target->getNumParams() == Source->getNumParams() && + assert((Target->getNumParams() - (unsigned)SkipTargetFirstParameter) == + (Source->getNumParams() - (unsigned)SkipSourceFirstParameter) && "Functions have different argument counts."); for (unsigned i = 0, E = Target->getNumParams(); i != E; ++i) { auto ParamDiag = DiagID; ParamDiag << 1; if (CheckSpecForTypesEquivalent( *this, ParamDiag, PDiag(), - Target->getParamType(i), TargetLoc, Source->getParamType(i), + Target->getParamType(i + (SkipTargetFirstParameter ? 1 : 0)), + TargetLoc, Source->getParamType(SkipSourceFirstParameter ? 1 : 0), SourceLoc)) return true; } @@ -958,9 +959,10 @@ bool Sema::CheckExceptionSpecCompatibility(Expr *From, QualType ToType) { // void (*q)(void (*) throw(int)) = p; // } // ... because it might be instantiated with T=int. - return CheckExceptionSpecSubset( - PDiag(DiagID), PDiag(NestedDiagID), PDiag(), PDiag(), ToFunc, - From->getSourceRange().getBegin(), FromFunc, SourceLocation()) && + return CheckExceptionSpecSubset(PDiag(DiagID), PDiag(NestedDiagID), PDiag(), + PDiag(), ToFunc, 0, + From->getSourceRange().getBegin(), FromFunc, + 0, SourceLocation()) && !getLangOpts().CPlusPlus17; } @@ -989,14 +991,14 @@ bool Sema::CheckOverridingFunctionExceptionSpec(const CXXMethodDecl *New, unsigned DiagID = diag::err_override_exception_spec; if (getLangOpts().MSVCCompat) DiagID = diag::ext_override_exception_spec; - return CheckExceptionSpecSubset(PDiag(DiagID), - PDiag(diag::err_deep_exception_specs_differ), - PDiag(diag::note_overridden_virtual_function), - PDiag(diag::ext_override_exception_spec), - Old->getType()->castAs(), - Old->getLocation(), - New->getType()->castAs(), - New->getLocation()); + return CheckExceptionSpecSubset( + PDiag(DiagID), PDiag(diag::err_deep_exception_specs_differ), + PDiag(diag::note_overridden_virtual_function), + PDiag(diag::ext_override_exception_spec), + Old->getType()->castAs(), + Old->hasCXXExplicitFunctionObjectParameter(), Old->getLocation(), + New->getType()->castAs(), + New->hasCXXExplicitFunctionObjectParameter(), New->getLocation()); } static CanThrowResult canSubStmtsThrow(Sema &Self, const Stmt *S) { diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 92496b03ecabe5..9c5f96eebd0416 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -2444,7 +2444,7 @@ bool Sema::DiagnoseDependentMemberLookup(const LookupResult &R) { // FIXME: Is this special case necessary? We could allow the caller to // diagnose this. if (isDefaultArgument && ((*R.begin())->isCXXInstanceMember())) { - Diag(R.getNameLoc(), diag::err_member_call_without_object); + Diag(R.getNameLoc(), diag::err_member_call_without_object) << 0; return true; } @@ -3217,11 +3217,11 @@ Sema::PerformObjectMemberConversion(Expr *From, FromRecordType = FromType; } } else if (const auto *Method = dyn_cast(Member)) { - if (Method->isStatic()) + if (!Method->isImplicitObjectMemberFunction()) return From; DestType = Method->getThisType().getNonReferenceType(); - DestRecordType = Method->getThisObjectType(); + DestRecordType = Method->getFunctionObjectParameterType(); if (FromType->getAs()) { FromRecordType = FromType->getPointeeType(); @@ -6503,6 +6503,9 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn, // C99 6.5.2.2p7 - the arguments are implicitly converted, as if by // assignment, to the types of the corresponding parameter, ... + bool HasExplicitObjectParameter = + FDecl && FDecl->hasCXXExplicitFunctionObjectParameter(); + unsigned ExplicitObjectParameterOffset = HasExplicitObjectParameter ? 1 : 0; unsigned NumParams = Proto->getNumParams(); bool Invalid = false; unsigned MinArgs = FDecl ? FDecl->getMinRequiredArguments() : NumParams; @@ -6521,21 +6524,29 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn, MinArgs == NumParams && !Proto->isVariadic() ? diag::err_typecheck_call_too_few_args_suggest : diag::err_typecheck_call_too_few_args_at_least_suggest; - diagnoseTypo(TC, PDiag(diag_id) << FnKind << MinArgs - << static_cast(Args.size()) - << TC.getCorrectionRange()); - } else if (MinArgs == 1 && FDecl && FDecl->getParamDecl(0)->getDeclName()) + diagnoseTypo( + TC, PDiag(diag_id) + << FnKind << MinArgs - ExplicitObjectParameterOffset + << static_cast(Args.size()) - + ExplicitObjectParameterOffset + << HasExplicitObjectParameter << TC.getCorrectionRange()); + } else if (MinArgs - ExplicitObjectParameterOffset == 1 && FDecl && + FDecl->getParamDecl(ExplicitObjectParameterOffset) + ->getDeclName()) Diag(RParenLoc, MinArgs == NumParams && !Proto->isVariadic() ? diag::err_typecheck_call_too_few_args_one : diag::err_typecheck_call_too_few_args_at_least_one) - << FnKind << FDecl->getParamDecl(0) << Fn->getSourceRange(); + << FnKind << FDecl->getParamDecl(ExplicitObjectParameterOffset) + << HasExplicitObjectParameter << Fn->getSourceRange(); else Diag(RParenLoc, MinArgs == NumParams && !Proto->isVariadic() ? diag::err_typecheck_call_too_few_args : diag::err_typecheck_call_too_few_args_at_least) - << FnKind << MinArgs << static_cast(Args.size()) - << Fn->getSourceRange(); + << FnKind << MinArgs - ExplicitObjectParameterOffset + << static_cast(Args.size()) - + ExplicitObjectParameterOffset + << HasExplicitObjectParameter << Fn->getSourceRange(); // Emit the location of the prototype. if (!TC && FDecl && !FDecl->getBuiltinID() && !IsExecConfig) @@ -6560,17 +6571,23 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn, MinArgs == NumParams && !Proto->isVariadic() ? diag::err_typecheck_call_too_many_args_suggest : diag::err_typecheck_call_too_many_args_at_most_suggest; - diagnoseTypo(TC, PDiag(diag_id) << FnKind << NumParams - << static_cast(Args.size()) - << TC.getCorrectionRange()); - } else if (NumParams == 1 && FDecl && - FDecl->getParamDecl(0)->getDeclName()) + diagnoseTypo( + TC, PDiag(diag_id) + << FnKind << NumParams - ExplicitObjectParameterOffset + << static_cast(Args.size()) - + ExplicitObjectParameterOffset + << HasExplicitObjectParameter << TC.getCorrectionRange()); + } else if (NumParams - ExplicitObjectParameterOffset == 1 && FDecl && + FDecl->getParamDecl(ExplicitObjectParameterOffset) + ->getDeclName()) Diag(Args[NumParams]->getBeginLoc(), MinArgs == NumParams ? diag::err_typecheck_call_too_many_args_one : diag::err_typecheck_call_too_many_args_at_most_one) - << FnKind << FDecl->getParamDecl(0) - << static_cast(Args.size()) << Fn->getSourceRange() + << FnKind << FDecl->getParamDecl(ExplicitObjectParameterOffset) + << static_cast(Args.size()) - + ExplicitObjectParameterOffset + << HasExplicitObjectParameter << Fn->getSourceRange() << SourceRange(Args[NumParams]->getBeginLoc(), Args.back()->getEndLoc()); else @@ -6578,8 +6595,10 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn, MinArgs == NumParams ? diag::err_typecheck_call_too_many_args : diag::err_typecheck_call_too_many_args_at_most) - << FnKind << NumParams << static_cast(Args.size()) - << Fn->getSourceRange() + << FnKind << NumParams - ExplicitObjectParameterOffset + << static_cast(Args.size()) - + ExplicitObjectParameterOffset + << HasExplicitObjectParameter << Fn->getSourceRange() << SourceRange(Args[NumParams]->getBeginLoc(), Args.back()->getEndLoc()); @@ -7661,9 +7680,9 @@ ExprResult Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, } if (CXXMethodDecl *Method = dyn_cast_or_null(FDecl)) - if (!Method->isStatic()) + if (Method->isImplicitObjectMemberFunction()) return ExprError(Diag(LParenLoc, diag::err_member_call_without_object) - << Fn->getSourceRange()); + << Fn->getSourceRange() << 0); // Check for sentinels if (NDecl) @@ -14955,6 +14974,34 @@ static void diagnoseAddressOfInvalidType(Sema &S, SourceLocation Loc, S.Diag(Loc, diag::err_typecheck_address_of) << Type << E->getSourceRange(); } +bool Sema::CheckUseOfCXXMethodAsAddressOfOperand(SourceLocation OpLoc, + const Expr *Op, + const CXXMethodDecl *MD) { + const auto *DRE = cast(Op->IgnoreParens()); + + if (Op != DRE) + return Diag(OpLoc, diag::err_parens_pointer_member_function) + << Op->getSourceRange(); + + // Taking the address of a dtor is illegal per C++ [class.dtor]p2. + if (isa(MD)) + return Diag(OpLoc, diag::err_typecheck_addrof_dtor) + << DRE->getSourceRange(); + + if (DRE->getQualifier()) + return false; + + if (MD->getParent()->getName().empty()) + return Diag(OpLoc, diag::err_unqualified_pointer_member_function) + << DRE->getSourceRange(); + + SmallString<32> Str; + StringRef Qual = (MD->getParent()->getName() + "::").toStringRef(Str); + return Diag(OpLoc, diag::err_unqualified_pointer_member_function) + << DRE->getSourceRange() + << FixItHint::CreateInsertion(DRE->getSourceRange().getBegin(), Qual); +} + /// CheckAddressOfOperand - The operand of & must be either a function /// designator or an lvalue designating an object. If it is an lvalue, the /// object cannot be declared with storage class register or be a bit field. @@ -15064,28 +15111,7 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) { DeclRefExpr *DRE = cast(op); CXXMethodDecl *MD = cast(DRE->getDecl()); - // The id-expression was parenthesized. - if (OrigOp.get() != DRE) { - Diag(OpLoc, diag::err_parens_pointer_member_function) - << OrigOp.get()->getSourceRange(); - - // The method was named without a qualifier. - } else if (!DRE->getQualifier()) { - if (MD->getParent()->getName().empty()) - Diag(OpLoc, diag::err_unqualified_pointer_member_function) - << op->getSourceRange(); - else { - SmallString<32> Str; - StringRef Qual = (MD->getParent()->getName() + "::").toStringRef(Str); - Diag(OpLoc, diag::err_unqualified_pointer_member_function) - << op->getSourceRange() - << FixItHint::CreateInsertion(op->getSourceRange().getBegin(), Qual); - } - } - - // Taking the address of a dtor is illegal per C++ [class.dtor]p2. - if (isa(MD)) - Diag(OpLoc, diag::err_typecheck_addrof_dtor) << op->getSourceRange(); + CheckUseOfCXXMethodAsAddressOfOperand(OpLoc, OrigOp.get(), MD); QualType MPTy = Context.getMemberPointerType( op->getType(), Context.getTypeDeclType(MD->getParent()).getTypePtr()); @@ -15105,7 +15131,11 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) { << op->getType() << op->getSourceRange(); return QualType(); } + } else if (const auto *DRE = dyn_cast(op)) { + if (const auto *MD = dyn_cast_or_null(DRE->getDecl())) + CheckUseOfCXXMethodAsAddressOfOperand(OpLoc, OrigOp.get(), MD); } + } else if (op->getObjectKind() == OK_BitField) { // C99 6.5.3.2p1 // The operand cannot be a bit-field AddressOfError = AO_Bit_Field; @@ -16496,7 +16526,7 @@ bool Sema::isQualifiedMemberAccess(Expr *E) { if (isa(VD) || isa(VD)) return true; if (CXXMethodDecl *Method = dyn_cast(VD)) - return Method->isInstance(); + return Method->isImplicitObjectMemberFunction(); return false; } @@ -16507,7 +16537,7 @@ bool Sema::isQualifiedMemberAccess(Expr *E) { for (NamedDecl *D : ULE->decls()) { if (CXXMethodDecl *Method = dyn_cast(D)) { - if (Method->isInstance()) + if (Method->isImplicitObjectMemberFunction()) return true; } else { // Overload set does not contain methods. @@ -18282,7 +18312,7 @@ void Sema::MarkExpressionAsImmediateEscalating(Expr *E) { ExprResult Sema::CheckForImmediateInvocation(ExprResult E, FunctionDecl *Decl) { if (isUnevaluatedContext() || !E.isUsable() || !Decl || - !Decl->isImmediateFunction() || isConstantEvaluated() || + !Decl->isImmediateFunction() || isAlwaysConstantEvaluatedContext() || isCheckingDefaultArgumentOrInitializer() || RebuildingImmediateInvocation || isImmediateFunctionContext()) return E; @@ -18438,7 +18468,10 @@ static void RemoveNestedImmediateInvocation( DRSet.erase(cast(E->getCallee()->IgnoreImplicit())); return Base::TransformCXXOperatorCallExpr(E); } - /// Base::TransformInitializer skip ConstantExpr so we need to visit them + /// Base::TransformUserDefinedLiteral doesn't preserve the + /// UserDefinedLiteral node. + ExprResult TransformUserDefinedLiteral(UserDefinedLiteral *E) { return E; } + /// Base::TransformInitializer skips ConstantExpr so we need to visit them /// here. ExprResult TransformInitializer(Expr *Init, bool NotCopyInit) { if (!Init) @@ -19127,7 +19160,7 @@ MarkVarDeclODRUsed(ValueDecl *V, SourceLocation Loc, Sema &SemaRef, // Diagnose ODR-use of host global variables in device functions. // Reference of device global variables in host functions is allowed // through shadow variables therefore it is not diagnosed. - if (SemaRef.LangOpts.CUDAIsDevice) { + if (SemaRef.LangOpts.CUDAIsDevice && !SemaRef.LangOpts.HIPStdPar) { SemaRef.targetDiag(Loc, diag::err_ref_bad_target) << /*host*/ 2 << /*variable*/ 1 << Var << UserTarget; SemaRef.targetDiag(Var->getLocation(), @@ -19227,7 +19260,8 @@ static bool isVariableAlreadyCapturedInScopeInfo(CapturingScopeInfo *CSI, // private instances of the captured declarations. const Capture &Cap = CSI->getCapture(Var); if (Cap.isCopyCapture() && - !(isa(CSI) && cast(CSI)->Mutable) && + !(isa(CSI) && + !cast(CSI)->lambdaCaptureShouldBeConst()) && !(isa(CSI) && cast(CSI)->CapRegionKind == CR_OpenMP)) DeclRefType.addConst(); @@ -19544,7 +19578,8 @@ static bool captureInLambda(LambdaScopeInfo *LSI, ValueDecl *Var, // declared const (9.3.1) if and only if the lambda-expression's // parameter-declaration-clause is not followed by mutable. DeclRefType = CaptureType.getNonReferenceType(); - if (!LSI->Mutable && !CaptureType->isReferenceType()) + bool Const = LSI->lambdaCaptureShouldBeConst(); + if (Const && !CaptureType->isReferenceType()) DeclRefType.addConst(); } @@ -20612,6 +20647,34 @@ void Sema::MarkVariableReferenced(SourceLocation Loc, VarDecl *Var) { DoMarkVarDeclReferenced(*this, Loc, Var, nullptr, RefsMinusAssignments); } +// C++ [temp.dep.expr]p3: +// An id-expression is type-dependent if it contains: +// - an identifier associated by name lookup with an entity captured by copy +// in a lambda-expression that has an explicit object parameter whose type +// is dependent ([dcl.fct]), +static void FixDependencyOfIdExpressionsInLambdaWithDependentObjectParameter( + Sema &SemaRef, ValueDecl *D, Expr *E) { + auto *ID = dyn_cast(E); + if (!ID || ID->isTypeDependent()) + return; + + auto IsDependent = [&]() { + const LambdaScopeInfo *LSI = SemaRef.getCurLambda(); + if (!LSI) + return false; + if (!LSI->ExplicitObjectParameter || + !LSI->ExplicitObjectParameter->getType()->isDependentType()) + return false; + if (!LSI->CaptureMap.count(D)) + return false; + const Capture &Cap = LSI->getCapture(D); + return !Cap.isCopyCapture(); + }(); + + ID->setCapturedByCopyInLambdaWithExplicitObjectParameter( + IsDependent, SemaRef.getASTContext()); +} + static void MarkExprReferenced(Sema &SemaRef, SourceLocation Loc, Decl *D, Expr *E, bool MightBeOdrUse, @@ -20621,14 +20684,19 @@ MarkExprReferenced(Sema &SemaRef, SourceLocation Loc, Decl *D, Expr *E, if (VarDecl *Var = dyn_cast(D)) { DoMarkVarDeclReferenced(SemaRef, Loc, Var, E, RefsMinusAssignments); + if (SemaRef.getLangOpts().CPlusPlus) + FixDependencyOfIdExpressionsInLambdaWithDependentObjectParameter(SemaRef, + Var, E); return; } if (BindingDecl *Decl = dyn_cast(D)) { DoMarkBindingDeclReferenced(SemaRef, Loc, Decl, E); + if (SemaRef.getLangOpts().CPlusPlus) + FixDependencyOfIdExpressionsInLambdaWithDependentObjectParameter(SemaRef, + Decl, E); return; } - SemaRef.MarkAnyDeclReferenced(Loc, D, MightBeOdrUse); // If this is a call to a method via a cast, also mark the method in the @@ -20668,7 +20736,7 @@ void Sema::MarkDeclRefReferenced(DeclRefExpr *E, const Expr *Base) { OdrUse = false; if (auto *FD = dyn_cast(E->getDecl())) { - if (!isUnevaluatedContext() && !isConstantEvaluated() && + if (!isUnevaluatedContext() && !isConstantEvaluatedContext() && !isImmediateFunctionContext() && !isCheckingDefaultArgumentOrInitializer() && FD->isImmediateFunction() && !RebuildingImmediateInvocation && diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index c147cc5293fd78..1153049496d129 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -1160,7 +1160,7 @@ static QualType adjustCVQualifiersForCXXThisWithinLambda( auto C = CurLSI->getCXXThisCapture(); if (C.isCopyCapture()) { - if (!CurLSI->Mutable) + if (CurLSI->lambdaCaptureShouldBeConst()) ClassType.addConst(); return ASTCtx.getPointerType(ClassType); } @@ -1216,11 +1216,11 @@ QualType Sema::getCurrentThisType() { QualType ThisTy = CXXThisTypeOverride; if (CXXMethodDecl *method = dyn_cast(DC)) { - if (method && method->isInstance()) + if (method && method->isImplicitObjectMemberFunction()) ThisTy = method->getThisType().getNonReferenceType(); } - if (ThisTy.isNull() && isLambdaCallOperator(CurContext) && + if (ThisTy.isNull() && isLambdaCallWithImplicitObjectParameter(CurContext) && inTemplateInstantiation() && isa(DC)) { // This is a lambda call operator that is being instantiated as a default @@ -1398,10 +1398,22 @@ ExprResult Sema::ActOnCXXThis(SourceLocation Loc) { /// C++ 9.3.2: In the body of a non-static member function, the keyword this /// is a non-lvalue expression whose value is the address of the object for /// which the function is called. - QualType ThisTy = getCurrentThisType(); - if (ThisTy.isNull()) - return Diag(Loc, diag::err_invalid_this_use); + + if (ThisTy.isNull()) { + DeclContext *DC = getFunctionLevelDeclContext(); + + if (const auto *Method = dyn_cast(DC); + Method && Method->isExplicitObjectMemberFunction()) { + return Diag(Loc, diag::err_invalid_this_use) << 1; + } + + if (isLambdaCallWithExplicitObjectParameter(CurContext)) + return Diag(Loc, diag::err_invalid_this_use) << 1; + + return Diag(Loc, diag::err_invalid_this_use) << 0; + } + return BuildCXXThisExpr(Loc, ThisTy, /*IsImplicit=*/false); } @@ -3960,7 +3972,7 @@ void Sema::CheckVirtualDtorCall(CXXDestructorDecl *dtor, SourceLocation Loc, if (getSourceManager().isInSystemHeader(PointeeRD->getLocation())) return; - QualType ClassType = dtor->getThisObjectType(); + QualType ClassType = dtor->getFunctionObjectParameterType(); if (PointeeRD->isAbstract()) { // If the class is abstract, we warn by default, because we're // sure the code has undefined behavior. @@ -4319,15 +4331,17 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, if (DiagnoseUseOfDecl(Fn, From->getBeginLoc())) return ExprError(); - From = FixOverloadedFunctionReference(From, Found, Fn); + ExprResult Res = FixOverloadedFunctionReference(From, Found, Fn); + if (Res.isInvalid()) + return ExprError(); // We might get back another placeholder expression if we resolved to a // builtin. - ExprResult Checked = CheckPlaceholderExpr(From); - if (Checked.isInvalid()) + Res = CheckPlaceholderExpr(Res.get()); + if (Res.isInvalid()) return ExprError(); - From = Checked.get(); + From = Res.get(); FromType = From->getType(); } @@ -8052,68 +8066,6 @@ ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base, Destructed); } -ExprResult Sema::BuildCXXMemberCallExpr(Expr *E, NamedDecl *FoundDecl, - CXXConversionDecl *Method, - bool HadMultipleCandidates) { - // Convert the expression to match the conversion function's implicit object - // parameter. - ExprResult Exp = PerformObjectArgumentInitialization(E, /*Qualifier=*/nullptr, - FoundDecl, Method); - if (Exp.isInvalid()) - return true; - - if (Method->getParent()->isLambda() && - Method->getConversionType()->isBlockPointerType()) { - // This is a lambda conversion to block pointer; check if the argument - // was a LambdaExpr. - Expr *SubE = E; - CastExpr *CE = dyn_cast(SubE); - if (CE && CE->getCastKind() == CK_NoOp) - SubE = CE->getSubExpr(); - SubE = SubE->IgnoreParens(); - if (CXXBindTemporaryExpr *BE = dyn_cast(SubE)) - SubE = BE->getSubExpr(); - if (isa(SubE)) { - // For the conversion to block pointer on a lambda expression, we - // construct a special BlockLiteral instead; this doesn't really make - // a difference in ARC, but outside of ARC the resulting block literal - // follows the normal lifetime rules for block literals instead of being - // autoreleased. - PushExpressionEvaluationContext( - ExpressionEvaluationContext::PotentiallyEvaluated); - ExprResult BlockExp = BuildBlockForLambdaConversion( - Exp.get()->getExprLoc(), Exp.get()->getExprLoc(), Method, Exp.get()); - PopExpressionEvaluationContext(); - - // FIXME: This note should be produced by a CodeSynthesisContext. - if (BlockExp.isInvalid()) - Diag(Exp.get()->getExprLoc(), diag::note_lambda_to_block_conv); - return BlockExp; - } - } - - MemberExpr *ME = - BuildMemberExpr(Exp.get(), /*IsArrow=*/false, SourceLocation(), - NestedNameSpecifierLoc(), SourceLocation(), Method, - DeclAccessPair::make(FoundDecl, FoundDecl->getAccess()), - HadMultipleCandidates, DeclarationNameInfo(), - Context.BoundMemberTy, VK_PRValue, OK_Ordinary); - - QualType ResultType = Method->getReturnType(); - ExprValueKind VK = Expr::getValueKindForType(ResultType); - ResultType = ResultType.getNonLValueExprType(Context); - - CXXMemberCallExpr *CE = CXXMemberCallExpr::Create( - Context, ME, /*Args=*/{}, ResultType, VK, Exp.get()->getEndLoc(), - CurFPFeatureOverrides()); - - if (CheckFunctionCall(Method, CE, - Method->getType()->castAs())) - return ExprError(); - - return CheckForImmediateInvocation(CE, CE->getMethodDecl()); -} - ExprResult Sema::BuildCXXNoexceptExpr(SourceLocation KeyLoc, Expr *Operand, SourceLocation RParen) { // If the operand is an unresolved lookup expression, the expression is ill- diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp index fe92215ae46776..bd85b548c0dd60 100644 --- a/clang/lib/Sema/SemaExprMember.cpp +++ b/clang/lib/Sema/SemaExprMember.cpp @@ -46,7 +46,7 @@ enum IMAKind { /// The reference may be to an instance member, but it might be invalid if /// so, because the context is not an instance method. - IMA_Mixed_StaticContext, + IMA_Mixed_StaticOrExplicitContext, /// The reference may be to an instance member, but it is invalid if /// so, because the context is from an unrelated class. @@ -63,7 +63,7 @@ enum IMAKind { /// The reference may be to an unresolved using declaration and the /// context is not an instance method. - IMA_Unresolved_StaticContext, + IMA_Unresolved_StaticOrExplicitContext, // The reference refers to a field which is not a member of the containing // class, which is allowed because we're in C++11 mode and the context is @@ -72,7 +72,7 @@ enum IMAKind { /// All possible referrents are instance members and the current /// context is not an instance method. - IMA_Error_StaticContext, + IMA_Error_StaticOrExplicitContext, /// All possible referrents are instance members of an unrelated /// class. @@ -91,11 +91,14 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef, DeclContext *DC = SemaRef.getFunctionLevelDeclContext(); - bool isStaticContext = SemaRef.CXXThisTypeOverride.isNull() && - (!isa(DC) || cast(DC)->isStatic()); + bool isStaticOrExplicitContext = + SemaRef.CXXThisTypeOverride.isNull() && + (!isa(DC) || cast(DC)->isStatic() || + cast(DC)->isExplicitObjectMemberFunction()); if (R.isUnresolvableResult()) - return isStaticContext ? IMA_Unresolved_StaticContext : IMA_Unresolved; + return isStaticOrExplicitContext ? IMA_Unresolved_StaticOrExplicitContext + : IMA_Unresolved; // Collect all the declaring classes of instance members we find. bool hasNonInstance = false; @@ -152,12 +155,12 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef, // If the current context is not an instance method, it can't be // an implicit member reference. - if (isStaticContext) { + if (isStaticOrExplicitContext) { if (hasNonInstance) - return IMA_Mixed_StaticContext; + return IMA_Mixed_StaticOrExplicitContext; return AbstractInstanceResult ? AbstractInstanceResult - : IMA_Error_StaticContext; + : IMA_Error_StaticOrExplicitContext; } CXXRecordDecl *contextClass; @@ -167,7 +170,7 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef, contextClass = RD; else return AbstractInstanceResult ? AbstractInstanceResult - : IMA_Error_StaticContext; + : IMA_Error_StaticOrExplicitContext; // [class.mfct.non-static]p3: // ...is used in the body of a non-static member function of class X, @@ -214,14 +217,31 @@ static void diagnoseInstanceReference(Sema &SemaRef, CXXRecordDecl *RepClass = dyn_cast(Rep->getDeclContext()); bool InStaticMethod = Method && Method->isStatic(); + bool InExplicitObjectMethod = + Method && Method->isExplicitObjectMemberFunction(); bool IsField = isa(Rep) || isa(Rep); + std::string Replacement; + if (InExplicitObjectMethod) { + DeclarationName N = Method->getParamDecl(0)->getDeclName(); + if (!N.isEmpty()) { + Replacement.append(N.getAsString()); + Replacement.append("."); + } + } if (IsField && InStaticMethod) // "invalid use of member 'x' in static member function" - SemaRef.Diag(Loc, diag::err_invalid_member_use_in_static_method) - << Range << nameInfo.getName(); - else if (ContextClass && RepClass && SS.isEmpty() && !InStaticMethod && - !RepClass->Equals(ContextClass) && RepClass->Encloses(ContextClass)) + SemaRef.Diag(Loc, diag::err_invalid_member_use_in_method) + << Range << nameInfo.getName() << /*static*/ 0; + else if (IsField && InExplicitObjectMethod) { + auto Diag = SemaRef.Diag(Loc, diag::err_invalid_member_use_in_method) + << Range << nameInfo.getName() << /*explicit*/ 1; + if (!Replacement.empty()) + Diag << FixItHint::CreateInsertion(Loc, Replacement); + } else if (ContextClass && RepClass && SS.isEmpty() && + !InExplicitObjectMethod && !InStaticMethod && + !RepClass->Equals(ContextClass) && + RepClass->Encloses(ContextClass)) // Unqualified lookup in a non-static member function found a member of an // enclosing class. SemaRef.Diag(Loc, diag::err_nested_non_static_member_use) @@ -229,9 +249,16 @@ static void diagnoseInstanceReference(Sema &SemaRef, else if (IsField) SemaRef.Diag(Loc, diag::err_invalid_non_static_member_use) << nameInfo.getName() << Range; - else + else if (!InExplicitObjectMethod) SemaRef.Diag(Loc, diag::err_member_call_without_object) - << Range; + << Range << /*static*/ 0; + else { + const auto *Callee = dyn_cast(Rep); + auto Diag = SemaRef.Diag(Loc, diag::err_member_call_without_object) + << Range << Callee->isExplicitObjectMemberFunction(); + if (!Replacement.empty()) + Diag << FixItHint::CreateInsertion(Loc, Replacement); + } } /// Builds an expression which might be an implicit member expression. @@ -255,13 +282,13 @@ ExprResult Sema::BuildPossibleImplicitMemberExpr( [[fallthrough]]; case IMA_Static: case IMA_Abstract: - case IMA_Mixed_StaticContext: - case IMA_Unresolved_StaticContext: + case IMA_Mixed_StaticOrExplicitContext: + case IMA_Unresolved_StaticOrExplicitContext: if (TemplateArgs || TemplateKWLoc.isValid()) return BuildTemplateIdExpr(SS, TemplateKWLoc, R, false, TemplateArgs); return AsULE ? AsULE : BuildDeclarationNameExpr(SS, R, false); - case IMA_Error_StaticContext: + case IMA_Error_StaticOrExplicitContext: case IMA_Error_Unrelated: diagnoseInstanceReference(*this, SS, R.getRepresentativeDecl(), R.getLookupNameInfo()); diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp index 5df830e5bee6d6..33e98bc2d6f713 100644 --- a/clang/lib/Sema/SemaExprObjC.cpp +++ b/clang/lib/Sema/SemaExprObjC.cpp @@ -1800,7 +1800,8 @@ bool Sema::CheckMessageArgumentTypes( // FIXME. This need be cleaned up. if (Args.size() < NumNamedArgs) { Diag(SelLoc, diag::err_typecheck_call_too_few_args) - << 2 << NumNamedArgs << static_cast(Args.size()); + << 2 << NumNamedArgs << static_cast(Args.size()) + << /*is non object*/ 0; return false; } @@ -1898,7 +1899,7 @@ bool Sema::CheckMessageArgumentTypes( Diag(Args[NumNamedArgs]->getBeginLoc(), diag::err_typecheck_call_too_many_args) << 2 /*method*/ << NumNamedArgs << static_cast(Args.size()) - << Method->getSourceRange() + << Method->getSourceRange() << /*is non object*/ 0 << SourceRange(Args[NumNamedArgs]->getBeginLoc(), Args.back()->getEndLoc()); } diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index de576cc52c42e7..fd95b16b84b6e3 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -7421,8 +7421,9 @@ static bool shouldTrackImplicitObjectArg(const CXXMethodDecl *Callee) { return true; if (!isInStlNamespace(Callee->getParent())) return false; - if (!isRecordWithAttr(Callee->getThisObjectType()) && - !isRecordWithAttr(Callee->getThisObjectType())) + if (!isRecordWithAttr( + Callee->getFunctionObjectParameterType()) && + !isRecordWithAttr(Callee->getFunctionObjectParameterType())) return false; if (Callee->getReturnType()->isPointerType() || isRecordWithAttr(Callee->getReturnType())) { @@ -7557,7 +7558,7 @@ static bool implicitObjectParamIsLifetimeBound(const FunctionDecl *FD) { QualType LHST; auto *MD = dyn_cast(FD); if (MD && MD->isCXXInstanceMember()) - LHST = Ctx.getLValueReferenceType(MD->getThisObjectType()); + LHST = Ctx.getLValueReferenceType(MD->getFunctionObjectParameterType()); else LHST = MD->getParamDecl(0)->getType(); if (Ctx.hasSameType(RetT, LHST)) diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp index 1702ddb3ee0fbf..421048aaff5c90 100644 --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/lib/Sema/SemaLambda.cpp @@ -379,6 +379,38 @@ buildTypeForLambdaCallOperator(Sema &S, clang::CXXRecordDecl *Class, return MethodType; } +// [C++2b] [expr.prim.lambda.closure] p4 +// Given a lambda with a lambda-capture, the type of the explicit object +// parameter, if any, of the lambda's function call operator (possibly +// instantiated from a function call operator template) shall be either: +// - the closure type, +// - class type derived from the closure type, or +// - a reference to a possibly cv-qualified such type. +void Sema::DiagnoseInvalidExplicitObjectParameterInLambda( + CXXMethodDecl *Method) { + if (!isLambdaCallWithExplicitObjectParameter(Method)) + return; + CXXRecordDecl *RD = Method->getParent(); + if (Method->getType()->isDependentType()) + return; + if (RD->getLambdaCaptureDefault() == LambdaCaptureDefault::LCD_None && + RD->capture_size() == 0) + return; + QualType ExplicitObjectParameterType = Method->getParamDecl(0) + ->getType() + .getNonReferenceType() + .getUnqualifiedType() + .getDesugaredType(getASTContext()); + QualType LambdaType = getASTContext().getRecordType(RD); + if (LambdaType == ExplicitObjectParameterType) + return; + if (IsDerivedFrom(RD->getLocation(), ExplicitObjectParameterType, LambdaType)) + return; + Diag(Method->getParamDecl(0)->getLocation(), + diag::err_invalid_explicit_object_type_in_lambda) + << ExplicitObjectParameterType; +} + void Sema::handleLambdaNumbering( CXXRecordDecl *Class, CXXMethodDecl *Method, std::optional NumberingOverride) { @@ -860,9 +892,17 @@ static TypeSourceInfo *getLambdaType(Sema &S, LambdaIntroducer &Intro, if (ParamInfo.getNumTypeObjects() == 0) { MethodTyInfo = getDummyLambdaType(S, Loc); } else { + // Check explicit parameters + S.CheckExplicitObjectLambda(ParamInfo); + DeclaratorChunk::FunctionTypeInfo &FTI = ParamInfo.getFunctionTypeInfo(); + + bool HasExplicitObjectParameter = + ParamInfo.isExplicitObjectMemberFunction(); + ExplicitResultType = FTI.hasTrailingReturnType(); - if (!FTI.hasMutableQualifier() && !IsLambdaStatic) + if (!FTI.hasMutableQualifier() && !IsLambdaStatic && + !HasExplicitObjectParameter) FTI.getOrCreateMethodQualifiers().SetTypeQual(DeclSpec::TQ_const, Loc); if (ExplicitResultType && S.getLangOpts().HLSL) { @@ -1686,7 +1726,7 @@ static void addFunctionPointerConversion(Sema &S, SourceRange IntroducerRange, // function that will be the result of the conversion with a // certain unique ID. // When it is static we just return the static call operator instead. - if (CallOperator->isInstance()) { + if (CallOperator->isImplicitObjectMemberFunction()) { DeclarationName InvokerName = &S.Context.Idents.get(getLambdaStaticInvokerName()); // FIXME: Instead of passing in the CallOperator->getTypeSourceInfo() @@ -2256,33 +2296,55 @@ ExprResult Sema::BuildBlockForLambdaConversion(SourceLocation CurrentLocation, return BuildBlock; } +static FunctionDecl *getPatternFunctionDecl(FunctionDecl *FD) { + if (FD->getTemplatedKind() == FunctionDecl::TK_MemberSpecialization) { + while (FD->getInstantiatedFromMemberFunction()) + FD = FD->getInstantiatedFromMemberFunction(); + return FD; + } + + if (FD->getTemplatedKind() == FunctionDecl::TK_DependentNonTemplate) + return FD->getInstantiatedFromDecl(); + + FunctionTemplateDecl *FTD = FD->getPrimaryTemplate(); + if (!FTD) + return nullptr; + + while (FTD->getInstantiatedFromMemberTemplate()) + FTD = FTD->getInstantiatedFromMemberTemplate(); + + return FTD->getTemplatedDecl(); +} + Sema::LambdaScopeForCallOperatorInstantiationRAII:: LambdaScopeForCallOperatorInstantiationRAII( - Sema &SemasRef, FunctionDecl *FD, MultiLevelTemplateArgumentList MLTAL, - LocalInstantiationScope &Scope) - : FunctionScopeRAII(SemasRef) { + Sema &SemaRef, FunctionDecl *FD, MultiLevelTemplateArgumentList MLTAL, + LocalInstantiationScope &Scope, bool ShouldAddDeclsFromParentScope) + : FunctionScopeRAII(SemaRef) { if (!isLambdaCallOperator(FD)) { FunctionScopeRAII::disable(); return; } - if (FD->isTemplateInstantiation() && FD->getPrimaryTemplate()) { - FunctionTemplateDecl *PrimaryTemplate = FD->getPrimaryTemplate(); - if (const auto *FromMemTempl = - PrimaryTemplate->getInstantiatedFromMemberTemplate()) { - SemasRef.addInstantiatedCapturesToScope( - FD, FromMemTempl->getTemplatedDecl(), Scope, MLTAL); - } - } + SemaRef.RebuildLambdaScopeInfo(cast(FD)); - else if (FD->getTemplatedKind() == FunctionDecl::TK_MemberSpecialization || - FD->getTemplatedKind() == FunctionDecl::TK_DependentNonTemplate) { - FunctionDecl *InstantiatedFrom = - FD->getTemplatedKind() == FunctionDecl::TK_MemberSpecialization - ? FD->getInstantiatedFromMemberFunction() - : FD->getInstantiatedFromDecl(); - SemasRef.addInstantiatedCapturesToScope(FD, InstantiatedFrom, Scope, MLTAL); - } + FunctionDecl *Pattern = getPatternFunctionDecl(FD); + if (Pattern) { + SemaRef.addInstantiatedCapturesToScope(FD, Pattern, Scope, MLTAL); - SemasRef.RebuildLambdaScopeInfo(cast(FD)); + FunctionDecl *ParentFD = FD; + while (ShouldAddDeclsFromParentScope) { + + ParentFD = + dyn_cast(getLambdaAwareParentOfDeclContext(ParentFD)); + Pattern = + dyn_cast(getLambdaAwareParentOfDeclContext(Pattern)); + + if (!FD || !Pattern) + break; + + SemaRef.addInstantiatedParametersToScope(ParentFD, Pattern, Scope, MLTAL); + SemaRef.addInstantiatedLocalVarsToScope(ParentFD, Pattern, Scope); + } + } } diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index d42a21976821a4..eb755e2a0c4540 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -17553,6 +17553,9 @@ OMPClause *Sema::ActOnOpenMPClause(OpenMPClauseKind Kind, case OMPC_partial: Res = ActOnOpenMPPartialClause(nullptr, StartLoc, /*LParenLoc=*/{}, EndLoc); break; + case OMPC_ompx_bare: + Res = ActOnOpenMPXBareClause(StartLoc, EndLoc); + break; case OMPC_if: case OMPC_final: case OMPC_num_threads: @@ -24279,3 +24282,8 @@ OMPClause *Sema::ActOnOpenMPXAttributeClause(ArrayRef Attrs, SourceLocation EndLoc) { return new (Context) OMPXAttributeClause(Attrs, StartLoc, LParenLoc, EndLoc); } + +OMPClause *Sema::ActOnOpenMPXBareClause(SourceLocation StartLoc, + SourceLocation EndLoc) { + return new (Context) OMPXBareClause(StartLoc, EndLoc); +} diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 0ac2ac258c0c7d..ce78994e655381 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -910,6 +910,9 @@ static bool FunctionsCorrespond(ASTContext &Ctx, const FunctionDecl *X, return false; if (X->getNumParams() != Y->getNumParams()) return false; + // FIXME: when do rewritten comparison operators + // with explicit object parameters correspond? + // https://cplusplus.github.io/CWG/issues/2797.html for (unsigned I = 0; I < X->getNumParams(); ++I) if (!Ctx.hasSameUnqualifiedType(X->getParamDecl(I)->getType(), Y->getParamDecl(I)->getType())) @@ -994,7 +997,7 @@ bool OverloadCandidateSet::OperatorRewriteInfo::shouldAddReversed( } // Don't bother adding a reversed candidate that can never be a better // match than the non-reversed version. - return FD->getNumParams() != 2 || + return FD->getNumNonObjectParams() != 2 || !S.Context.hasSameUnqualifiedType(FD->getParamDecl(0)->getType(), FD->getParamDecl(1)->getType()) || FD->hasAttr(); @@ -1235,9 +1238,11 @@ Sema::CheckOverload(Scope *S, FunctionDecl *New, const LookupResult &Old, return Ovl_Overload; } -bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old, - bool UseMemberUsingDeclRules, bool ConsiderCudaAttrs, - bool ConsiderRequiresClauses) { +static bool IsOverloadOrOverrideImpl(Sema &SemaRef, FunctionDecl *New, + FunctionDecl *Old, + bool UseMemberUsingDeclRules, + bool ConsiderCudaAttrs, + bool UseOverrideRules = false) { // C++ [basic.start.main]p2: This function shall not be overloaded. if (New->isMain()) return false; @@ -1256,8 +1261,8 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old, return true; // Is the function New an overload of the function Old? - QualType OldQType = Context.getCanonicalType(Old->getType()); - QualType NewQType = Context.getCanonicalType(New->getType()); + QualType OldQType = SemaRef.Context.getCanonicalType(Old->getType()); + QualType NewQType = SemaRef.Context.getCanonicalType(New->getType()); // Compare the signatures (C++ 1.3.10) of the two functions to // determine whether they are overloads. If we find any mismatch @@ -1275,10 +1280,7 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old, // The signature of a function includes the types of its // parameters (C++ 1.3.10), which includes the presence or absence // of the ellipsis; see C++ DR 357). - if (OldQType != NewQType && - (OldType->getNumParams() != NewType->getNumParams() || - OldType->isVariadic() != NewType->isVariadic() || - !FunctionParamTypesAreEqual(OldType, NewType))) + if (OldQType != NewQType && OldType->isVariadic() != NewType->isVariadic()) return true; // For member-like friends, the enclosing class is part of the signature. @@ -1286,6 +1288,128 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old, Old->isMemberLikeConstrainedFriend()) && !New->getLexicalDeclContext()->Equals(Old->getLexicalDeclContext())) return true; + const auto *OldMethod = dyn_cast(Old); + const auto *NewMethod = dyn_cast(New); + + int OldParamsOffset = 0; + int NewParamsOffset = 0; + + // When determining if a method is an overload from a base class, act as if + // the implicit object parameter are of the same type. + + auto NormalizeQualifiers = [&](const CXXMethodDecl *M, Qualifiers Q) { + if (M->isExplicitObjectMemberFunction()) + return Q; + + // We do not allow overloading based off of '__restrict'. + Q.removeRestrict(); + + // We may not have applied the implicit const for a constexpr member + // function yet (because we haven't yet resolved whether this is a static + // or non-static member function). Add it now, on the assumption that this + // is a redeclaration of OldMethod. + if (!SemaRef.getLangOpts().CPlusPlus14 && + (M->isConstexpr() || M->isConsteval()) && + !isa(NewMethod)) + Q.addConst(); + return Q; + }; + + auto CompareType = [&](QualType Base, QualType D) { + auto BS = Base.getNonReferenceType().getCanonicalType().split(); + BS.Quals = NormalizeQualifiers(OldMethod, BS.Quals); + + auto DS = D.getNonReferenceType().getCanonicalType().split(); + DS.Quals = NormalizeQualifiers(NewMethod, DS.Quals); + + if (BS.Quals != DS.Quals) + return false; + + if (OldMethod->isImplicitObjectMemberFunction() && + OldMethod->getParent() != NewMethod->getParent()) { + QualType ParentType = + SemaRef.Context.getTypeDeclType(OldMethod->getParent()) + .getCanonicalType(); + if (ParentType.getTypePtr() != BS.Ty) + return false; + BS.Ty = DS.Ty; + } + + // FIXME: should we ignore some type attributes here? + if (BS.Ty != DS.Ty) + return false; + + if (Base->isLValueReferenceType()) + return D->isLValueReferenceType(); + return Base->isRValueReferenceType() == D->isRValueReferenceType(); + }; + + // If the function is a class member, its signature includes the + // cv-qualifiers (if any) and ref-qualifier (if any) on the function itself. + auto DiagnoseInconsistentRefQualifiers = [&]() { + if (SemaRef.LangOpts.CPlusPlus23) + return false; + if (OldMethod->getRefQualifier() == NewMethod->getRefQualifier()) + return false; + if (OldMethod->isExplicitObjectMemberFunction() || + NewMethod->isExplicitObjectMemberFunction()) + return false; + if (!UseMemberUsingDeclRules && (OldMethod->getRefQualifier() == RQ_None || + NewMethod->getRefQualifier() == RQ_None)) { + SemaRef.Diag(NewMethod->getLocation(), diag::err_ref_qualifier_overload) + << NewMethod->getRefQualifier() << OldMethod->getRefQualifier(); + SemaRef.Diag(OldMethod->getLocation(), diag::note_previous_declaration); + return true; + } + return false; + }; + + if (OldMethod && OldMethod->isExplicitObjectMemberFunction()) + OldParamsOffset++; + if (NewMethod && NewMethod->isExplicitObjectMemberFunction()) + NewParamsOffset++; + + if (OldType->getNumParams() - OldParamsOffset != + NewType->getNumParams() - NewParamsOffset || + !SemaRef.FunctionParamTypesAreEqual( + {OldType->param_type_begin() + OldParamsOffset, + OldType->param_type_end()}, + {NewType->param_type_begin() + NewParamsOffset, + NewType->param_type_end()}, + nullptr)) { + return true; + } + + if (OldMethod && NewMethod && !OldMethod->isStatic() && + !OldMethod->isStatic()) { + bool HaveCorrespondingObjectParameters = [&](const CXXMethodDecl *Old, + const CXXMethodDecl *New) { + auto NewObjectType = New->getFunctionObjectParameterReferenceType(); + auto OldObjectType = Old->getFunctionObjectParameterReferenceType(); + + auto IsImplicitWithNoRefQual = [](const CXXMethodDecl *F) { + return F->getRefQualifier() == RQ_None && + !F->isExplicitObjectMemberFunction(); + }; + + if (IsImplicitWithNoRefQual(Old) != IsImplicitWithNoRefQual(New) && + CompareType(OldObjectType.getNonReferenceType(), + NewObjectType.getNonReferenceType())) + return true; + return CompareType(OldObjectType, NewObjectType); + }(OldMethod, NewMethod); + + if (!HaveCorrespondingObjectParameters) { + if (DiagnoseInconsistentRefQualifiers()) + return true; + // CWG2554 + // and, if at least one is an explicit object member function, ignoring + // object parameters + if (!UseOverrideRules || (!NewMethod->isExplicitObjectMemberFunction() && + !OldMethod->isExplicitObjectMemberFunction())) + return true; + } + } if (NewTemplate) { // C++ [temp.over.link]p4: @@ -1297,11 +1421,11 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old, // // We check the return type and template parameter lists for function // templates first; the remaining checks follow. - bool SameTemplateParameterList = TemplateParameterListsAreEqual( + bool SameTemplateParameterList = SemaRef.TemplateParameterListsAreEqual( NewTemplate, NewTemplate->getTemplateParameters(), OldTemplate, - OldTemplate->getTemplateParameters(), false, TPL_TemplateMatch); - bool SameReturnType = Context.hasSameType(Old->getDeclaredReturnType(), - New->getDeclaredReturnType()); + 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. @@ -1324,59 +1448,19 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old, return true; } - if (ConsiderRequiresClauses) { + if (!UseOverrideRules) { Expr *NewRC = New->getTrailingRequiresClause(), *OldRC = Old->getTrailingRequiresClause(); if ((NewRC != nullptr) != (OldRC != nullptr)) return true; - if (NewRC && !AreConstraintExpressionsEqual(Old, OldRC, New, NewRC)) - return true; - } - - // If the function is a class member, its signature includes the - // cv-qualifiers (if any) and ref-qualifier (if any) on the function itself. - // - // As part of this, also check whether one of the member functions - // is static, in which case they are not overloads (C++ - // 13.1p2). While not part of the definition of the signature, - // this check is important to determine whether these functions - // can be overloaded. - CXXMethodDecl *OldMethod = dyn_cast(Old); - CXXMethodDecl *NewMethod = dyn_cast(New); - if (OldMethod && NewMethod && - !OldMethod->isStatic() && !NewMethod->isStatic()) { - if (OldMethod->getRefQualifier() != NewMethod->getRefQualifier()) { - if (!UseMemberUsingDeclRules && - (OldMethod->getRefQualifier() == RQ_None || - NewMethod->getRefQualifier() == RQ_None)) { - // C++20 [over.load]p2: - // - Member function declarations with the same name, the same - // parameter-type-list, and the same trailing requires-clause (if - // any), as well as member function template declarations with the - // same name, the same parameter-type-list, the same trailing - // requires-clause (if any), and the same template-head, cannot be - // overloaded if any of them, but not all, have a ref-qualifier. - Diag(NewMethod->getLocation(), diag::err_ref_qualifier_overload) - << NewMethod->getRefQualifier() << OldMethod->getRefQualifier(); - Diag(OldMethod->getLocation(), diag::note_previous_declaration); - } + if (NewRC && !SemaRef.AreConstraintExpressionsEqual(Old, OldRC, New, NewRC)) return true; - } + } - // We may not have applied the implicit const for a constexpr member - // function yet (because we haven't yet resolved whether this is a static - // or non-static member function). Add it now, on the assumption that this - // is a redeclaration of OldMethod. - auto OldQuals = OldMethod->getMethodQualifiers(); - auto NewQuals = NewMethod->getMethodQualifiers(); - if (!getLangOpts().CPlusPlus14 && NewMethod->isConstexpr() && - !isa(NewMethod)) - NewQuals.addConst(); - // We do not allow overloading based off of '__restrict'. - OldQuals.removeRestrict(); - NewQuals.removeRestrict(); - if (OldQuals != NewQuals) + if (NewMethod && OldMethod && OldMethod->isImplicitObjectMemberFunction() && + NewMethod->isImplicitObjectMemberFunction()) { + if (DiagnoseInconsistentRefQualifiers()) return true; } @@ -1398,20 +1482,20 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old, if (NewI == NewE || OldI == OldE) return true; llvm::FoldingSetNodeID NewID, OldID; - NewI->getCond()->Profile(NewID, Context, true); - OldI->getCond()->Profile(OldID, Context, true); + NewI->getCond()->Profile(NewID, SemaRef.Context, true); + OldI->getCond()->Profile(OldID, SemaRef.Context, true); if (NewID != OldID) return true; } - if (getLangOpts().CUDA && ConsiderCudaAttrs) { + if (SemaRef.getLangOpts().CUDA && ConsiderCudaAttrs) { // Don't allow overloading of destructors. (In theory we could, but it // would be a giant change to clang.) if (!isa(New)) { - CUDAFunctionTarget NewTarget = IdentifyCUDATarget(New), - OldTarget = IdentifyCUDATarget(Old); - if (NewTarget != CFT_InvalidTarget) { - assert((OldTarget != CFT_InvalidTarget) && + Sema::CUDAFunctionTarget NewTarget = SemaRef.IdentifyCUDATarget(New), + OldTarget = SemaRef.IdentifyCUDATarget(Old); + if (NewTarget != Sema::CFT_InvalidTarget) { + assert((OldTarget != Sema::CFT_InvalidTarget) && "Unexpected invalid target."); // Allow overloading of functions with same signature and different CUDA @@ -1426,6 +1510,20 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old, return false; } +bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old, + bool UseMemberUsingDeclRules, bool ConsiderCudaAttrs) { + return IsOverloadOrOverrideImpl(*this, New, Old, UseMemberUsingDeclRules, + ConsiderCudaAttrs); +} + +bool Sema::IsOverride(FunctionDecl *MD, FunctionDecl *BaseMD, + bool UseMemberUsingDeclRules, bool ConsiderCudaAttrs) { + return IsOverloadOrOverrideImpl(*this, MD, BaseMD, + /*UseMemberUsingDeclRules=*/false, + /*ConsiderCudaAttrs=*/true, + /*UseOverrideRules=*/true); +} + /// Tries a user-defined conversion from From to ToType. /// /// Produces an implicit conversion sequence for when a standard conversion @@ -1884,7 +1982,8 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, // fact that non-static member functions *must* have such an address-of // expression. CXXMethodDecl *Method = dyn_cast(Fn); - if (Method && !Method->isStatic()) { + if (Method && !Method->isStatic() && + !Method->isExplicitObjectMemberFunction()) { assert(isa(From->IgnoreParens()) && "Non-unary operator on non-static member address"); assert(cast(From->IgnoreParens())->getOpcode() @@ -3104,30 +3203,40 @@ void Sema::HandleFunctionTypeMismatch(PartialDiagnostic &PDiag, /// If `Reversed` is true, the parameters of `NewType` will be compared in /// reverse order. That's useful if one of the functions is being used as a C++20 /// synthesized operator overload with a reversed parameter order. -bool Sema::FunctionParamTypesAreEqual(const FunctionProtoType *OldType, - const FunctionProtoType *NewType, - unsigned *ArgPos, bool Reversed) { - assert(OldType->getNumParams() == NewType->getNumParams() && +bool Sema::FunctionParamTypesAreEqual(ArrayRef Old, + ArrayRef New, unsigned *ArgPos, + bool Reversed) { + assert(llvm::size(Old) == llvm::size(New) && "Can't compare parameters of functions with different number of " "parameters!"); - for (size_t I = 0; I < OldType->getNumParams(); I++) { + + for (auto &&[Idx, Type] : llvm::enumerate(Old)) { // Reverse iterate over the parameters of `OldType` if `Reversed` is true. - size_t J = Reversed ? (OldType->getNumParams() - I - 1) : I; + size_t J = Reversed ? (llvm::size(New) - Idx - 1) : Idx; // Ignore address spaces in pointee type. This is to disallow overloading // on __ptr32/__ptr64 address spaces. - QualType Old = Context.removePtrSizeAddrSpace(OldType->getParamType(I).getUnqualifiedType()); - QualType New = Context.removePtrSizeAddrSpace(NewType->getParamType(J).getUnqualifiedType()); + QualType OldType = + Context.removePtrSizeAddrSpace(Type.getUnqualifiedType()); + QualType NewType = + Context.removePtrSizeAddrSpace((New.begin() + J)->getUnqualifiedType()); - if (!Context.hasSameType(Old, New)) { + if (!Context.hasSameType(OldType, NewType)) { if (ArgPos) - *ArgPos = I; + *ArgPos = Idx; return false; } } return true; } +bool Sema::FunctionParamTypesAreEqual(const FunctionProtoType *OldType, + const FunctionProtoType *NewType, + unsigned *ArgPos, bool Reversed) { + return FunctionParamTypesAreEqual(OldType->param_types(), + NewType->param_types(), ArgPos, Reversed); +} + /// CheckPointerConversion - Check the pointer conversion from the /// expression From to the type ToType. This routine checks for /// ambiguous or inaccessible derived-to-base pointer @@ -3532,7 +3641,7 @@ IsInitializerListConstructorConversion(Sema &S, Expr *From, QualType ToType, case OR_Success: { // Record the standard conversion we used and the conversion function. CXXConstructorDecl *Constructor = cast(Best->Function); - QualType ThisType = Constructor->getThisObjectType(); + QualType ThisType = Constructor->getFunctionObjectParameterType(); // Initializer lists don't have conversions as such. User.Before.setAsIdentityConversion(); User.HadMultipleCandidates = HadMultipleCandidates; @@ -3734,7 +3843,7 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, User.ConversionFunction = Constructor; User.FoundConversionFunction = Best->FoundDecl; User.After.setAsIdentityConversion(); - User.After.setFromType(Constructor->getThisObjectType()); + User.After.setFromType(Constructor->getFunctionObjectParameterType()); User.After.setAllToTypes(ToType); return Result; } @@ -5505,11 +5614,45 @@ static bool TryCopyInitialization(const CanQualType FromQTy, /// TryObjectArgumentInitialization - Try to initialize the object /// parameter of the given member function (@c Method) from the /// expression @p From. -static ImplicitConversionSequence -TryObjectArgumentInitialization(Sema &S, SourceLocation Loc, QualType FromType, - Expr::Classification FromClassification, - CXXMethodDecl *Method, - CXXRecordDecl *ActingContext) { +static ImplicitConversionSequence TryObjectArgumentInitialization( + Sema &S, SourceLocation Loc, QualType FromType, + Expr::Classification FromClassification, CXXMethodDecl *Method, + const CXXRecordDecl *ActingContext, bool InOverloadResolution = false, + QualType ExplicitParameterType = QualType(), + bool SuppressUserConversion = false) { + + // We need to have an object of class type. + if (const auto *PT = FromType->getAs()) { + FromType = PT->getPointeeType(); + + // When we had a pointer, it's implicitly dereferenced, so we + // better have an lvalue. + assert(FromClassification.isLValue()); + } + + auto ValueKindFromClassification = [](Expr::Classification C) { + if (C.isPRValue()) + return clang::VK_PRValue; + if (C.isXValue()) + return VK_XValue; + return clang::VK_LValue; + }; + + if (Method->isExplicitObjectMemberFunction()) { + if (ExplicitParameterType.isNull()) + ExplicitParameterType = Method->getFunctionObjectParameterReferenceType(); + OpaqueValueExpr TmpExpr(Loc, FromType.getNonReferenceType(), + ValueKindFromClassification(FromClassification)); + ImplicitConversionSequence ICS = TryCopyInitialization( + S, &TmpExpr, ExplicitParameterType, SuppressUserConversion, + /*InOverloadResolution=*/true, false); + if (ICS.isBad()) + ICS.Bad.FromExpr = nullptr; + return ICS; + } + + assert(FromType->isRecordType()); + QualType ClassType = S.Context.getTypeDeclType(ActingContext); // [class.dtor]p2: A destructor can be invoked for a const, volatile or // const volatile object. @@ -5525,17 +5668,6 @@ TryObjectArgumentInitialization(Sema &S, SourceLocation Loc, QualType FromType, // to exit early. ImplicitConversionSequence ICS; - // We need to have an object of class type. - if (const PointerType *PT = FromType->getAs()) { - FromType = PT->getPointeeType(); - - // When we had a pointer, it's implicitly dereferenced, so we - // better have an lvalue. - assert(FromClassification.isLValue()); - } - - assert(FromType->isRecordType()); - // C++0x [over.match.funcs]p4: // For non-static member functions, the type of the implicit object // parameter is @@ -5582,9 +5714,9 @@ TryObjectArgumentInitialization(Sema &S, SourceLocation Loc, QualType FromType, ImplicitConversionKind SecondKind; if (ClassTypeCanon == FromTypeCanon.getLocalUnqualifiedType()) { SecondKind = ICK_Identity; - } else if (S.IsDerivedFrom(Loc, FromType, ClassType)) + } else if (S.IsDerivedFrom(Loc, FromType, ClassType)) { SecondKind = ICK_Derived_To_Base; - else { + } else if (!Method->isExplicitObjectMemberFunction()) { ICS.setBad(BadConversionSequence::unrelated_class, FromType, ImplicitParamType); return ICS; @@ -5634,13 +5766,11 @@ TryObjectArgumentInitialization(Sema &S, SourceLocation Loc, QualType FromType, /// PerformObjectArgumentInitialization - Perform initialization of /// the implicit object parameter for the given Method with the given /// expression. -ExprResult -Sema::PerformObjectArgumentInitialization(Expr *From, - NestedNameSpecifier *Qualifier, - NamedDecl *FoundDecl, - CXXMethodDecl *Method) { +ExprResult Sema::PerformImplicitObjectArgumentInitialization( + Expr *From, NestedNameSpecifier *Qualifier, NamedDecl *FoundDecl, + CXXMethodDecl *Method) { QualType FromRecordType, DestType; - QualType ImplicitParamRecordType = Method->getThisObjectType(); + QualType ImplicitParamRecordType = Method->getFunctionObjectParameterType(); Expr::Classification FromClassification; if (const PointerType *PT = From->getType()->getAs()) { @@ -6134,6 +6264,64 @@ ExprResult Sema::PerformContextuallyConvertToObjCPointer(Expr *From) { return ExprResult(); } +static QualType GetExplicitObjectType(Sema &S, const Expr *MemExprE) { + const Expr *Base = nullptr; + assert((isa(MemExprE)) && + "expected a member expression"); + + if (const auto M = dyn_cast(MemExprE); + M && !M->isImplicitAccess()) + Base = M->getBase(); + else if (const auto M = dyn_cast(MemExprE); + M && !M->isImplicitAccess()) + Base = M->getBase(); + + QualType T = Base ? Base->getType() : S.getCurrentThisType(); + + if (T->isPointerType()) + T = T->getPointeeType(); + + return T; +} + +static Expr *GetExplicitObjectExpr(Sema &S, Expr *Obj, + const FunctionDecl *Fun) { + QualType ObjType = Obj->getType(); + if (ObjType->isPointerType()) { + ObjType = ObjType->getPointeeType(); + Obj = UnaryOperator::Create(S.getASTContext(), Obj, UO_Deref, ObjType, + VK_LValue, OK_Ordinary, SourceLocation(), + /*CanOverflow=*/false, FPOptionsOverride()); + } + if (Obj->Classify(S.getASTContext()).isPRValue()) { + Obj = S.CreateMaterializeTemporaryExpr( + ObjType, Obj, + !Fun->getParamDecl(0)->getType()->isRValueReferenceType()); + } + return Obj; +} + +ExprResult Sema::InitializeExplicitObjectArgument(Sema &S, Expr *Obj, + FunctionDecl *Fun) { + Obj = GetExplicitObjectExpr(S, Obj, Fun); + return S.PerformCopyInitialization( + InitializedEntity::InitializeParameter(S.Context, Fun->getParamDecl(0)), + Obj->getExprLoc(), Obj); +} + +static void PrepareExplicitObjectArgument(Sema &S, CXXMethodDecl *Method, + Expr *Object, MultiExprArg &Args, + SmallVectorImpl &NewArgs) { + assert(Method->isExplicitObjectMemberFunction() && + "Method is not an explicit member function"); + assert(NewArgs.empty() && "NewArgs should be empty"); + NewArgs.reserve(Args.size() + 1); + Expr *This = GetExplicitObjectExpr(S, Object, Method); + NewArgs.push_back(This); + NewArgs.append(Args.begin(), Args.end()); + Args = NewArgs; +} + /// Determine whether the provided type is an integral type, or an enumeration /// type of a permitted flavor. bool Sema::ICEConvertDiagnoser::match(QualType T) { @@ -6868,7 +7056,7 @@ static bool convertArgsForAvailabilityChecks( assert(!isa(Method) && "Shouldn't have `this` for ctors!"); assert(!Method->isStatic() && "Shouldn't have `this` for static methods!"); - ExprResult R = S.PerformObjectArgumentInitialization( + ExprResult R = S.PerformImplicitObjectArgumentInitialization( ThisArg, /*Qualifier=*/nullptr, Method, Method); if (R.isInvalid()) return false; @@ -7168,7 +7356,8 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl, Candidate.IgnoreObjectArgument = false; Candidate.ExplicitCallArguments = Args.size(); - unsigned NumParams = Proto->getNumParams(); + unsigned NumParams = Method->getNumExplicitParams(); + unsigned ExplicitOffset = Method->isExplicitObjectMemberFunction() ? 1 : 0; // (C++ 13.3.2p2): A candidate function having fewer than m // parameters is viable only if it has an ellipsis in its parameter @@ -7186,7 +7375,7 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl, // (8.3.6). For the purposes of overload resolution, the // parameter list is truncated on the right, so that there are // exactly m parameters. - unsigned MinRequiredArgs = Method->getMinRequiredArguments(); + unsigned MinRequiredArgs = Method->getMinRequiredExplicitArguments(); if (Args.size() < MinRequiredArgs && !PartialOverloading) { // Not enough arguments. Candidate.Viable = false; @@ -7215,7 +7404,7 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl, // parameter. Candidate.Conversions[FirstConvIdx] = TryObjectArgumentInitialization( *this, CandidateSet.getLocation(), ObjectType, ObjectClassification, - Method, ActingContext); + Method, ActingContext, /*InOverloadResolution=*/true); if (Candidate.Conversions[FirstConvIdx].isBad()) { Candidate.Viable = false; Candidate.FailureKind = ovl_fail_bad_conversion; @@ -7255,7 +7444,7 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl, // exist for each argument an implicit conversion sequence // (13.3.3.1) that converts that argument to the corresponding // parameter of F. - QualType ParamType = Proto->getParamType(ArgIdx); + QualType ParamType = Proto->getParamType(ArgIdx + ExplicitOffset); Candidate.Conversions[ConvIdx] = TryCopyInitialization(*this, Args[ArgIdx], ParamType, SuppressUserConversions, @@ -7320,8 +7509,8 @@ void Sema::AddMethodTemplateCandidate( ConversionSequenceList Conversions; if (TemplateDeductionResult Result = DeduceTemplateArguments( MethodTmpl, ExplicitTemplateArgs, Args, Specialization, Info, - PartialOverloading, /*AggregateDeductionCandidate=*/false, - [&](ArrayRef ParamTypes) { + PartialOverloading, /*AggregateDeductionCandidate=*/false, ObjectType, + ObjectClassification, [&](ArrayRef ParamTypes) { return CheckNonDependentConversions( MethodTmpl, ParamTypes, Args, CandidateSet, Conversions, SuppressUserConversions, ActingContext, ObjectType, @@ -7405,6 +7594,8 @@ void Sema::AddTemplateOverloadCandidate( if (TemplateDeductionResult Result = DeduceTemplateArguments( FunctionTemplate, ExplicitTemplateArgs, Args, Specialization, Info, PartialOverloading, AggregateCandidateDeduction, + /*ObjectType=*/QualType(), + /*ObjectClassification=*/Expr::Classification(), [&](ArrayRef ParamTypes) { return CheckNonDependentConversions( FunctionTemplate, ParamTypes, Args, CandidateSet, Conversions, @@ -7477,16 +7668,24 @@ bool Sema::CheckNonDependentConversions( if (HasThisConversion && !cast(FD)->isStatic() && !ObjectType.isNull()) { unsigned ConvIdx = PO == OverloadCandidateParamOrder::Reversed ? 1 : 0; - Conversions[ConvIdx] = TryObjectArgumentInitialization( - *this, CandidateSet.getLocation(), ObjectType, ObjectClassification, - Method, ActingContext); - if (Conversions[ConvIdx].isBad()) - return true; + if (!FD->hasCXXExplicitFunctionObjectParameter() || + !ParamTypes[0]->isDependentType()) { + Conversions[ConvIdx] = TryObjectArgumentInitialization( + *this, CandidateSet.getLocation(), ObjectType, ObjectClassification, + Method, ActingContext, /*InOverloadResolution=*/true, + FD->hasCXXExplicitFunctionObjectParameter() ? ParamTypes[0] + : QualType()); + if (Conversions[ConvIdx].isBad()) + return true; + } } + unsigned Offset = + Method && Method->hasCXXExplicitFunctionObjectParameter() ? 1 : 0; + for (unsigned I = 0, N = std::min(ParamTypes.size(), Args.size()); I != N; ++I) { - QualType ParamType = ParamTypes[I]; + QualType ParamType = ParamTypes[I + Offset]; if (!ParamType->isDependentType()) { unsigned ConvIdx = PO == OverloadCandidateParamOrder::Reversed ? 0 @@ -7619,15 +7818,21 @@ void Sema::AddConversionCandidate( // // Determine the implicit conversion sequence for the implicit // object parameter. - QualType ImplicitParamType = From->getType(); - if (const PointerType *FromPtrType = ImplicitParamType->getAs()) - ImplicitParamType = FromPtrType->getPointeeType(); - CXXRecordDecl *ConversionContext - = cast(ImplicitParamType->castAs()->getDecl()); - + QualType ObjectType = From->getType(); + if (const auto *FromPtrType = ObjectType->getAs()) + ObjectType = FromPtrType->getPointeeType(); + const auto *ConversionContext = + cast(ObjectType->castAs()->getDecl()); + + // C++23 [over.best.ics.general] + // However, if the target is [...] + // - the object parameter of a user-defined conversion function + // [...] user-defined conversion sequences are not considered. Candidate.Conversions[0] = TryObjectArgumentInitialization( *this, CandidateSet.getLocation(), From->getType(), - From->Classify(Context), Conversion, ConversionContext); + From->Classify(Context), Conversion, ConversionContext, + /*InOverloadResolution*/ false, /*ExplicitParameterType=*/QualType(), + /*SuppressUserConversion*/ true); if (Candidate.Conversions[0].isBad()) { Candidate.Viable = false; @@ -7781,11 +7986,14 @@ void Sema::AddTemplateConversionCandidate( return; } + QualType ObjectType = From->getType(); + Expr::Classification ObjectClassification = From->Classify(getASTContext()); + TemplateDeductionInfo Info(CandidateSet.getLocation()); CXXConversionDecl *Specialization = nullptr; - if (TemplateDeductionResult Result - = DeduceTemplateArguments(FunctionTemplate, ToType, - Specialization, Info)) { + if (TemplateDeductionResult Result = DeduceTemplateArguments( + FunctionTemplate, ObjectType, ObjectClassification, ToType, + Specialization, Info)) { OverloadCandidate &Candidate = CandidateSet.addCandidate(); Candidate.FoundDecl = FoundDecl; Candidate.Function = FunctionTemplate->getTemplatedDecl(); @@ -7837,9 +8045,18 @@ void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion, // Determine the implicit conversion sequence for the implicit // object parameter. - ImplicitConversionSequence ObjectInit = TryObjectArgumentInitialization( - *this, CandidateSet.getLocation(), Object->getType(), - Object->Classify(Context), Conversion, ActingContext); + ImplicitConversionSequence ObjectInit; + if (Conversion->hasCXXExplicitFunctionObjectParameter()) { + ObjectInit = TryCopyInitialization(*this, Object, + Conversion->getParamDecl(0)->getType(), + /*SuppressUserConversions=*/false, + /*InOverloadResolution=*/true, false); + } else { + ObjectInit = TryObjectArgumentInitialization( + *this, CandidateSet.getLocation(), Object->getType(), + Object->Classify(Context), Conversion, ActingContext); + } + if (ObjectInit.isBad()) { Candidate.Viable = false; Candidate.FailureKind = ovl_fail_bad_conversion; @@ -9865,11 +10082,7 @@ getImplicitObjectParamType(ASTContext &Context, const FunctionDecl *F) { // Static member functions' object parameters match all types. if (M->isStatic()) return QualType(); - - QualType T = M->getThisObjectType(); - if (M->getRefQualifier() == RQ_RValue) - return Context.getRValueReferenceType(T); - return Context.getLValueReferenceType(T); + return M->getFunctionObjectParameterReferenceType(); } static bool haveSameParameterTypes(ASTContext &Context, const FunctionDecl *F1, @@ -10227,6 +10440,21 @@ bool clang::isBetterOverloadCandidate( // -- F1 is the copy deduction candidate(16.3.1.8) and F2 is not if (Guide1->getDeductionCandidateKind() == DeductionCandidate::Copy) return true; + if (Guide2->getDeductionCandidateKind() == DeductionCandidate::Copy) + return false; + + // --F1 is generated from a non-template constructor and F2 is generated + // from a constructor template + const auto *Constructor1 = Guide1->getCorrespondingConstructor(); + const auto *Constructor2 = Guide2->getCorrespondingConstructor(); + if (Constructor1 && Constructor2) { + bool isC1Templated = Constructor1->getTemplatedKind() != + FunctionDecl::TemplatedKind::TK_NonTemplate; + bool isC2Templated = Constructor2->getTemplatedKind() != + FunctionDecl::TemplatedKind::TK_NonTemplate; + if (isC1Templated != isC2Templated) + return isC2Templated; + } } } @@ -10270,7 +10498,7 @@ bool clang::isBetterOverloadCandidate( if (AS1 != AS2) { if (Qualifiers::isAddressSpaceSupersetOf(AS2, AS1)) return true; - if (Qualifiers::isAddressSpaceSupersetOf(AS2, AS1)) + if (Qualifiers::isAddressSpaceSupersetOf(AS1, AS2)) return false; } } @@ -11072,39 +11300,43 @@ static void DiagnoseArityMismatch(Sema &S, NamedDecl *Found, Decl *D, // TODO: treat calls to a missing default constructor as a special case const auto *FnTy = Fn->getType()->castAs(); - unsigned MinParams = Fn->getMinRequiredArguments(); + unsigned MinParams = Fn->getMinRequiredExplicitArguments(); // at least / at most / exactly + bool HasExplicitObjectParam = Fn->hasCXXExplicitFunctionObjectParameter(); + unsigned ParamCount = FnTy->getNumParams() - (HasExplicitObjectParam ? 1 : 0); unsigned mode, modeCount; if (NumFormalArgs < MinParams) { - if (MinParams != FnTy->getNumParams() || FnTy->isVariadic() || + if (MinParams != ParamCount || FnTy->isVariadic() || FnTy->isTemplateVariadic()) mode = 0; // "at least" else mode = 2; // "exactly" modeCount = MinParams; } else { - if (MinParams != FnTy->getNumParams()) + if (MinParams != ParamCount) mode = 1; // "at most" else mode = 2; // "exactly" - modeCount = FnTy->getNumParams(); + modeCount = ParamCount; } std::string Description; std::pair FnKindPair = ClassifyOverloadCandidate(S, Found, Fn, CRK_None, Description); - if (modeCount == 1 && Fn->getParamDecl(0)->getDeclName()) + if (modeCount == 1 && + Fn->getParamDecl(HasExplicitObjectParam ? 1 : 0)->getDeclName()) S.Diag(Fn->getLocation(), diag::note_ovl_candidate_arity_one) << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second - << Description << mode << Fn->getParamDecl(0) << NumFormalArgs - << Fn->getParametersSourceRange(); + << Description << mode + << Fn->getParamDecl(HasExplicitObjectParam ? 1 : 0) << NumFormalArgs + << HasExplicitObjectParam << Fn->getParametersSourceRange(); else S.Diag(Fn->getLocation(), diag::note_ovl_candidate_arity) << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << Description << mode << modeCount << NumFormalArgs - << Fn->getParametersSourceRange(); + << HasExplicitObjectParam << Fn->getParametersSourceRange(); MaybeEmitInheritedConstructorNote(S, Found); } @@ -12448,7 +12680,9 @@ class AddressOfFunctionResolver { = dyn_cast(FunctionTemplate->getTemplatedDecl())) { // Skip non-static function templates when converting to pointer, and // static when converting to member pointer. - if (Method->isStatic() == TargetTypeIsNonStaticMemberFunction) + bool CanConvertToFunctionPointer = + Method->isStatic() || Method->isExplicitObjectMemberFunction(); + if (CanConvertToFunctionPointer == TargetTypeIsNonStaticMemberFunction) return false; } else if (TargetTypeIsNonStaticMemberFunction) @@ -12493,7 +12727,9 @@ class AddressOfFunctionResolver { if (CXXMethodDecl *Method = dyn_cast(Fn)) { // Skip non-static functions when converting to pointer, and static // when converting to member pointer. - if (Method->isStatic() == TargetTypeIsNonStaticMemberFunction) + bool CanConvertToFunctionPointer = + Method->isStatic() || Method->isExplicitObjectMemberFunction(); + if (CanConvertToFunctionPointer == TargetTypeIsNonStaticMemberFunction) return false; } else if (TargetTypeIsNonStaticMemberFunction) @@ -12895,7 +13131,10 @@ bool Sema::resolveAndFixAddressOfSingleOverloadCandidate( // for both. DiagnoseUseOfDecl(Found, E->getExprLoc()); CheckAddressOfMemberAccess(E, DAP); - Expr *Fixed = FixOverloadedFunctionReference(E, DAP, Found); + ExprResult Res = FixOverloadedFunctionReference(E, DAP, Found); + if (Res.isInvalid()) + return false; + Expr *Fixed = Res.get(); if (DoFunctionPointerConversion && Fixed->getType()->isFunctionType()) SrcExpr = DefaultFunctionArrayConversion(Fixed, /*Diagnose=*/false); else @@ -13557,10 +13796,13 @@ static ExprResult FinishOverloadedCallExpr(Sema &SemaRef, Scope *S, Expr *Fn, SemaRef.CheckUnresolvedLookupAccess(ULE, (*Best)->FoundDecl); if (SemaRef.DiagnoseUseOfDecl(FDecl, ULE->getNameLoc())) return ExprError(); - Fn = SemaRef.FixOverloadedFunctionReference(Fn, (*Best)->FoundDecl, FDecl); - return SemaRef.BuildResolvedCallExpr(Fn, FDecl, LParenLoc, Args, RParenLoc, - ExecConfig, /*IsExecConfig=*/false, - (*Best)->IsADLCandidate); + ExprResult Res = + SemaRef.FixOverloadedFunctionReference(Fn, (*Best)->FoundDecl, FDecl); + if (Res.isInvalid()) + return ExprError(); + return SemaRef.BuildResolvedCallExpr( + Res.get(), FDecl, LParenLoc, Args, RParenLoc, ExecConfig, + /*IsExecConfig=*/false, (*Best)->IsADLCandidate); } case OR_No_Viable_Function: { @@ -13615,10 +13857,13 @@ static ExprResult FinishOverloadedCallExpr(Sema &SemaRef, Scope *S, Expr *Fn, // We emitted an error for the unavailable/deleted function call but keep // the call in the AST. FunctionDecl *FDecl = (*Best)->Function; - Fn = SemaRef.FixOverloadedFunctionReference(Fn, (*Best)->FoundDecl, FDecl); - return SemaRef.BuildResolvedCallExpr(Fn, FDecl, LParenLoc, Args, RParenLoc, - ExecConfig, /*IsExecConfig=*/false, - (*Best)->IsADLCandidate); + ExprResult Res = + SemaRef.FixOverloadedFunctionReference(Fn, (*Best)->FoundDecl, FDecl); + if (Res.isInvalid()) + return ExprError(); + return SemaRef.BuildResolvedCallExpr( + Res.get(), FDecl, LParenLoc, Args, RParenLoc, ExecConfig, + /*IsExecConfig=*/false, (*Best)->IsADLCandidate); } } @@ -13692,6 +13937,83 @@ ExprResult Sema::CreateUnresolvedLookupExpr(CXXRecordDecl *NamingClass, Fns.begin(), Fns.end()); } +ExprResult Sema::BuildCXXMemberCallExpr(Expr *E, NamedDecl *FoundDecl, + CXXConversionDecl *Method, + bool HadMultipleCandidates) { + // Convert the expression to match the conversion function's implicit object + // parameter. + ExprResult Exp; + if (Method->isExplicitObjectMemberFunction()) + Exp = InitializeExplicitObjectArgument(*this, E, Method); + else + Exp = PerformImplicitObjectArgumentInitialization(E, /*Qualifier=*/nullptr, + FoundDecl, Method); + if (Exp.isInvalid()) + return true; + + if (Method->getParent()->isLambda() && + Method->getConversionType()->isBlockPointerType()) { + // This is a lambda conversion to block pointer; check if the argument + // was a LambdaExpr. + Expr *SubE = E; + auto *CE = dyn_cast(SubE); + if (CE && CE->getCastKind() == CK_NoOp) + SubE = CE->getSubExpr(); + SubE = SubE->IgnoreParens(); + if (auto *BE = dyn_cast(SubE)) + SubE = BE->getSubExpr(); + if (isa(SubE)) { + // For the conversion to block pointer on a lambda expression, we + // construct a special BlockLiteral instead; this doesn't really make + // a difference in ARC, but outside of ARC the resulting block literal + // follows the normal lifetime rules for block literals instead of being + // autoreleased. + PushExpressionEvaluationContext( + ExpressionEvaluationContext::PotentiallyEvaluated); + ExprResult BlockExp = BuildBlockForLambdaConversion( + Exp.get()->getExprLoc(), Exp.get()->getExprLoc(), Method, Exp.get()); + PopExpressionEvaluationContext(); + + // FIXME: This note should be produced by a CodeSynthesisContext. + if (BlockExp.isInvalid()) + Diag(Exp.get()->getExprLoc(), diag::note_lambda_to_block_conv); + return BlockExp; + } + } + CallExpr *CE; + QualType ResultType = Method->getReturnType(); + ExprValueKind VK = Expr::getValueKindForType(ResultType); + ResultType = ResultType.getNonLValueExprType(Context); + if (Method->isExplicitObjectMemberFunction()) { + ExprResult FnExpr = + CreateFunctionRefExpr(*this, Method, FoundDecl, Exp.get(), + HadMultipleCandidates, E->getBeginLoc()); + if (FnExpr.isInvalid()) + return ExprError(); + Expr *ObjectParam = Exp.get(); + CE = CallExpr::Create(Context, FnExpr.get(), MultiExprArg(&ObjectParam, 1), + ResultType, VK, Exp.get()->getEndLoc(), + CurFPFeatureOverrides()); + } else { + MemberExpr *ME = + BuildMemberExpr(Exp.get(), /*IsArrow=*/false, SourceLocation(), + NestedNameSpecifierLoc(), SourceLocation(), Method, + DeclAccessPair::make(FoundDecl, FoundDecl->getAccess()), + HadMultipleCandidates, DeclarationNameInfo(), + Context.BoundMemberTy, VK_PRValue, OK_Ordinary); + + CE = CXXMemberCallExpr::Create(Context, ME, /*Args=*/{}, ResultType, VK, + Exp.get()->getEndLoc(), + CurFPFeatureOverrides()); + } + + if (CheckFunctionCall(Method, CE, + Method->getType()->castAs())) + return ExprError(); + + return CheckForImmediateInvocation(CE, CE->getDirectCallee()); +} + /// Create a unary operation that may resolve to an overloaded /// operator. /// @@ -13786,14 +14108,17 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, // Convert the arguments. if (CXXMethodDecl *Method = dyn_cast(FnDecl)) { - CheckMemberOperatorAccess(OpLoc, Args[0], nullptr, Best->FoundDecl); + CheckMemberOperatorAccess(OpLoc, Input, nullptr, Best->FoundDecl); - ExprResult InputRes = - PerformObjectArgumentInitialization(Input, /*Qualifier=*/nullptr, - Best->FoundDecl, Method); - if (InputRes.isInvalid()) + ExprResult InputInit; + if (Method->isExplicitObjectMemberFunction()) + InputInit = InitializeExplicitObjectArgument(*this, Input, Method); + else + InputInit = PerformImplicitObjectArgumentInitialization( + Input, /*Qualifier=*/nullptr, Best->FoundDecl, Method); + if (InputInit.isInvalid()) return ExprError(); - Base = Input = InputRes.get(); + Base = Input = InputInit.get(); } else { // Convert the arguments. ExprResult InputInit @@ -14127,13 +14452,16 @@ ExprResult Sema::CreateOverloadedBinOp(SourceLocation OpLoc, if (auto *MD = dyn_cast(FnDecl)) if (Op == OverloadedOperatorKind::OO_EqualEqual && !MD->isConst() && + !MD->hasCXXExplicitFunctionObjectParameter() && Context.hasSameUnqualifiedType( - MD->getThisObjectType(), + MD->getFunctionObjectParameterType(), MD->getParamDecl(0)->getType().getNonReferenceType()) && - Context.hasSameUnqualifiedType(MD->getThisObjectType(), - Args[0]->getType()) && - Context.hasSameUnqualifiedType(MD->getThisObjectType(), - Args[1]->getType())) + Context.hasSameUnqualifiedType( + MD->getFunctionObjectParameterType(), + Args[0]->getType()) && + Context.hasSameUnqualifiedType( + MD->getFunctionObjectParameterType(), + Args[1]->getType())) Diag(FnDecl->getLocation(), diag::note_ovl_ambiguous_eqeq_reversed_self_non_const); } else { @@ -14151,19 +14479,22 @@ ExprResult Sema::CreateOverloadedBinOp(SourceLocation OpLoc, // Best->Access is only meaningful for class members. CheckMemberOperatorAccess(OpLoc, Args[0], Args[1], Best->FoundDecl); - ExprResult Arg1 = - PerformCopyInitialization( - InitializedEntity::InitializeParameter(Context, - FnDecl->getParamDecl(0)), + ExprResult Arg0, Arg1; + unsigned ParamIdx = 0; + if (Method->isExplicitObjectMemberFunction()) { + Arg0 = InitializeExplicitObjectArgument(*this, Args[0], FnDecl); + ParamIdx = 1; + } else { + Arg0 = PerformImplicitObjectArgumentInitialization( + Args[0], /*Qualifier=*/nullptr, Best->FoundDecl, Method); + } + Arg1 = PerformCopyInitialization( + InitializedEntity::InitializeParameter( + Context, FnDecl->getParamDecl(ParamIdx)), SourceLocation(), Args[1]); - if (Arg1.isInvalid()) + if (Arg0.isInvalid() || Arg1.isInvalid()) return ExprError(); - ExprResult Arg0 = - PerformObjectArgumentInitialization(Args[0], /*Qualifier=*/nullptr, - Best->FoundDecl, Method); - if (Arg0.isInvalid()) - return ExprError(); Base = Args[0] = Arg0.getAs(); Args[1] = RHS = Arg1.getAs(); } else { @@ -14198,22 +14529,27 @@ ExprResult Sema::CreateOverloadedBinOp(SourceLocation OpLoc, ExprValueKind VK = Expr::getValueKindForType(ResultTy); ResultTy = ResultTy.getNonLValueExprType(Context); - CXXOperatorCallExpr *TheCall = CXXOperatorCallExpr::Create( + CallExpr *TheCall; + ArrayRef ArgsArray(Args, 2); + const Expr *ImplicitThis = nullptr; + + // We always create a CXXOperatorCallExpr, even for explicit object + // members; CodeGen should take care not to emit the this pointer. + TheCall = CXXOperatorCallExpr::Create( Context, ChosenOp, FnExpr.get(), Args, ResultTy, VK, OpLoc, CurFPFeatureOverrides(), Best->IsADLCandidate); - if (CheckCallReturnType(FnDecl->getReturnType(), OpLoc, TheCall, - FnDecl)) - return ExprError(); - - ArrayRef ArgsArray(Args, 2); - const Expr *ImplicitThis = nullptr; - // Cut off the implicit 'this'. - if (isa(FnDecl)) { + if (const auto *Method = dyn_cast(FnDecl); + Method && Method->isImplicitObjectMemberFunction()) { + // Cut off the implicit 'this'. ImplicitThis = ArgsArray[0]; ArgsArray = ArgsArray.slice(1); } + if (CheckCallReturnType(FnDecl->getReturnType(), OpLoc, TheCall, + FnDecl)) + return ExprError(); + // Check for a self move. if (Op == OO_Equal) DiagnoseSelfMove(Args[0], Args[1], OpLoc); @@ -14221,7 +14557,7 @@ ExprResult Sema::CreateOverloadedBinOp(SourceLocation OpLoc, if (ImplicitThis) { QualType ThisType = Context.getPointerType(ImplicitThis->getType()); QualType ThisTypeFromDecl = Context.getPointerType( - cast(FnDecl)->getThisObjectType()); + cast(FnDecl)->getFunctionObjectParameterType()); CheckArgAlignment(OpLoc, FnDecl, "'this'", ThisType, ThisTypeFromDecl); @@ -14600,8 +14936,15 @@ ExprResult Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, SmallVector MethodArgs; // Handle 'this' parameter if the selected function is not static. - if (Method->isInstance()) { - ExprResult Arg0 = PerformObjectArgumentInitialization( + if (Method->isExplicitObjectMemberFunction()) { + ExprResult Res = + InitializeExplicitObjectArgument(*this, Args[0], Method); + if (Res.isInvalid()) + return ExprError(); + Args[0] = Res.get(); + ArgExpr = Args; + } else if (Method->isInstance()) { + ExprResult Arg0 = PerformImplicitObjectArgumentInitialization( Args[0], /*Qualifier=*/nullptr, Best->FoundDecl, Method); if (Arg0.isInvalid()) return ExprError(); @@ -14803,6 +15146,7 @@ ExprResult Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, MemberExpr *MemExpr; CXXMethodDecl *Method = nullptr; + bool HadMultipleCandidates = false; DeclAccessPair FoundDecl = DeclAccessPair::make(nullptr, AS_public); NestedNameSpecifier *Qualifier = nullptr; if (isa(NakedMemExpr)) { @@ -14834,11 +15178,24 @@ ExprResult Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, for (UnresolvedMemberExpr::decls_iterator I = UnresExpr->decls_begin(), E = UnresExpr->decls_end(); I != E; ++I) { + QualType ExplicitObjectType = ObjectType; + NamedDecl *Func = *I; CXXRecordDecl *ActingDC = cast(Func->getDeclContext()); if (isa(Func)) Func = cast(Func)->getTargetDecl(); + bool HasExplicitParameter = false; + if (const auto *M = dyn_cast(Func); + M && M->hasCXXExplicitFunctionObjectParameter()) + HasExplicitParameter = true; + else if (const auto *M = dyn_cast(Func); + M && + M->getTemplatedDecl()->hasCXXExplicitFunctionObjectParameter()) + HasExplicitParameter = true; + + if (HasExplicitParameter) + ExplicitObjectType = GetExplicitObjectType(*this, UnresExpr); // Microsoft supports direct constructor calls. if (getLangOpts().MicrosoftExt && isa(Func)) { @@ -14851,17 +15208,20 @@ ExprResult Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, if (TemplateArgs) continue; - AddMethodCandidate(Method, I.getPair(), ActingDC, ObjectType, + AddMethodCandidate(Method, I.getPair(), ActingDC, ExplicitObjectType, ObjectClassification, Args, CandidateSet, /*SuppressUserConversions=*/false); } else { - AddMethodTemplateCandidate( - cast(Func), I.getPair(), ActingDC, - TemplateArgs, ObjectType, ObjectClassification, Args, CandidateSet, - /*SuppressUserConversions=*/false); + AddMethodTemplateCandidate(cast(Func), + I.getPair(), ActingDC, TemplateArgs, + ExplicitObjectType, ObjectClassification, + Args, CandidateSet, + /*SuppressUserConversions=*/false); } } + HadMultipleCandidates = (CandidateSet.size() > 1); + DeclarationName DeclName = UnresExpr->getMemberName(); UnbridgedCasts.restore(); @@ -14915,10 +15275,14 @@ ExprResult Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, if (!Succeeded) return BuildRecoveryExpr(chooseRecoveryType(CandidateSet, &Best)); - MemExprE = FixOverloadedFunctionReference(MemExprE, FoundDecl, Method); + ExprResult Res = + FixOverloadedFunctionReference(MemExprE, FoundDecl, Method); + if (Res.isInvalid()) + return ExprError(); + MemExprE = Res.get(); - // If overload resolution picked a static member, build a - // non-member call based on that function. + // If overload resolution picked a static member + // build a non-member call based on that function. if (Method->isStatic()) { return BuildResolvedCallExpr(MemExprE, Method, LParenLoc, Args, RParenLoc, ExecConfig, IsExecConfig); @@ -14933,27 +15297,41 @@ ExprResult Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, assert(Method && "Member call to something that isn't a method?"); const auto *Proto = Method->getType()->castAs(); - CXXMemberCallExpr *TheCall = CXXMemberCallExpr::Create( - Context, MemExprE, Args, ResultType, VK, RParenLoc, - CurFPFeatureOverrides(), Proto->getNumParams()); - // Check for a valid return type. - if (CheckCallReturnType(Method->getReturnType(), MemExpr->getMemberLoc(), - TheCall, Method)) - return BuildRecoveryExpr(ResultType); + CallExpr *TheCall = nullptr; + llvm::SmallVector NewArgs; + if (Method->isExplicitObjectMemberFunction()) { + PrepareExplicitObjectArgument(*this, Method, MemExpr->getBase(), Args, + NewArgs); + // Build the actual expression node. + ExprResult FnExpr = + CreateFunctionRefExpr(*this, Method, FoundDecl, MemExpr, + HadMultipleCandidates, MemExpr->getExprLoc()); + if (FnExpr.isInvalid()) + return ExprError(); - // Convert the object argument (for a non-static member function call). - // We only need to do this if there was actually an overload; otherwise - // it was done at lookup. - if (!Method->isStatic()) { - ExprResult ObjectArg = - PerformObjectArgumentInitialization(MemExpr->getBase(), Qualifier, - FoundDecl, Method); + TheCall = + CallExpr::Create(Context, FnExpr.get(), Args, ResultType, VK, RParenLoc, + CurFPFeatureOverrides(), Proto->getNumParams()); + } else { + // Convert the object argument (for a non-static member function call). + // We only need to do this if there was actually an overload; otherwise + // it was done at lookup. + ExprResult ObjectArg = PerformImplicitObjectArgumentInitialization( + MemExpr->getBase(), Qualifier, FoundDecl, Method); if (ObjectArg.isInvalid()) return ExprError(); MemExpr->setBase(ObjectArg.get()); + TheCall = CXXMemberCallExpr::Create(Context, MemExprE, Args, ResultType, VK, + RParenLoc, CurFPFeatureOverrides(), + Proto->getNumParams()); } + // Check for a valid return type. + if (CheckCallReturnType(Method->getReturnType(), MemExpr->getMemberLoc(), + TheCall, Method)) + return BuildRecoveryExpr(ResultType); + // Convert the rest of the arguments if (ConvertArgumentsForCall(TheCall, MemExpr, Method, Proto, Args, RParenLoc)) @@ -14980,10 +15358,9 @@ ExprResult Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, } } - if ((isa(CurContext) || - isa(CurContext)) && - TheCall->getMethodDecl()->isPure()) { - const CXXMethodDecl *MD = TheCall->getMethodDecl(); + if (isa(CurContext) && + TheCall->getDirectCallee()->isPure()) { + const FunctionDecl *MD = TheCall->getDirectCallee(); if (isa(MemExpr->getBase()->IgnoreParenCasts()) && MemExpr->performsVirtualDispatch(getLangOpts())) { @@ -14999,8 +15376,7 @@ ExprResult Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, } } - if (CXXDestructorDecl *DD = - dyn_cast(TheCall->getMethodDecl())) { + if (auto *DD = dyn_cast(TheCall->getDirectCallee())) { // a->A::f() doesn't go through the vtable, except in AppleKext mode. bool CallCanBeVirtual = !MemExpr->hasQualifier() || getLangOpts().AppleKext; CheckVirtualDtorCall(DD, MemExpr->getBeginLoc(), /*IsDelete=*/false, @@ -15009,7 +15385,7 @@ ExprResult Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, } return CheckForImmediateInvocation(MaybeBindToTemporary(TheCall), - TheCall->getMethodDecl()); + TheCall->getDirectCallee()); } /// BuildCallToObjectOfClassType - Build a call to an object of class @@ -15234,8 +15610,13 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, // Initialize the implicit object parameter if needed. // Since C++23, this could also be a call to a static call operator // which we emit as a regular CallExpr. - if (Method->isInstance()) { - ExprResult ObjRes = PerformObjectArgumentInitialization( + llvm::SmallVector NewArgs; + if (Method->isExplicitObjectMemberFunction()) { + // FIXME: we should do that during the definition of the lambda when we can. + DiagnoseInvalidExplicitObjectParameterInLambda(Method); + PrepareExplicitObjectArgument(*this, Method, Obj, Args, NewArgs); + } else if (Method->isInstance()) { + ExprResult ObjRes = PerformImplicitObjectArgumentInitialization( Object.get(), /*Qualifier=*/nullptr, Best->FoundDecl, Method); if (ObjRes.isInvalid()) IsError = true; @@ -15377,12 +15758,19 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc, // Convert the object parameter. CXXMethodDecl *Method = cast(Best->Function); - ExprResult BaseResult = - PerformObjectArgumentInitialization(Base, /*Qualifier=*/nullptr, - Best->FoundDecl, Method); - if (BaseResult.isInvalid()) - return ExprError(); - Base = BaseResult.get(); + + if (Method->isExplicitObjectMemberFunction()) { + ExprResult R = InitializeExplicitObjectArgument(*this, Base, Method); + if (R.isInvalid()) + return ExprError(); + Base = R.get(); + } else { + ExprResult BaseResult = PerformImplicitObjectArgumentInitialization( + Base, /*Qualifier=*/nullptr, Best->FoundDecl, Method); + if (BaseResult.isInvalid()) + return ExprError(); + Base = BaseResult.get(); + } // Build the operator call. ExprResult FnExpr = CreateFunctionRefExpr(*this, Method, Best->FoundDecl, @@ -15393,7 +15781,8 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc, QualType ResultTy = Method->getReturnType(); ExprValueKind VK = Expr::getValueKindForType(ResultTy); ResultTy = ResultTy.getNonLValueExprType(Context); - CXXOperatorCallExpr *TheCall = + + CallExpr *TheCall = CXXOperatorCallExpr::Create(Context, OO_Arrow, FnExpr.get(), Base, ResultTy, VK, OpLoc, CurFPFeatureOverrides()); @@ -15559,37 +15948,44 @@ Sema::BuildForRangeBeginEndCall(SourceLocation Loc, /// perhaps a '&' around it). We have resolved the overloaded function /// to the function declaration Fn, so patch up the expression E to /// refer (possibly indirectly) to Fn. Returns the new expr. -Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found, - FunctionDecl *Fn) { +ExprResult Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found, + FunctionDecl *Fn) { if (ParenExpr *PE = dyn_cast(E)) { - Expr *SubExpr = FixOverloadedFunctionReference(PE->getSubExpr(), - Found, Fn); - if (SubExpr == PE->getSubExpr()) + ExprResult SubExpr = + FixOverloadedFunctionReference(PE->getSubExpr(), Found, Fn); + if (SubExpr.isInvalid()) + return ExprError(); + if (SubExpr.get() == PE->getSubExpr()) return PE; - return new (Context) ParenExpr(PE->getLParen(), PE->getRParen(), SubExpr); + return new (Context) + ParenExpr(PE->getLParen(), PE->getRParen(), SubExpr.get()); } if (ImplicitCastExpr *ICE = dyn_cast(E)) { - Expr *SubExpr = FixOverloadedFunctionReference(ICE->getSubExpr(), - Found, Fn); + ExprResult SubExpr = + FixOverloadedFunctionReference(ICE->getSubExpr(), Found, Fn); + if (SubExpr.isInvalid()) + return ExprError(); assert(Context.hasSameType(ICE->getSubExpr()->getType(), - SubExpr->getType()) && + SubExpr.get()->getType()) && "Implicit cast type cannot be determined from overload"); assert(ICE->path_empty() && "fixing up hierarchy conversion?"); - if (SubExpr == ICE->getSubExpr()) + if (SubExpr.get() == ICE->getSubExpr()) return ICE; return ImplicitCastExpr::Create(Context, ICE->getType(), ICE->getCastKind(), - SubExpr, nullptr, ICE->getValueKind(), + SubExpr.get(), nullptr, ICE->getValueKind(), CurFPFeatureOverrides()); } if (auto *GSE = dyn_cast(E)) { if (!GSE->isResultDependent()) { - Expr *SubExpr = + ExprResult SubExpr = FixOverloadedFunctionReference(GSE->getResultExpr(), Found, Fn); - if (SubExpr == GSE->getResultExpr()) + if (SubExpr.isInvalid()) + return ExprError(); + if (SubExpr.get() == GSE->getResultExpr()) return GSE; // Replace the resulting type information before rebuilding the generic @@ -15597,7 +15993,7 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found, ArrayRef A = GSE->getAssocExprs(); SmallVector AssocExprs(A.begin(), A.end()); unsigned ResultIdx = GSE->getResultIndex(); - AssocExprs[ResultIdx] = SubExpr; + AssocExprs[ResultIdx] = SubExpr.get(); if (GSE->isExprPredicate()) return GenericSelectionExpr::Create( @@ -15627,15 +16023,21 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found, // Fix the subexpression, which really has to be an // UnresolvedLookupExpr holding an overloaded member function // or template. - Expr *SubExpr = FixOverloadedFunctionReference(UnOp->getSubExpr(), - Found, Fn); - if (SubExpr == UnOp->getSubExpr()) + ExprResult SubExpr = + FixOverloadedFunctionReference(UnOp->getSubExpr(), Found, Fn); + if (SubExpr.isInvalid()) + return ExprError(); + if (SubExpr.get() == UnOp->getSubExpr()) return UnOp; - assert(isa(SubExpr) - && "fixed to something other than a decl ref"); - assert(cast(SubExpr)->getQualifier() - && "fixed to a member ref with no nested name qualifier"); + if (CheckUseOfCXXMethodAsAddressOfOperand(UnOp->getBeginLoc(), + SubExpr.get(), Method)) + return ExprError(); + + assert(isa(SubExpr.get()) && + "fixed to something other than a decl ref"); + assert(cast(SubExpr.get())->getQualifier() && + "fixed to a member ref with no nested name qualifier"); // We have taken the address of a pointer to member // function. Perform the computation here so that we get the @@ -15648,19 +16050,21 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found, if (Context.getTargetInfo().getCXXABI().isMicrosoft()) (void)isCompleteType(UnOp->getOperatorLoc(), MemPtrType); - return UnaryOperator::Create( - Context, SubExpr, UO_AddrOf, MemPtrType, VK_PRValue, OK_Ordinary, - UnOp->getOperatorLoc(), false, CurFPFeatureOverrides()); + return UnaryOperator::Create(Context, SubExpr.get(), UO_AddrOf, + MemPtrType, VK_PRValue, OK_Ordinary, + UnOp->getOperatorLoc(), false, + CurFPFeatureOverrides()); } } - Expr *SubExpr = FixOverloadedFunctionReference(UnOp->getSubExpr(), - Found, Fn); - if (SubExpr == UnOp->getSubExpr()) + ExprResult SubExpr = + FixOverloadedFunctionReference(UnOp->getSubExpr(), Found, Fn); + if (SubExpr.isInvalid()) + return ExprError(); + if (SubExpr.get() == UnOp->getSubExpr()) return UnOp; - // FIXME: This can't currently fail, but in principle it could. - return CreateBuiltinUnaryOp(UnOp->getOperatorLoc(), UO_AddrOf, SubExpr) - .get(); + return CreateBuiltinUnaryOp(UnOp->getOperatorLoc(), UO_AddrOf, + SubExpr.get()); } if (UnresolvedLookupExpr *ULE = dyn_cast(E)) { diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index 10adfbc406dfbb..333226963aeac5 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -689,7 +689,7 @@ bool Sema::checkMustTailAttr(const Stmt *St, const Attr &MTA) { if (CMD->isStatic()) Type.MemberType = FuncType::ft_static_member; else { - Type.This = CMD->getThisObjectType(); + Type.This = CMD->getFunctionObjectParameterType(); Type.MemberType = FuncType::ft_non_static_member; } Type.Func = CMD->getType()->castAs(); diff --git a/clang/lib/Sema/SemaStmtAsm.cpp b/clang/lib/Sema/SemaStmtAsm.cpp index 2acb269f042399..83351b703c1536 100644 --- a/clang/lib/Sema/SemaStmtAsm.cpp +++ b/clang/lib/Sema/SemaStmtAsm.cpp @@ -271,7 +271,8 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, OutputName = Names[i]->getName(); TargetInfo::ConstraintInfo Info(Literal->getString(), OutputName); - if (!Context.getTargetInfo().validateOutputConstraint(Info)) { + if (!Context.getTargetInfo().validateOutputConstraint(Info) && + !(LangOpts.HIPStdPar && LangOpts.CUDAIsDevice)) { targetDiag(Literal->getBeginLoc(), diag::err_asm_invalid_output_constraint) << Info.getConstraintStr(); diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 994d89e25b3848..080f005e04402c 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -753,7 +753,8 @@ Sema::ActOnDependentIdExpression(const CXXScopeSpec &SS, IsEnum = isa_and_nonnull(NNS->getAsType()); if (!MightBeCxx11UnevalField && !isAddressOfOperand && !IsEnum && - isa(DC) && cast(DC)->isInstance()) { + isa(DC) && + cast(DC)->isImplicitObjectMemberFunction()) { QualType ThisType = cast(DC)->getThisType().getNonReferenceType(); // Since the 'this' expression is synthesized, we don't need to @@ -7079,7 +7080,8 @@ CheckTemplateArgumentPointerToMember(Sema &S, NonTypeTemplateParmDecl *Param, isa(DRE->getDecl())) { assert((isa(DRE->getDecl()) || isa(DRE->getDecl()) || - !cast(DRE->getDecl())->isStatic()) && + cast(DRE->getDecl()) + ->isImplicitObjectMemberFunction()) && "Only non-static member pointers can make it here"); // Okay: this is the address of a non-static member, and therefore @@ -7631,7 +7633,10 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, if (DiagnoseUseOfDecl(Fn, Arg->getBeginLoc())) return ExprError(); - Arg = FixOverloadedFunctionReference(Arg, FoundResult, Fn); + ExprResult Res = FixOverloadedFunctionReference(Arg, FoundResult, Fn); + if (Res.isInvalid()) + return ExprError(); + Arg = Res.get(); ArgType = Arg->getType(); } else return ExprError(); @@ -7682,8 +7687,10 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, FoundResult)) { if (DiagnoseUseOfDecl(Fn, Arg->getBeginLoc())) return ExprError(); - - Arg = FixOverloadedFunctionReference(Arg, FoundResult, Fn); + ExprResult Res = FixOverloadedFunctionReference(Arg, FoundResult, Fn); + if (Res.isInvalid()) + return ExprError(); + Arg = Res.get(); ArgType = Arg->getType(); } else return ExprError(); diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index 31ea7be2975e49..62fbd903a04044 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -1905,11 +1905,11 @@ static Sema::TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch( QualType PPT = MPP->getPointeeType(); if (PPT->isFunctionType()) - S.adjustMemberFunctionCC(PPT, /*IsStatic=*/true, + S.adjustMemberFunctionCC(PPT, /*HasThisPointer=*/false, /*IsCtorOrDtor=*/false, Info.getLocation()); QualType APT = MPA->getPointeeType(); if (APT->isFunctionType()) - S.adjustMemberFunctionCC(APT, /*IsStatic=*/true, + S.adjustMemberFunctionCC(APT, /*HasThisPointer=*/false, /*IsCtorOrDtor=*/false, Info.getLocation()); unsigned SubTDF = TDF & TDF_IgnoreQualifiers; @@ -3685,7 +3685,9 @@ Sema::TemplateDeductionResult Sema::FinishTemplateArgumentDeduction( OriginalCallArg OriginalArg = (*OriginalCallArgs)[I]; auto ParamIdx = OriginalArg.ArgIdx; - if (ParamIdx >= Specialization->getNumParams()) + unsigned ExplicitOffset = + Specialization->hasCXXExplicitFunctionObjectParameter() ? 1 : 0; + if (ParamIdx >= Specialization->getNumParams() - ExplicitOffset) // FIXME: This presumably means a pack ended up smaller than we // expected while deducing. Should this not result in deduction // failure? Can it even happen? @@ -3695,7 +3697,8 @@ Sema::TemplateDeductionResult Sema::FinishTemplateArgumentDeduction( if (!OriginalArg.DecomposedParam) { // P is one of the function parameters, just look up its substituted // type. - DeducedA = Specialization->getParamDecl(ParamIdx)->getType(); + DeducedA = + Specialization->getParamDecl(ParamIdx + ExplicitOffset)->getType(); } else { // P is a decomposed element of a parameter corresponding to a // braced-init-list argument. Substitute back into P to find the @@ -3745,7 +3748,7 @@ static QualType GetTypeOfFunction(Sema &S, const OverloadExpr::FindResult &R, return {}; if (CXXMethodDecl *Method = dyn_cast(Fn)) - if (Method->isInstance()) { + if (Method->isImplicitObjectMemberFunction()) { // An instance method that's referenced in a form that doesn't // look like a member pointer is just invalid. if (!R.HasFormOfMemberPointer) @@ -3874,7 +3877,8 @@ ResolveOverloadForDeduction(Sema &S, TemplateParameterList *TemplateParams, /// overloaded function set that could not be resolved. static bool AdjustFunctionParmAndArgTypesForDeduction( Sema &S, TemplateParameterList *TemplateParams, unsigned FirstInnerIndex, - QualType &ParamType, QualType &ArgType, Expr *Arg, unsigned &TDF, + QualType &ParamType, QualType &ArgType, + Expr::Classification ArgClassification, Expr *Arg, unsigned &TDF, TemplateSpecCandidateSet *FailedTSC = nullptr) { // C++0x [temp.deduct.call]p3: // If P is a cv-qualified type, the top level cv-qualifiers of P's type @@ -3892,6 +3896,7 @@ static bool AdjustFunctionParmAndArgTypesForDeduction( // but there are sometimes special circumstances. Typically // involving a template-id-expr. if (ArgType == S.Context.OverloadTy) { + assert(Arg && "expected a non-null arg expression"); ArgType = ResolveOverloadForDeduction(S, TemplateParams, Arg, ParamType, ParamRefType != nullptr, FailedTSC); if (ArgType.isNull()) @@ -3900,14 +3905,16 @@ static bool AdjustFunctionParmAndArgTypesForDeduction( if (ParamRefType) { // If the argument has incomplete array type, try to complete its type. - if (ArgType->isIncompleteArrayType()) + if (ArgType->isIncompleteArrayType()) { + assert(Arg && "expected a non-null arg expression"); ArgType = S.getCompletedType(Arg); + } // C++1z [temp.deduct.call]p3: // If P is a forwarding reference and the argument is an lvalue, the type // "lvalue reference to A" is used in place of A for type deduction. if (isForwardingReference(QualType(ParamRefType, 0), FirstInnerIndex) && - Arg->isLValue()) { + ArgClassification.isLValue()) { if (S.getLangOpts().OpenCL && !ArgType.hasAddressSpace()) ArgType = S.Context.getAddrSpaceQualType( ArgType, S.Context.getDefaultOpenCLPointeeAddrSpace()); @@ -3968,7 +3975,9 @@ hasDeducibleTemplateParameters(Sema &S, FunctionTemplateDecl *FunctionTemplate, static Sema::TemplateDeductionResult DeduceTemplateArgumentsFromCallArgument( Sema &S, TemplateParameterList *TemplateParams, unsigned FirstInnerIndex, - QualType ParamType, Expr *Arg, TemplateDeductionInfo &Info, + QualType ParamType, QualType ArgType, + Expr::Classification ArgClassification, Expr *Arg, + TemplateDeductionInfo &Info, SmallVectorImpl &Deduced, SmallVectorImpl &OriginalCallArgs, bool DecomposedParam, unsigned ArgIdx, unsigned TDF, @@ -4013,8 +4022,9 @@ static Sema::TemplateDeductionResult DeduceFromInitializerList( if (ElTy->isDependentType()) { for (Expr *E : ILE->inits()) { if (auto Result = DeduceTemplateArgumentsFromCallArgument( - S, TemplateParams, 0, ElTy, E, Info, Deduced, OriginalCallArgs, true, - ArgIdx, TDF)) + S, TemplateParams, 0, ElTy, E->getType(), + E->Classify(S.getASTContext()), E, Info, Deduced, + OriginalCallArgs, true, ArgIdx, TDF)) return Result; } } @@ -4045,23 +4055,25 @@ static Sema::TemplateDeductionResult DeduceFromInitializerList( /// single parameter / argument pair. static Sema::TemplateDeductionResult DeduceTemplateArgumentsFromCallArgument( Sema &S, TemplateParameterList *TemplateParams, unsigned FirstInnerIndex, - QualType ParamType, Expr *Arg, TemplateDeductionInfo &Info, + QualType ParamType, QualType ArgType, + Expr::Classification ArgClassification, Expr *Arg, + TemplateDeductionInfo &Info, SmallVectorImpl &Deduced, SmallVectorImpl &OriginalCallArgs, bool DecomposedParam, unsigned ArgIdx, unsigned TDF, TemplateSpecCandidateSet *FailedTSC) { - QualType ArgType = Arg->getType(); + QualType OrigParamType = ParamType; // If P is a reference type [...] // If P is a cv-qualified type [...] - if (AdjustFunctionParmAndArgTypesForDeduction(S, TemplateParams, - FirstInnerIndex, ParamType, - ArgType, Arg, TDF, FailedTSC)) + if (AdjustFunctionParmAndArgTypesForDeduction( + S, TemplateParams, FirstInnerIndex, ParamType, ArgType, + ArgClassification, Arg, TDF, FailedTSC)) return Sema::TDK_Success; // If [...] the argument is a non-empty initializer list [...] - if (InitListExpr *ILE = dyn_cast(Arg)) + if (InitListExpr *ILE = dyn_cast_if_present(Arg)) return DeduceFromInitializerList(S, TemplateParams, ParamType, ILE, Info, Deduced, OriginalCallArgs, ArgIdx, TDF); @@ -4070,8 +4082,9 @@ static Sema::TemplateDeductionResult DeduceTemplateArgumentsFromCallArgument( // // Keep track of the argument type and corresponding parameter index, // so we can check for compatibility between the deduced A and A. - OriginalCallArgs.push_back( - Sema::OriginalCallArg(OrigParamType, DecomposedParam, ArgIdx, ArgType)); + if (Arg) + OriginalCallArgs.push_back( + Sema::OriginalCallArg(OrigParamType, DecomposedParam, ArgIdx, ArgType)); return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, ParamType, ArgType, Info, Deduced, TDF); } @@ -4106,12 +4119,19 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef Args, FunctionDecl *&Specialization, TemplateDeductionInfo &Info, bool PartialOverloading, bool AggregateDeductionCandidate, + QualType ObjectType, Expr::Classification ObjectClassification, llvm::function_ref)> CheckNonDependent) { if (FunctionTemplate->isInvalidDecl()) return TDK_Invalid; FunctionDecl *Function = FunctionTemplate->getTemplatedDecl(); unsigned NumParams = Function->getNumParams(); + bool HasExplicitObject = false; + int ExplicitObjectOffset = 0; + if (Function->hasCXXExplicitFunctionObjectParameter()) { + HasExplicitObject = true; + ExplicitObjectOffset = 1; + } unsigned FirstInnerIndex = getFirstInnerIndex(FunctionTemplate); @@ -4119,9 +4139,11 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( // Template argument deduction is done by comparing each function template // parameter type (call it P) with the type of the corresponding argument // of the call (call it A) as described below. - if (Args.size() < Function->getMinRequiredArguments() && !PartialOverloading) + if (Args.size() < Function->getMinRequiredExplicitArguments() && + !PartialOverloading) return TDK_TooFewArguments; - else if (TooManyArguments(NumParams, Args.size(), PartialOverloading)) { + else if (TooManyArguments(NumParams, Args.size() + ExplicitObjectOffset, + PartialOverloading)) { const auto *Proto = Function->getType()->castAs(); if (Proto->isTemplateVariadic()) /* Do nothing */; @@ -4157,7 +4179,8 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( SmallVector OriginalCallArgs; // Deduce an argument of type ParamType from an expression with index ArgIdx. - auto DeduceCallArgument = [&](QualType ParamType, unsigned ArgIdx) { + auto DeduceCallArgument = [&](QualType ParamType, unsigned ArgIdx, + bool ExplicitObjetArgument) { // C++ [demp.deduct.call]p1: (DR1391) // Template argument deduction is done by comparing each function template // parameter that contains template-parameters that participate in @@ -4165,10 +4188,21 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( if (!hasDeducibleTemplateParameters(*this, FunctionTemplate, ParamType)) return Sema::TDK_Success; + if (ExplicitObjetArgument) { + // ... with the type of the corresponding argument + return DeduceTemplateArgumentsFromCallArgument( + *this, TemplateParams, FirstInnerIndex, ParamType, ObjectType, + ObjectClassification, + /*Arg=*/nullptr, Info, Deduced, OriginalCallArgs, + /*Decomposed*/ false, ArgIdx, /*TDF*/ 0); + } + // ... with the type of the corresponding argument return DeduceTemplateArgumentsFromCallArgument( - *this, TemplateParams, FirstInnerIndex, ParamType, Args[ArgIdx], Info, Deduced, - OriginalCallArgs, /*Decomposed*/false, ArgIdx, /*TDF*/ 0); + *this, TemplateParams, FirstInnerIndex, ParamType, + Args[ArgIdx]->getType(), Args[ArgIdx]->Classify(getASTContext()), + Args[ArgIdx], Info, Deduced, OriginalCallArgs, /*Decomposed*/ false, + ArgIdx, /*TDF*/ 0); }; // Deduce template arguments from the function parameters. @@ -4182,11 +4216,20 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( dyn_cast(ParamType); if (!ParamExpansion) { // Simple case: matching a function parameter to a function argument. - if (ArgIdx >= Args.size()) + if (ArgIdx >= Args.size() && !(HasExplicitObject && ParamIdx == 0)) break; ParamTypesForArgChecking.push_back(ParamType); - if (auto Result = DeduceCallArgument(ParamType, ArgIdx++)) + + if (ParamIdx == 0 && HasExplicitObject) { + if (auto Result = DeduceCallArgument(ParamType, 0, + /*ExplicitObjetArgument=*/true)) + return Result; + continue; + } + + if (auto Result = DeduceCallArgument(ParamType, ArgIdx++, + /*ExplicitObjetArgument=*/false)) return Result; continue; @@ -4219,7 +4262,8 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( for (; ArgIdx < Args.size() && PackScope.hasNextElement(); PackScope.nextPackElement(), ++ArgIdx) { ParamTypesForArgChecking.push_back(ParamPattern); - if (auto Result = DeduceCallArgument(ParamPattern, ArgIdx)) + if (auto Result = DeduceCallArgument(ParamPattern, ArgIdx, + /*ExplicitObjetArgument=*/false)) return Result; } } else { @@ -4459,11 +4503,10 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( /// Deduce template arguments for a templated conversion /// function (C++ [temp.deduct.conv]) and, if successful, produce a /// conversion function template specialization. -Sema::TemplateDeductionResult -Sema::DeduceTemplateArguments(FunctionTemplateDecl *ConversionTemplate, - QualType ToType, - CXXConversionDecl *&Specialization, - TemplateDeductionInfo &Info) { +Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( + FunctionTemplateDecl *ConversionTemplate, QualType ObjectType, + Expr::Classification ObjectClassification, QualType ToType, + CXXConversionDecl *&Specialization, TemplateDeductionInfo &Info) { if (ConversionTemplate->isInvalidDecl()) return TDK_Invalid; @@ -4558,6 +4601,19 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *ConversionTemplate, if ((P->isPointerType() && A->isPointerType()) || (P->isMemberPointerType() && A->isMemberPointerType())) TDF |= TDF_IgnoreQualifiers; + + SmallVector OriginalCallArgs; + if (ConversionGeneric->isExplicitObjectMemberFunction()) { + QualType ParamType = ConversionGeneric->getParamDecl(0)->getType(); + if (TemplateDeductionResult Result = + DeduceTemplateArgumentsFromCallArgument( + *this, TemplateParams, getFirstInnerIndex(ConversionTemplate), + ParamType, ObjectType, ObjectClassification, + /*Arg=*/nullptr, Info, Deduced, OriginalCallArgs, + /*Decomposed*/ false, 0, /*TDF*/ 0)) + return Result; + } + if (TemplateDeductionResult Result = DeduceTemplateArgumentsByTypeMatch(*this, TemplateParams, P, A, Info, Deduced, TDF)) @@ -4570,7 +4626,8 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *ConversionTemplate, TemplateDeductionResult Result; runWithSufficientStackSpace(Info.getLocation(), [&] { Result = FinishTemplateArgumentDeduction(ConversionTemplate, Deduced, 0, - ConversionSpecialized, Info); + ConversionSpecialized, Info, + &OriginalCallArgs); }); Specialization = cast_or_null(ConversionSpecialized); return Result; @@ -4785,9 +4842,25 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *Init, QualType &Result, return TDK_Success; } + // Make sure that we treat 'char[]' equaly as 'char*' in C23 mode. + auto *String = dyn_cast(Init); + if (getLangOpts().C23 && String && Type.getType()->isArrayType()) { + Diag(Type.getBeginLoc(), diag::ext_c23_auto_non_plain_identifier); + TypeLoc TL = TypeLoc(Init->getType(), Type.getOpaqueData()); + Result = SubstituteDeducedTypeTransform(*this, DependentResult).Apply(TL); + assert(!Result.isNull() && "substituting DependentTy can't fail"); + return TDK_Success; + } + + // Emit a warning if 'auto*' is used in pedantic and in C23 mode. + if (getLangOpts().C23 && Type.getType()->isPointerType()) { + Diag(Type.getBeginLoc(), diag::ext_c23_auto_non_plain_identifier); + } + auto *InitList = dyn_cast(Init); if (!getLangOpts().CPlusPlus && InitList) { - Diag(Init->getBeginLoc(), diag::err_auto_init_list_from_c); + Diag(Init->getBeginLoc(), diag::err_auto_init_list_from_c) + << (int)AT->getKeyword() << getLangOpts().C23; return TDK_AlreadyDiagnosed; } @@ -4846,7 +4919,8 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *Init, QualType &Result, if (isa(Init)) return TDK_Invalid; if (auto TDK = DeduceTemplateArgumentsFromCallArgument( - *this, TemplateParamsSt.get(), 0, TemplArg, Init, Info, Deduced, + *this, TemplateParamsSt.get(), 0, TemplArg, Init->getType(), + Init->Classify(getASTContext()), Init, Info, Deduced, OriginalCallArgs, /*Decomposed=*/true, /*ArgIdx=*/0, /*TDF=*/0)) { if (TDK == TDK_Inconsistent) { @@ -4872,7 +4946,8 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *Init, QualType &Result, assert(!FuncParam.isNull() && "substituting template parameter for 'auto' failed"); if (auto TDK = DeduceTemplateArgumentsFromCallArgument( - *this, TemplateParamsSt.get(), 0, FuncParam, Init, Info, Deduced, + *this, TemplateParamsSt.get(), 0, FuncParam, Init->getType(), + Init->Classify(getASTContext()), Init, Info, Deduced, OriginalCallArgs, /*Decomposed=*/false, /*ArgIdx=*/0, /*TDF=*/0, FailedTSC)) return DeductionFailed(TDK); @@ -5080,6 +5155,8 @@ AddImplicitObjectParameterType(ASTContext &Context, // // The standard doesn't say explicitly, but we pick the appropriate kind of // reference type based on [over.match.funcs]p4. + assert(Method && Method->isImplicitObjectMemberFunction() && + "expected an implicit objet function"); QualType ArgTy = Context.getTypeDeclType(Method->getParent()); ArgTy = Context.getQualifiedType(ArgTy, Method->getMethodQualifiers()); if (Method->getRefQualifier() == RQ_RValue) @@ -5141,14 +5218,17 @@ static bool isAtLeastAsSpecializedAs(Sema &S, unsigned NumComparedArguments = NumCallArguments1; - if (!Method2 && Method1 && !Method1->isStatic()) { + if (!Method2 && Method1 && Method1->isImplicitObjectMemberFunction()) { // Compare 'this' from Method1 against first parameter from Method2. AddImplicitObjectParameterType(S.Context, Method1, Args1); ++NumComparedArguments; - } else if (!Method1 && Method2 && !Method2->isStatic()) { + } else if (!Method1 && Method2 && + Method2->isImplicitObjectMemberFunction()) { // Compare 'this' from Method2 against first parameter from Method1. AddImplicitObjectParameterType(S.Context, Method2, Args2); - } else if (Method1 && Method2 && Reversed) { + } else if (Method1 && Method2 && Reversed && + Method1->isImplicitObjectMemberFunction() && + Method2->isImplicitObjectMemberFunction()) { // Compare 'this' from Method1 against second parameter from Method2 // and 'this' from Method2 against second parameter from Method1. AddImplicitObjectParameterType(S.Context, Method1, Args1); diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 00a36696cf9045..23de64080a070c 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -1075,7 +1075,9 @@ void Sema::PrintInstantiationStack() { << Active->InstantiationRange; break; case CodeSynthesisContext::BuildingDeductionGuides: - llvm_unreachable("unexpected deduction guide in instantiation stack"); + Diags.Report(Active->PointOfInstantiation, + diag::note_building_deduction_guide_here); + break; } } } @@ -2908,6 +2910,8 @@ ParmVarDecl *Sema::SubstParmVarDecl( NewParm->setUninstantiatedDefaultArg(Arg); } + NewParm->setExplicitObjectParameterLoc( + OldParm->getExplicitObjectParamThisLoc()); NewParm->setHasInheritedDefaultArg(OldParm->hasInheritedDefaultArg()); if (OldParm->isParameterPack() && !NewParm->isParameterPack()) { diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 1aa4036756f369..071366ac0ee983 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -2140,7 +2140,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl( Function = CXXDeductionGuideDecl::Create( SemaRef.Context, DC, D->getInnerLocStart(), InstantiatedExplicitSpecifier, NameInfo, T, TInfo, - D->getSourceRange().getEnd(), /*Ctor=*/nullptr, + D->getSourceRange().getEnd(), DGuide->getCorrespondingConstructor(), DGuide->getDeductionCandidateKind()); Function->setAccess(D->getAccess()); } else { @@ -4434,7 +4434,7 @@ TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D, Qualifiers ThisTypeQuals; if (CXXMethodDecl *Method = dyn_cast(D)) { ThisContext = cast(Owner); - ThisTypeQuals = Method->getMethodQualifiers(); + ThisTypeQuals = Method->getFunctionObjectParameterType().getQualifiers(); } TypeSourceInfo *NewTInfo = SemaRef.SubstFunctionDeclType( @@ -4523,6 +4523,36 @@ TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D, return NewTInfo; } +/// Introduce the instantiated local variables into the local +/// instantiation scope. +void Sema::addInstantiatedLocalVarsToScope(FunctionDecl *Function, + const FunctionDecl *PatternDecl, + LocalInstantiationScope &Scope) { + LambdaScopeInfo *LSI = cast(getFunctionScopes().back()); + + for (auto *decl : PatternDecl->decls()) { + if (!isa(decl) || isa(decl)) + continue; + + VarDecl *VD = cast(decl); + IdentifierInfo *II = VD->getIdentifier(); + + auto it = llvm::find_if(Function->decls(), [&](Decl *inst) { + VarDecl *InstVD = dyn_cast(inst); + return InstVD && InstVD->isLocalVarDecl() && + InstVD->getIdentifier() == II; + }); + + if (it == Function->decls().end()) + continue; + + Scope.InstantiatedLocal(VD, *it); + LSI->addCapture(cast(*it), /*isBlock=*/false, /*isByref=*/false, + /*isNested=*/false, VD->getLocation(), SourceLocation(), + VD->getType(), /*Invalid=*/false); + } +} + /// Introduce the instantiated function parameters into the local /// instantiation scope, and set the parameter names to those used /// in the template. diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index d13a5564e9ad64..068971f8130a4a 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -16,6 +16,7 @@ #include "clang/AST/ASTMutationListener.h" #include "clang/AST/ASTStructuralEquivalence.h" #include "clang/AST/CXXInheritance.h" +#include "clang/AST/Decl.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" @@ -40,6 +41,7 @@ #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" #include "llvm/IR/DerivedTypes.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/ErrorHandling.h" #include #include @@ -3122,7 +3124,7 @@ QualType Sema::BuildMemberPointerType(QualType T, QualType Class, (Entity.getNameKind() == DeclarationName::CXXConstructorName) || (Entity.getNameKind() == DeclarationName::CXXDestructorName); if (T->isFunctionType()) - adjustMemberFunctionCC(T, /*IsStatic=*/false, IsCtorOrDtor, Loc); + adjustMemberFunctionCC(T, /*HasThisPointer=*/true, IsCtorOrDtor, Loc); return Context.getMemberPointerType(T, Class.getTypePtr()); } @@ -5801,7 +5803,12 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // // Core issue 547 also allows cv-qualifiers on function types that are // top-level template type arguments. - enum { NonMember, Member, DeductionGuide } Kind = NonMember; + enum { + NonMember, + Member, + ExplicitObjectMember, + DeductionGuide + } Kind = NonMember; if (D.getName().getKind() == UnqualifiedIdKind::IK_DeductionGuideName) Kind = DeductionGuide; else if (!D.getCXXScopeSpec().isSet()) { @@ -5815,6 +5822,18 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, Kind = Member; } + if (Kind == Member) { + unsigned I; + if (D.isFunctionDeclarator(I)) { + const DeclaratorChunk &Chunk = D.getTypeObject(I); + if (Chunk.Fun.NumParams) { + auto *P = dyn_cast_or_null(Chunk.Fun.Params->Param); + if (P && P->isExplicitObjectParameter()) + Kind = ExplicitObjectMember; + } + } + } + // C++11 [dcl.fct]p6 (w/DR1417): // An attempt to specify a function type with a cv-qualifier-seq or a // ref-qualifier (including by typedef-name) is ill-formed unless it is: @@ -5832,7 +5851,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // // ... for instance. if (IsQualifiedFunction && - !(Kind == Member && + !(Kind == Member && !D.isExplicitObjectMemberFunction() && D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_static) && !IsTypedefName && D.getContext() != DeclaratorContext::TemplateArg && D.getContext() != DeclaratorContext::TemplateTypeArg) { @@ -8123,14 +8142,15 @@ bool Sema::hasExplicitCallingConv(QualType T) { return false; } -void Sema::adjustMemberFunctionCC(QualType &T, bool IsStatic, bool IsCtorOrDtor, - SourceLocation Loc) { +void Sema::adjustMemberFunctionCC(QualType &T, bool HasThisPointer, + bool IsCtorOrDtor, SourceLocation Loc) { FunctionTypeUnwrapper Unwrapped(*this, T); const FunctionType *FT = Unwrapped.get(); bool IsVariadic = (isa(FT) && cast(FT)->isVariadic()); CallingConv CurCC = FT->getCallConv(); - CallingConv ToCC = Context.getDefaultCallingConvention(IsVariadic, !IsStatic); + CallingConv ToCC = + Context.getDefaultCallingConvention(IsVariadic, HasThisPointer); if (CurCC == ToCC) return; @@ -8150,7 +8170,7 @@ void Sema::adjustMemberFunctionCC(QualType &T, bool IsStatic, bool IsCtorOrDtor, // we should adjust a __cdecl type to __thiscall for instance methods, and a // __thiscall type to __cdecl for static methods. CallingConv DefaultCC = - Context.getDefaultCallingConvention(IsVariadic, IsStatic); + Context.getDefaultCallingConvention(IsVariadic, !HasThisPointer); if (CurCC != DefaultCC) return; @@ -9860,11 +9880,14 @@ QualType Sema::BuildAtomicType(QualType T, SourceLocation Loc) { DisallowedKind = 5; else if (T->isSizelessType()) DisallowedKind = 6; - else if (!T.isTriviallyCopyableType(Context)) + else if (!T.isTriviallyCopyableType(Context) && getLangOpts().CPlusPlus) // Some other non-trivially-copyable type (probably a C++ class) DisallowedKind = 7; else if (T->isBitIntType()) DisallowedKind = 8; + else if (getLangOpts().C23 && T->isUndeducedAutoType()) + // _Atomic auto is prohibited in C23 + DisallowedKind = 9; if (DisallowedKind != -1) { Diag(Loc, diag::err_atomic_specifier_bad_type) << DisallowedKind << T; diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 0fc5ad8e3bde6c..8fafdd4f5caa1e 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -2391,6 +2391,15 @@ class TreeTransform { EndLoc); } + /// Build a new OpenMP 'ompx_bare' clause. + /// + /// By default, performs semantic analysis to build the new OpenMP clause. + /// Subclasses may override this routine to provide different behavior. + OMPClause *RebuildOMPXBareClause(SourceLocation StartLoc, + SourceLocation EndLoc) { + return getSema().ActOnOpenMPXBareClause(StartLoc, EndLoc); + } + /// Build a new OpenMP 'align' clause. /// /// By default, performs semantic analysis to build the new OpenMP clause. @@ -5490,6 +5499,9 @@ TreeTransform::TransformDependentSizedArrayType(TypeLocBuilder &TLB, EnterExpressionEvaluationContext Unevaluated( SemaRef, Sema::ExpressionEvaluationContext::ConstantEvaluated); + // If we have a VLA then it won't be a constant. + SemaRef.ExprEvalContexts.back().InConditionallyConstantEvaluateContext = true; + // Prefer the expression from the TypeLoc; the other may have been uniqued. Expr *origSize = TL.getSizeExpr(); if (!origSize) origSize = T->getSizeExpr(); @@ -10804,6 +10816,11 @@ TreeTransform::TransformOMPXAttributeClause(OMPXAttributeClause *C) { NewAttrs, C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc()); } +template +OMPClause *TreeTransform::TransformOMPXBareClause(OMPXBareClause *C) { + return getDerived().RebuildOMPXBareClause(C->getBeginLoc(), C->getEndLoc()); +} + //===----------------------------------------------------------------------===// // Expression transformation //===----------------------------------------------------------------------===// diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 0c9c5992c267b3..cdfd3b6e863a93 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -10447,6 +10447,9 @@ OMPClause *OMPClauseReader::readClause() { case llvm::omp::OMPC_ompx_attribute: C = new (Context) OMPXAttributeClause(); break; + case llvm::omp::OMPC_ompx_bare: + C = new (Context) OMPXBareClause(); + break; #define OMP_CLAUSE_NO_CLASS(Enum, Str) \ case llvm::omp::Enum: \ break; @@ -11548,6 +11551,8 @@ void OMPClauseReader::VisitOMPXAttributeClause(OMPXAttributeClause *C) { C->setLocEnd(Record.readSourceLocation()); } +void OMPClauseReader::VisitOMPXBareClause(OMPXBareClause *C) {} + OMPTraitInfo *ASTRecordReader::readOMPTraitInfo() { OMPTraitInfo &TI = getContext().getNewOMPTraitInfo(); TI.Sets.resize(readUInt32()); diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 88cb54a0365e62..d553b3c6d78ded 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -1707,6 +1707,7 @@ void ASTDeclReader::VisitParmVarDecl(ParmVarDecl *PD) { PD->ParmVarDeclBits.HasInheritedDefaultArg = Record.readInt(); if (Record.readInt()) // hasUninstantiatedDefaultArg. PD->setUninstantiatedDefaultArg(Record.readExpr()); + PD->ExplicitObjectParameterIntroducerLoc = Record.readSourceLocation(); // FIXME: If this is a redeclaration of a function from another module, handle // inheritance of default arguments. diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index 8edb04f4f81907..1bdc3fa3bea455 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -596,6 +596,7 @@ void ASTStmtReader::VisitDeclRefExpr(DeclRefExpr *E) { E->DeclRefExprBits.RefersToEnclosingVariableOrCapture = Record.readInt(); E->DeclRefExprBits.NonOdrUseReason = Record.readInt(); E->DeclRefExprBits.IsImmediateEscalating = Record.readInt(); + E->DeclRefExprBits.CapturedByCopyInLambdaWithExplicitObjectParameter = false; unsigned NumTemplateArgs = 0; if (E->hasTemplateKWAndArgsInfo()) NumTemplateArgs = Record.readInt(); diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 201e2fcaaec91a..8d8a10336576d9 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -7258,6 +7258,8 @@ void OMPClauseWriter::VisitOMPXAttributeClause(OMPXAttributeClause *C) { Record.AddSourceLocation(C->getEndLoc()); } +void OMPClauseWriter::VisitOMPXBareClause(OMPXBareClause *C) {} + void ASTRecordWriter::writeOMPTraitInfo(const OMPTraitInfo *TI) { writeUInt32(TI->Sets.size()); for (const auto &Set : TI->Sets) { diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp index 4426f5c22277ed..91c8ed9f75db1f 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -1162,28 +1162,21 @@ void ASTDeclWriter::VisitParmVarDecl(ParmVarDecl *D) { Record.push_back(D->hasUninstantiatedDefaultArg()); if (D->hasUninstantiatedDefaultArg()) Record.AddStmt(D->getUninstantiatedDefaultArg()); + Record.AddSourceLocation(D->getExplicitObjectParamThisLoc()); Code = serialization::DECL_PARM_VAR; // If the assumptions about the DECL_PARM_VAR abbrev are true, use it. Here // we dynamically check for the properties that we optimize for, but don't // know are true of all PARM_VAR_DECLs. - if (D->getDeclContext() == D->getLexicalDeclContext() && - !D->hasAttrs() && - !D->hasExtInfo() && - !D->isImplicit() && - !D->isUsed(false) && - !D->isInvalidDecl() && - !D->isReferenced() && - D->getAccess() == AS_none && - !D->isModulePrivate() && - D->getStorageClass() == 0 && + if (D->getDeclContext() == D->getLexicalDeclContext() && !D->hasAttrs() && + !D->hasExtInfo() && !D->isImplicit() && !D->isUsed(false) && + !D->isInvalidDecl() && !D->isReferenced() && D->getAccess() == AS_none && + !D->isModulePrivate() && D->getStorageClass() == 0 && D->getInitStyle() == VarDecl::CInit && // Can params have anything else? - D->getFunctionScopeDepth() == 0 && - D->getObjCDeclQualifier() == 0 && - !D->isKNRPromoted() && - !D->hasInheritedDefaultArg() && - D->getInit() == nullptr && - !D->hasUninstantiatedDefaultArg()) // No default expr. + D->getFunctionScopeDepth() == 0 && D->getObjCDeclQualifier() == 0 && + !D->isKNRPromoted() && !D->isExplicitObjectParameter() && + !D->hasInheritedDefaultArg() && D->getInit() == nullptr && + !D->hasUninstantiatedDefaultArg()) // No default expr. AbbrevToUse = Writer.getDeclParmVarAbbrev(); // Check things we know are true of *every* PARM_VAR_DECL, which is more than diff --git a/clang/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp index 906f4e85a8e5b5..627b51af6bd44a 100644 --- a/clang/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp @@ -899,6 +899,14 @@ void NullabilityChecker::checkPostCall(const CallEvent &Call, const NullabilityState *TrackedNullability = State->get(Region); + // ObjCMessageExpr gets the actual type through + // Sema::getMessageSendResultType, instead of using the return type of + // MethodDecl directly. The final type is generated by considering the + // nullability of receiver and MethodDecl together. Thus, The type of + // ObjCMessageExpr is prefer. + if (const Expr *E = Call.getOriginExpr()) + ReturnType = E->getType(); + if (!TrackedNullability && getNullabilityAnnotation(ReturnType) == Nullability::Nullable) { State = State->set(Region, Nullability::Nullable); @@ -1053,7 +1061,7 @@ void NullabilityChecker::checkPostObjCMessage(const ObjCMethodCall &M, } // No tracked information. Use static type information for return value. - Nullability RetNullability = getNullabilityAnnotation(RetType); + Nullability RetNullability = getNullabilityAnnotation(Message->getType()); // Properties might be computed, which means the property value could // theoretically change between calls even in commonly-observed cases like diff --git a/clang/lib/StaticAnalyzer/Core/BasicValueFactory.cpp b/clang/lib/StaticAnalyzer/Core/BasicValueFactory.cpp index e8d74b40c6fd84..5c10e757244d7f 100644 --- a/clang/lib/StaticAnalyzer/Core/BasicValueFactory.cpp +++ b/clang/lib/StaticAnalyzer/Core/BasicValueFactory.cpp @@ -272,7 +272,7 @@ BasicValueFactory::evalAPSInt(BinaryOperator::Opcode Op, // FIXME: This logic should probably go higher up, where we can // test these conditions symbolically. - if (V2.isSigned() && V2.isNegative()) + if (V2.isNegative() || V2.getBitWidth() > 64) return nullptr; uint64_t Amt = V2.getZExtValue(); @@ -287,7 +287,7 @@ BasicValueFactory::evalAPSInt(BinaryOperator::Opcode Op, // FIXME: This logic should probably go higher up, where we can // test these conditions symbolically. - if (V2.isSigned() && V2.isNegative()) + if (V2.isNegative() || V2.getBitWidth() > 64) return nullptr; uint64_t Amt = V2.getZExtValue(); diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp index d7c5bd1d404235..451ee91b94533d 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -299,7 +299,7 @@ ProgramStateRef ExprEngine::getInitialState(const LocationContext *InitLoc) { } if (const auto *MD = dyn_cast(D)) { - if (!MD->isStatic()) { + if (MD->isImplicitObjectMemberFunction()) { // Precondition: 'this' is always non-null upon entry to the // top-level function. This is our starting assumption for // analyzing an "open" program. @@ -2114,7 +2114,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, // valid region. const Decl *Callee = OCE->getCalleeDecl(); if (const auto *MD = dyn_cast_or_null(Callee)) { - if (MD->isInstance()) { + if (MD->isImplicitObjectMemberFunction()) { ProgramStateRef State = Pred->getState(); const LocationContext *LCtx = Pred->getLocationContext(); ProgramStateRef NewState = @@ -3357,7 +3357,7 @@ void ExprEngine::VisitMemberExpr(const MemberExpr *M, ExplodedNode *Pred, // Handle C++ method calls. if (const auto *MD = dyn_cast(Member)) { - if (MD->isInstance()) + if (MD->isImplicitObjectMemberFunction()) state = createTemporaryRegionIfNeeded(state, LCtx, BaseExpr); SVal MDVal = svalBuilder.getFunctionPointer(MD); diff --git a/clang/lib/StaticAnalyzer/Core/LoopWidening.cpp b/clang/lib/StaticAnalyzer/Core/LoopWidening.cpp index 748c65f578a81a..a3b29ff487e4ed 100644 --- a/clang/lib/StaticAnalyzer/Core/LoopWidening.cpp +++ b/clang/lib/StaticAnalyzer/Core/LoopWidening.cpp @@ -84,7 +84,7 @@ ProgramStateRef getWidenedLoopState(ProgramStateRef PrevState, // pointer should remain unchanged. Ignore static methods, since they do not // have 'this' pointers. const CXXMethodDecl *CXXMD = dyn_cast(STC->getDecl()); - if (CXXMD && !CXXMD->isStatic()) { + if (CXXMD && CXXMD->isImplicitObjectMemberFunction()) { const CXXThisRegion *ThisR = MRMgr.getCXXThisRegion(CXXMD->getThisType(), STC); ITraits.setTrait(ThisR, diff --git a/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp b/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp index f827f43eaa7da6..d89d82626f7269 100644 --- a/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp +++ b/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp @@ -275,7 +275,7 @@ DefinedSVal SValBuilder::getMemberPointer(const NamedDecl *ND) { // We don't need to play a similar trick for static member fields // because these are represented as plain VarDecls and not FieldDecls // in the AST. - if (MD->isStatic()) + if (!MD->isImplicitObjectMemberFunction()) return getFunctionPointer(MD); } diff --git a/clang/lib/Tooling/Core/Replacement.cpp b/clang/lib/Tooling/Core/Replacement.cpp index 2c472df086d5ec..269f17a6db4cfc 100644 --- a/clang/lib/Tooling/Core/Replacement.cpp +++ b/clang/lib/Tooling/Core/Replacement.cpp @@ -67,7 +67,7 @@ bool Replacement::isApplicable() const { bool Replacement::apply(Rewriter &Rewrite) const { SourceManager &SM = Rewrite.getSourceMgr(); - auto Entry = SM.getFileManager().getFile(FilePath); + auto Entry = SM.getFileManager().getOptionalFileRef(FilePath); if (!Entry) return false; diff --git a/clang/lib/Tooling/Refactoring.cpp b/clang/lib/Tooling/Refactoring.cpp index d45cd8c57f10e9..961fc1c1801547 100644 --- a/clang/lib/Tooling/Refactoring.cpp +++ b/clang/lib/Tooling/Refactoring.cpp @@ -78,10 +78,7 @@ bool formatAndApplyAllReplacements( const std::string &FilePath = FileAndReplaces.first; auto &CurReplaces = FileAndReplaces.second; - const FileEntry *Entry = nullptr; - if (auto File = Files.getFile(FilePath)) - Entry = *File; - + FileEntryRef Entry = llvm::cantFail(Files.getFileRef(FilePath)); FileID ID = SM.getOrCreateFileID(Entry, SrcMgr::C_User); StringRef Code = SM.getBufferData(ID); diff --git a/clang/test/AST/Interp/builtin-functions.cpp b/clang/test/AST/Interp/builtin-functions.cpp index cd4ad010af1222..65361d67d68d57 100644 --- a/clang/test/AST/Interp/builtin-functions.cpp +++ b/clang/test/AST/Interp/builtin-functions.cpp @@ -260,3 +260,25 @@ namespace SourceLocation { static_assert(c.a.n == __LINE__ - 1, ""); } } + +namespace popcount { + static_assert(__builtin_popcount(~0u) == __CHAR_BIT__ * sizeof(unsigned int), ""); + static_assert(__builtin_popcount(0) == 0, ""); + static_assert(__builtin_popcountl(~0ul) == __CHAR_BIT__ * sizeof(unsigned long), ""); + static_assert(__builtin_popcountl(0) == 0, ""); + static_assert(__builtin_popcountll(~0ull) == __CHAR_BIT__ * sizeof(unsigned long long), ""); + static_assert(__builtin_popcountll(0) == 0, ""); + + /// From test/Sema/constant-builtins-2.c +#define BITSIZE(x) (sizeof(x) * 8) + char popcount1[__builtin_popcount(0) == 0 ? 1 : -1]; + char popcount2[__builtin_popcount(0xF0F0) == 8 ? 1 : -1]; + char popcount3[__builtin_popcount(~0) == BITSIZE(int) ? 1 : -1]; + char popcount4[__builtin_popcount(~0L) == BITSIZE(int) ? 1 : -1]; + char popcount5[__builtin_popcountl(0L) == 0 ? 1 : -1]; + char popcount6[__builtin_popcountl(0xF0F0L) == 8 ? 1 : -1]; + char popcount7[__builtin_popcountl(~0L) == BITSIZE(long) ? 1 : -1]; + char popcount8[__builtin_popcountll(0LL) == 0 ? 1 : -1]; + char popcount9[__builtin_popcountll(0xF0F0LL) == 8 ? 1 : -1]; + char popcount10[__builtin_popcountll(~0LL) == BITSIZE(long long) ? 1 : -1]; +} diff --git a/clang/test/AST/Interp/c.c b/clang/test/AST/Interp/c.c index c0ec5f8339dd1d..47058b8a93203b 100644 --- a/clang/test/AST/Interp/c.c +++ b/clang/test/AST/Interp/c.c @@ -14,11 +14,15 @@ _Static_assert(!!1.0, ""); // pedantic-ref-warning {{not an integer constant exp // pedantic-expected-warning {{not an integer constant expression}} _Static_assert(!!1, ""); -/// FIXME: Should also be rejected in the new interpreter -int a = (1 == 1 ? 5 : 3); +int a = (1 == 1 ? 5 : 3); // expected-note {{declared here}} \ + // pedantic-expected-note {{declared here}} _Static_assert(a == 5, ""); // ref-error {{not an integral constant expression}} \ // pedantic-ref-error {{not an integral constant expression}} \ - // pedantic-expected-warning {{not an integer constant expression}} + // expected-error {{not an integral constant expression}} \ + // expected-note {{read of non-const variable}} \ + // pedantic-expected-error {{not an integral constant expression}} \ + // pedantic-expected-note {{read of non-const variable}} + const int b = 3; _Static_assert(b == 3, ""); // pedantic-ref-warning {{not an integer constant expression}} \ diff --git a/clang/test/AST/Interp/constexpr-subobj-initialization.cpp b/clang/test/AST/Interp/constexpr-subobj-initialization.cpp new file mode 100644 index 00000000000000..4976b165468bd6 --- /dev/null +++ b/clang/test/AST/Interp/constexpr-subobj-initialization.cpp @@ -0,0 +1,73 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -fexperimental-new-constant-interpreter + +/// This is like the version in test/SemaCXX/, but some of the +/// output types and their location has been adapted. +/// Differences: +/// 1) The type of the uninitialized base class is printed WITH the namespace, +/// i.e. 'baseclass_uninit::DelBase' instead of just 'DelBase'. +/// 2) The location is not the base specifier declaration, but the call site +/// of the constructor. + + +namespace baseclass_uninit { +struct DelBase { + constexpr DelBase() = delete; // expected-note {{'DelBase' has been explicitly marked deleted here}} +}; + +struct Foo : DelBase { + constexpr Foo() {}; // expected-error {{call to deleted constructor of 'DelBase'}} +}; +constexpr Foo f; // expected-error {{must be initialized by a constant expression}} \ + // expected-note {{constructor of base class 'baseclass_uninit::DelBase' is not called}} + +struct Bar : Foo { + constexpr Bar() {}; +}; +constexpr Bar bar; // expected-error {{must be initialized by a constant expression}} \ + // expected-note {{constructor of base class 'baseclass_uninit::DelBase' is not called}} + +struct Base {}; +struct A : Base { + constexpr A() : value() {} // expected-error {{member initializer 'value' does not name a non-static data member or base class}} +}; + +constexpr A a; // expected-error {{must be initialized by a constant expression}} \ + // expected-note {{constructor of base class 'baseclass_uninit::Base' is not called}} + + +struct B : Base { + constexpr B() : {} // expected-error {{expected class member or base class name}} +}; + +constexpr B b; // expected-error {{must be initialized by a constant expression}} \ + // expected-note {{constructor of base class 'baseclass_uninit::Base' is not called}} +} // namespace baseclass_uninit + + +struct Foo { + constexpr Foo(); // expected-note 2{{declared here}} +}; + +constexpr Foo ff; // expected-error {{must be initialized by a constant expression}} \ + // expected-note {{undefined constructor 'Foo' cannot be used in a constant expression}} + +struct Bar : protected Foo { + int i; + constexpr Bar() : i(12) {} // expected-note {{undefined constructor 'Foo' cannot be used in a constant expression}} +}; + +constexpr Bar bb; // expected-error {{must be initialized by a constant expression}} \ + // expected-note {{in call to 'Bar()'}} + +template +struct Baz { + constexpr Baz(); // expected-note {{declared here}} +}; + +struct Quux : Baz, private Bar { + int i; + constexpr Quux() : i(12) {} // expected-note {{undefined constructor 'Baz' cannot be used in a constant expression}} +}; + +constexpr Quux qx; // expected-error {{must be initialized by a constant expression}} \ + // expected-note {{in call to 'Quux()'}} diff --git a/clang/test/AST/Interp/lambda.cpp b/clang/test/AST/Interp/lambda.cpp index da1d706af1d050..f8400898acc0c0 100644 --- a/clang/test/AST/Interp/lambda.cpp +++ b/clang/test/AST/Interp/lambda.cpp @@ -179,3 +179,24 @@ namespace LambdasAsParams { } static_assert(heh() == 1.0); } + +namespace ThisCapture { + class Foo { + public: + int b = 32; + int a; + + constexpr Foo() : a([this](){ return b + 1;}()) {} + + constexpr int Aplus2() const { + auto F = [this]() { + return a + 2; + }; + + return F(); + } + }; + constexpr Foo F; + static_assert(F.a == 33, ""); + static_assert(F.Aplus2() == (33 + 2), ""); +} diff --git a/clang/test/AST/Interp/literals.cpp b/clang/test/AST/Interp/literals.cpp index 0dd036353fa7ef..00875bcf44dc8e 100644 --- a/clang/test/AST/Interp/literals.cpp +++ b/clang/test/AST/Interp/literals.cpp @@ -7,8 +7,6 @@ #define INT_MAX __INT_MAX__ typedef __INTPTR_TYPE__ intptr_t; -typedef __int128 int128_t; -typedef unsigned __int128 uint128_t; static_assert(true, ""); @@ -29,7 +27,10 @@ static_assert(number != 10, ""); // expected-error{{failed}} \ // ref-note{{evaluates to}} +#ifdef __SIZEOF_INT128__ namespace i128 { + typedef __int128 int128_t; + typedef unsigned __int128 uint128_t; constexpr int128_t I128_1 = 12; static_assert(I128_1 == 12, ""); static_assert(I128_1 != 10, ""); @@ -51,6 +52,9 @@ namespace i128 { constexpr int128_t Two = (int128_t)1 << 1ul; static_assert(Two == 2, ""); + constexpr uint128_t AllOnes = ~static_cast(0); + static_assert(AllOnes == UINT128_MAX, ""); + #if __cplusplus >= 201402L template constexpr T CastFrom(__int128_t A) { @@ -66,6 +70,14 @@ namespace i128 { static_assert(CastFrom(12) == 12, ""); static_assert(CastFrom(12) == 12, ""); + static_assert(CastFrom(AllOnes) == -1, ""); + static_assert(CastFrom(AllOnes) == 0xFF, ""); + static_assert(CastFrom(AllOnes) == -1, ""); + static_assert(CastFrom(AllOnes) == 0xFFFF, ""); + static_assert(CastFrom(AllOnes) == -1, ""); + static_assert(CastFrom(AllOnes) == -1, ""); + static_assert(CastFrom(AllOnes) == AllOnes, ""); + template constexpr __int128 CastTo(T A) { int128_t B = (int128_t)A; @@ -87,6 +99,7 @@ constexpr int128_t Error = __LDBL_MAX__; // ref-warning {{implicit conversion of // expected-error {{must be initialized by a constant expression}} \ // expected-note {{is outside the range of representable values of type}} } +#endif constexpr bool b = number; static_assert(b, ""); diff --git a/clang/test/AST/ast-dump-udl-consteval.cpp b/clang/test/AST/ast-dump-udl-consteval.cpp new file mode 100644 index 00000000000000..9da53f725172ab --- /dev/null +++ b/clang/test/AST/ast-dump-udl-consteval.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -xc++ -std=c++23 -ast-dump %s | FileCheck %s + +int inline consteval operator""_u32(unsigned long long val) { + return val; +} + +void udl() { + (void)(0_u32 + 1_u32); +} + +// CHECK: `-BinaryOperator {{.+}} 'int' '+' +// CHECK-NEXT: |-ConstantExpr {{.+}} 'int' +// CHECK-NEXT: | |-value: Int 0 +// CHECK-NEXT: | `-UserDefinedLiteral {{.+}} 'int' +// CHECK: `-ConstantExpr {{.+}} 'int' +// CHECK-NEXT: |-value: Int 1 +// CHECK-NEXT: `-UserDefinedLiteral {{.+}} 'int' diff --git a/clang/test/Analysis/cxx2b-deducing-this.cpp b/clang/test/Analysis/cxx2b-deducing-this.cpp new file mode 100644 index 00000000000000..d22a897097bec0 --- /dev/null +++ b/clang/test/Analysis/cxx2b-deducing-this.cpp @@ -0,0 +1,62 @@ +// RUN: %clang_analyze_cc1 -std=c++2b -verify %s \ +// RUN: -analyzer-checker=core,debug.ExprInspection + +template void clang_analyzer_dump(T); + +struct S { + int num; + S *orig; + + void a(this auto Self) { + clang_analyzer_dump(&Self); // expected-warning {{&Self}} + clang_analyzer_dump(Self.orig); // expected-warning {{&s}} + clang_analyzer_dump(Self.num); // expected-warning {{5 S32b}} + clang_analyzer_dump(Self.orig->num); // expected-warning {{5 S32b}} + + Self.num = 1; + clang_analyzer_dump(Self.num); // expected-warning {{1 S32b}} + clang_analyzer_dump(Self.orig->num); // expected-warning {{5 S32b}} + } + + void b(this auto& Self) { + clang_analyzer_dump(&Self); // expected-warning {{&s}} + clang_analyzer_dump(Self.orig); // expected-warning {{&s}} + clang_analyzer_dump(Self.num); // expected-warning {{5 S32b}} + clang_analyzer_dump(Self.orig->num); // expected-warning {{5 S32b}} + + Self.num = 2; + clang_analyzer_dump(Self.num); // expected-warning {{2 S32b}} + clang_analyzer_dump(Self.orig->num); // expected-warning {{2 S32b}} + } + + void c(this S Self) { + clang_analyzer_dump(&Self); // expected-warning {{&Self}} + clang_analyzer_dump(Self.orig); // expected-warning {{&s}} + clang_analyzer_dump(Self.num); // expected-warning {{2 S32b}} + clang_analyzer_dump(Self.orig->num); // expected-warning {{2 S32b}} + + Self.num = 3; + clang_analyzer_dump(Self.num); // expected-warning {{3 S32b}} + clang_analyzer_dump(Self.orig->num); // expected-warning {{2 S32b}} + } + + void c(this S Self, int I) { + clang_analyzer_dump(I); // expected-warning {{11 S32b}} + clang_analyzer_dump(&Self); // expected-warning {{&Self}} + clang_analyzer_dump(Self.orig); // expected-warning {{&s}} + clang_analyzer_dump(Self.num); // expected-warning {{2 S32b}} + clang_analyzer_dump(Self.orig->num); // expected-warning {{2 S32b}} + + Self.num = 4; + clang_analyzer_dump(Self.num); // expected-warning {{4 S32b}} + clang_analyzer_dump(Self.orig->num); // expected-warning {{2 S32b}} + } +}; + +void top() { + S s = {/*num=*/5, /*orig=*/&s}; + s.a(); + s.b(); // This call changes 's.num' to 2. + s.c(); + s.c(11); +} diff --git a/clang/test/Analysis/int128-nocrash.c b/clang/test/Analysis/int128-nocrash.c new file mode 100644 index 00000000000000..457254ce50caf0 --- /dev/null +++ b/clang/test/Analysis/int128-nocrash.c @@ -0,0 +1,15 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=optin.portability.UnixAPI \ +// RUN: -triple x86_64-pc-linux-gnu -x c %s + +// Don't crash! +// expected-no-diagnostics +const __int128_t a = ( (__int128_t)1 << 64 ); +const _BitInt(72) b = ( 1 << 72 ); + +void int128() { + 2 >> a; +} + +void withbitint() { + 2 >> b; +} diff --git a/clang/test/Analysis/nullability.mm b/clang/test/Analysis/nullability.mm index 06bb9912296e32..d69116d03df746 100644 --- a/clang/test/Analysis/nullability.mm +++ b/clang/test/Analysis/nullability.mm @@ -55,6 +55,7 @@ - (void)takesUnspecified:(int *)p; @property(readonly, nullable) void (^propReturnsNullableBlock)(void); @property(readonly, nullable) int *propReturnsNullable; @property(readonly) int *propReturnsUnspecified; ++ (nullable TestObject *)getNullableObject; @end TestObject * getUnspecifiedTestObject(); @@ -256,6 +257,12 @@ void testObjCPropertyReadNullability() { case 8: [o takesNonnullBlock:o.propReturnsNullableBlock]; // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 1st parameter}} break; + case 9: + [o takesNonnull:getNullableTestObject().propReturnsNonnull]; // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 1st parameter}} + break; + case 10: + [o takesNonnull:[TestObject getNullableObject].propReturnsNonnull]; // expected-warning {{Nullable pointer is passed to a callee that requires a non-null 1st parameter}} + break; } } diff --git a/clang/test/C/C2x/n3007.c b/clang/test/C/C2x/n3007.c new file mode 100644 index 00000000000000..1fd20332ceb471 --- /dev/null +++ b/clang/test/C/C2x/n3007.c @@ -0,0 +1,186 @@ +// RUN: %clang_cc1 -std=c2x -verify -pedantic -Wno-comments %s + +/* WG14 N3007: Yes + * Type Inference for object definitions + */ +void test_qualifiers(int x, const int y, int * restrict z) { + const auto a = x; + auto b = y; + static auto c = 1UL; + int* pa = &a; // expected-warning {{initializing 'int *' with an expression of type 'const int *' discards qualifiers}} + const int* pb = &b; + int* pc = &c; // expected-warning {{incompatible pointer types initializing 'int *' with an expression of type 'unsigned long *'}} + + const int ci = 12; + auto yup = ci; + yup = 12; + + auto r_test = z; + + _Static_assert(_Generic(a, int : 1)); + _Static_assert(_Generic(c, unsigned long : 1)); + _Static_assert(_Generic(pa, int * : 1)); + _Static_assert(_Generic(pb, const int * : 1)); + _Static_assert(_Generic(r_test, int * : 1)); +} + +void test_atomic(void) { + _Atomic auto i = 12; // expected-error {{_Atomic cannot be applied to type 'auto' in C23}} + _Atomic(auto) j = 12; // expected-error {{'auto' not allowed here}} \ + expected-error {{a type specifier is required for all declarations}} + + _Atomic(int) foo(void); + auto k = foo(); + + _Static_assert(_Generic(&i, _Atomic auto *: 1)); // expected-error {{_Atomic cannot be applied to type 'auto' in C23}} \ + expected-error {{'auto' not allowed here}} + _Static_assert(_Generic(k, int: 1)); +} + +void test_double(void) { + double A[3] = { 0 }; + auto pA = A; + auto qA = &A; + auto pi = 3.14; + + _Static_assert(_Generic(A, double * : 1)); + _Static_assert(_Generic(pA, double * : 1)); + _Static_assert(_Generic(qA, double (*)[3] : 1)); + _Static_assert(_Generic(pi, double : 1)); +} + +int test_auto_param(auto a) { // expected-error {{'auto' not allowed in function prototype}} + return (int)(a * 2); +} + +auto test_auto_return(float a, int b) { // expected-error {{'auto' not allowed in function return type}} + return ((a * b) * (a / b)); +} + +[[clang::overloadable]] auto test(auto x) { // expected-error {{'auto' not allowed in function prototype}} \ + expected-error {{'auto' not allowed in function return type}} + return x; +} + +void test_sizeof_alignas(void) { + (void)sizeof(auto); // expected-error {{expected expression}} + _Alignas(auto) int a[4]; // expected-error {{expected expression}} +} + +void test_arrary(void) { + auto a[4]; // expected-error {{'auto' not allowed in array declaration}} + auto b[] = {1, 2}; // expected-error {{cannot use 'auto' with array in C}} +} + +void test_initializer_list(void) { + auto a = {}; // expected-error {{cannot use 'auto' with array in C}} + auto b = { 0 }; // expected-error {{cannot use 'auto' with array in C}} + auto c = { 1, }; // expected-error {{cannot use 'auto' with array in C}} + auto d = { 1 , 2 }; // expected-error {{cannot use 'auto' with array in C}} + auto e = (int [3]){ 1, 2, 3 }; +} + +void test_structs(void) { + // FIXME: Both of these should be diagnosed as invalid underspecified + // declarations as described in N3006. + auto p1 = (struct { int a; } *)0; + struct s; + auto p2 = (struct s { int a; } *)0; + + struct B { auto b; }; // expected-error {{'auto' not allowed in struct member}} +} + +void test_typedefs(void) { + typedef auto auto_type; // expected-error {{'auto' not allowed in typedef}} + + typedef auto (*fp)(void); // expected-error {{'auto' not allowed in typedef}} + typedef void (*fp)(auto); // expected-error {{'auto' not allowed in function prototype}} + + _Generic(0, auto : 1); // expected-error {{'auto' not allowed here}} +} + +void test_misc(void) { + auto something; // expected-error {{declaration of variable 'something' with deduced type 'auto' requires an initializer}} + auto test_char = 'A'; + auto test_char_ptr = "test"; + auto test_char_ptr2[] = "another test"; // expected-warning {{type inference of a declaration other than a plain identifier with optional trailing attributes is a Clang extension}} + auto auto_size = sizeof(auto); // expected-error {{expected expression}} + + _Static_assert(_Generic(test_char, int : 1)); + _Static_assert(_Generic(test_char_ptr, char * : 1)); + _Static_assert(_Generic(test_char_ptr2, char * : 1)); +} + +void test_no_integer_promotions(void) { + short s; + auto a = s; + _Generic(a, int : 1); // expected-error {{controlling expression type 'short' not compatible with any generic association type}} +} + +void test_compound_literals(void) { + auto a = (int){}; + auto b = (int){ 0 }; + auto c = (int){ 0, }; + auto d = (int){ 0, 1 }; // expected-warning {{excess elements in scalar initializer}} + + auto auto_cl = (auto){13}; // expected-error {{expected expression}} + + _Static_assert(_Generic(a, int : 1)); + _Static_assert(_Generic(b, int : 1)); + _Static_assert(_Generic(c, int : 1)); +} + +void test_pointers(void) { + int a; + auto *ptr = &a; // expected-warning {{type inference of a declaration other than a plain identifier with optional trailing attributes is a Clang extension}} + auto *ptr2 = a; // expected-error {{variable 'ptr2' with type 'auto *' has incompatible initializer of type 'int'}} \ + expected-warning {{type inference of a declaration other than a plain identifier with optional trailing attributes is a Clang extension}} + auto nptr = nullptr; + + _Static_assert(_Generic(ptr, int * : 1)); + _Static_assert(_Generic(ptr2, int * : 1)); +} + +void test_scopes(void) { + double a = 7; + double b = 9; + { + auto a = a * a; // expected-error {{variable 'a' declared with deduced type 'auto' cannot appear in its own initializer}} \ + expected-error {{variable 'a' declared with deduced type 'auto' cannot appear in its own initializer}} + } + { + auto b = a * a; + auto a = b; + + _Static_assert(_Generic(a, double : 1)); + _Static_assert(_Generic(b, double : 1)); + } +} + +void test_loop(void) { + auto j = 4; + for (auto i = j; i < 2 * j; i++); + + _Static_assert(_Generic(j, int : 1)); +} + +#define AUTO_MACRO(_NAME, ARG, ARG2, ARG3) \ +auto _NAME = ARG + (ARG2 / ARG3); + +// This macro should only work with integers due to the usage of binary operators +#define AUTO_INT_MACRO(_NAME, ARG, ARG2, ARG3) \ +auto _NAME = (ARG ^ ARG2) & ARG3; + +void test_macros(int in_int) { + auto a = in_int + 1; + AUTO_MACRO(b, 1.3, 2.5f, 3); + AUTO_INT_MACRO(c, 64, 23, 0xff); + AUTO_INT_MACRO(not_valid, 51.5, 25, 0xff); // expected-error {{invalid operands to binary expression ('double' and 'int')}} + + auto result = (a + (int)b) - c; + + _Static_assert(_Generic(a, int : 1)); + _Static_assert(_Generic(b, double : 1)); + _Static_assert(_Generic(c, int : 1)); + _Static_assert(_Generic(result, int : 1)); +} diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp index d545f49fa5db3d..6214ff8006d67f 100644 --- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp @@ -283,3 +283,12 @@ namespace std_example { return r; } } + +struct Base { + constexpr Base() = default; +}; +struct Derived : virtual Base { // expected-note 3{{virtual base class declared here}} + constexpr Derived() = default; // expected-error {{default constructor cannot be 'constexpr' in a class with virtual base class}} + constexpr Derived(const Derived&) = default; // expected-error {{copy constructor cannot be 'constexpr' in a class with virtual base class}} + constexpr Derived(Derived&&) = default; // expected-error {{move constructor cannot be 'constexpr' in a class with virtual base class}} +}; diff --git a/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct/dcl.fct.def.default/p1.cpp b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct/dcl.fct.def.default/p1.cpp index 21f71f05419cd0..b1b5b77c4622fc 100644 --- a/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct/dcl.fct.def.default/p1.cpp +++ b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct/dcl.fct.def.default/p1.cpp @@ -5,10 +5,10 @@ // -- not have default arguments struct DefArg { static DefArg &&make(); - DefArg(int n = 5) = default; // expected-error {{an explicitly-defaulted constructor cannot have default arguments}} - DefArg(const DefArg &DA = make()) = default; // expected-error {{an explicitly-defaulted constructor cannot have default arguments}} + DefArg(int n = 5) = default; // expected-error {{an explicitly-defaulted default constructor cannot have default arguments}} + DefArg(const DefArg &DA = make()) = default; // expected-error {{an explicitly-defaulted default constructor cannot have default arguments}} DefArg(const DefArg &DA, int k = 3) = default; // expected-error {{an explicitly-defaulted copy constructor cannot have default arguments}} - DefArg(DefArg &&DA = make()) = default; // expected-error {{an explicitly-defaulted constructor cannot have default arguments}} + DefArg(DefArg &&DA = make()) = default; // expected-error {{an explicitly-defaulted default constructor cannot have default arguments}} DefArg(DefArg &&DA, int k = 3) = default; // expected-error {{an explicitly-defaulted move constructor cannot have default arguments}} DefArg &operator=(const DefArg&, int k = 4) = default; // expected-error {{parameter of overloaded 'operator=' cannot have a default argument}} DefArg &operator=(DefArg&&, int k = 4) = default; // expected-error {{parameter of overloaded 'operator=' cannot have a default argument}} diff --git a/clang/test/CXX/drs/dr12xx.cpp b/clang/test/CXX/drs/dr12xx.cpp index a941366050e1ab..c23a515ba56cb9 100644 --- a/clang/test/CXX/drs/dr12xx.cpp +++ b/clang/test/CXX/drs/dr12xx.cpp @@ -32,7 +32,7 @@ namespace dr1213 { // dr1213: 7 } #if __cplusplus >= 201103L -namespace dr1223 { // dr1227: yes open +namespace dr1223 { // dr1223: 17 drafting struct M; template struct V; diff --git a/clang/test/CXX/drs/dr13xx.cpp b/clang/test/CXX/drs/dr13xx.cpp index feaf523c44fc27..3510695954e27c 100644 --- a/clang/test/CXX/drs/dr13xx.cpp +++ b/clang/test/CXX/drs/dr13xx.cpp @@ -254,6 +254,23 @@ namespace dr1330 { // dr1330: 4 c++11 #endif } +namespace dr1341 { // dr1341: sup P0683R1 +#if __cplusplus >= 202002L +int a; +const int b = 0; // #dr1341-b-decl +struct S { + int x1 : 8 = 42; + int x2 : 8 { 42 }; + int y1 : true ? 8 : a = 42; + int y2 : true ? 8 : b = 42; + // expected-error@-1 {{cannot assign to variable 'b' with const-qualified type 'const int'}} + // expected-note@#dr1341-b-decl {{variable 'b' declared const here}} + int y3 : (true ? 8 : b) = 42; + int z : 1 || new int { 0 }; +}; +#endif +} + namespace dr1346 { // dr1346: 3.5 auto a(1); // expected-error 0-1{{extension}} auto b(1, 2); // expected-error {{multiple expressions}} expected-error 0-1{{extension}} diff --git a/clang/test/CXX/drs/dr22xx.cpp b/clang/test/CXX/drs/dr22xx.cpp index 414925f0d74cc2..cd849443b1119b 100644 --- a/clang/test/CXX/drs/dr22xx.cpp +++ b/clang/test/CXX/drs/dr22xx.cpp @@ -123,6 +123,28 @@ namespace CheckAfterMerging2 { #endif } // namespace dr2233 +namespace dr2267 { // dr2267: no +#if __cplusplus >= 201103L +struct A {} a; +struct B { explicit B(const A&); }; // #dr2267-struct-B + +struct D { D(); }; +struct C { explicit operator D(); } c; + +B b1(a); +const B &b2{a}; // FIXME ill-formed +const B &b3(a); +// expected-error@-1 {{no viable conversion from 'struct A' to 'const B'}} +// expected-note@#dr2267-struct-B {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'struct A' to 'const B &' for 1st argument}} +// expected-note@#dr2267-struct-B {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'struct A' to 'B &&' for 1st argument}} +// expected-note@#dr2267-struct-B {{explicit constructor is not a candidate}} + +D d1(c); +const D &d2{c}; // FIXME ill-formed +const D &d3(c); // FIXME ill-formed +#endif +} + namespace dr2292 { // dr2292: 9 #if __cplusplus >= 201103L template using id = T; diff --git a/clang/test/CXX/drs/dr25xx.cpp b/clang/test/CXX/drs/dr25xx.cpp index 68fb4bdaaf2e7d..f1b5a1c26fec1b 100644 --- a/clang/test/CXX/drs/dr25xx.cpp +++ b/clang/test/CXX/drs/dr25xx.cpp @@ -81,6 +81,63 @@ using ::dr2521::operator""_div; #endif } // namespace dr2521 + +#if __cplusplus >= 202302L +namespace dr2553 { // dr2553: 18 +struct B { + virtual void f(this B&); // expected-error {{an explicit object parameter cannot appear in a virtual function}} \ + // expected-note {{here}} + static void f(this B&); // expected-error {{an explicit object parameter cannot appear in a static function}} + virtual void g(); // expected-note {{here}} +}; +struct D : B { + void g(this D&); // expected-error {{an explicit object parameter cannot appear in a virtual function}} +}; + +struct D2 : B { + void f(this B&); // expected-error {{an explicit object parameter cannot appear in a virtual function}} +}; + +} +#endif + +#if __cplusplus >= 202302L +namespace dr2554 { // dr2554: 18 review +struct B { + virtual void f(); // expected-note 3{{here}} +}; + +struct D : B { + void f(this D&); // expected-error {{an explicit object parameter cannot appear in a virtual function}} +}; + +struct D2 : B { + void f(this B&); // expected-error {{an explicit object parameter cannot appear in a virtual function}} +}; +struct T {}; +struct D3 : B { + void f(this T&); // expected-error {{an explicit object parameter cannot appear in a virtual function}} +}; + +} +#endif + +#if __cplusplus >= 202302L +namespace dr2561 { // dr2561: 18 review +struct C { + constexpr C(auto) { } +}; +void foo() { + constexpr auto b = [](this C) { return 1; }; + constexpr int (*fp)(C) = b; + static_assert(fp(1) == 1); + static_assert((&decltype(b)::operator())(1) == 1); +} + +} +#endif + + namespace dr2565 { // dr2565: 16 #if __cplusplus >= 202002L template diff --git a/clang/test/CXX/drs/dr26xx.cpp b/clang/test/CXX/drs/dr26xx.cpp index 8dd07b63deb436..8517cd5872b183 100644 --- a/clang/test/CXX/drs/dr26xx.cpp +++ b/clang/test/CXX/drs/dr26xx.cpp @@ -1,4 +1,6 @@ // RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -verify +// RUN: %clang_cc1 -std=c++2b -triple x86_64-unknown-unknown %s -verify + namespace dr2621 { // dr2621: yes enum class E { a }; @@ -108,6 +110,7 @@ auto z = [a = 42](int a) { // expected-error {{a lambda parameter cannot shadow } +#if __cplusplus >= 202302L namespace dr2650 { // dr2650: yes template struct S {}; template int f(S*); // expected-note {{type 'X' of non-type template parameter is not a structural type}} @@ -116,6 +119,16 @@ class X { }; int i0 = f(0); //expected-error {{no matching function for call to 'f'}} } +#endif + +#if __cplusplus >= 202302L +namespace dr2653 { // dr2653: 18 + struct Test { void f(this const auto& = Test{}); }; + // expected-error@-1 {{the explicit object parameter cannot have a default argument}} + auto L = [](this const auto& = Test{}){}; + // expected-error@-1 {{the explicit object parameter cannot have a default argument}} +} +#endif namespace dr2654 { // dr2654: 16 void f() { @@ -171,3 +184,18 @@ void m() { bar(0); } } +#if __cplusplus >= 202302L +namespace dr2687 { // dr2687: 18 +struct S{ + void f(int); + static void g(int); + void h(this const S&, int); +}; + +void test() { + (&S::f)(1); // expected-error {{called object type 'void (dr2687::S::*)(int)' is not a function or function pointer}} + (&S::g)(1); + (&S::h)(S(), 1); +} +} +#endif diff --git a/clang/test/CXX/drs/dr5xx.cpp b/clang/test/CXX/drs/dr5xx.cpp index cba0c4e1241c5d..a3563481eac68e 100644 --- a/clang/test/CXX/drs/dr5xx.cpp +++ b/clang/test/CXX/drs/dr5xx.cpp @@ -771,10 +771,15 @@ namespace dr574 { // dr574: yes }; #if __cplusplus >= 201103L struct C { - C &operator=(const C&) &; // expected-note {{not viable}} expected-note {{candidate}} expected-note {{here}} + C &operator=(const C&) &; // #574-overload1 \ + // expected-note {{not viable}} \ + // expected-note {{here}} + }; struct D { - D &operator=(const D&) &&; // expected-note {{not viable}} expected-note {{candidate}} expected-note {{here}} + D &operator=(const D&) &&; // #574-overload2 \ + // expected-note {{not viable}} \ + // expected-note {{here}} }; void test(C c, D d) { c = c; @@ -786,10 +791,17 @@ namespace dr574 { // dr574: yes struct Test { friend A &A::operator=(const A&); // expected-error {{does not match}} friend B &B::operator=(const B&); // expected-error {{does not match}} -#if __cplusplus >= 201103L +#if __cplusplus >= 202302L + friend C &C::operator=(const C&); // expected-error {{conflicting types for 'operator='}} + friend D &D::operator=(const D&); // expected-error {{conflicting types for 'operator='}} __cplusplus >= 201103L +#elif __cplusplus >= 201103L // FIXME: We shouldn't produce the 'cannot overload' diagnostics here. - friend C &C::operator=(const C&); // expected-error {{does not match}} expected-error {{cannot overload}} - friend D &D::operator=(const D&); // expected-error {{does not match}} expected-error {{cannot overload}} + friend C &C::operator=(const C&); // expected-error {{does not match}} \ + // expected-error {{cannot overload}} \ + // expected-note@#574-overload1 {{candidate}} + friend D &D::operator=(const D&); // expected-error {{does not match}} \ + // expected-error {{cannot overload}} \ + // expected-note@#574-overload2 {{candidate}} #endif }; } diff --git a/clang/test/CXX/over/over.match/over.match.funcs/over.match.class.deduct/p2.cpp b/clang/test/CXX/over/over.match/over.match.funcs/over.match.class.deduct/p2.cpp index 4eac0a1ac510f1..49fde292f6a36d 100644 --- a/clang/test/CXX/over/over.match/over.match.funcs/over.match.class.deduct/p2.cpp +++ b/clang/test/CXX/over/over.match/over.match.funcs/over.match.class.deduct/p2.cpp @@ -85,3 +85,38 @@ int main() { } + +namespace deduceTemplatedConstructor { +template struct IsSame { + static constexpr bool value = false; +}; + +template struct IsSame { + static constexpr bool value = true; +}; +template struct A { + using value_type = T; + A(value_type); + A(const A&); + A(T, T, int); + template + A(int, T, U); +}; + +A x(1, 2, 3); // no-error +static_assert(IsSame>::value); + +template +A(T) -> A; + +A a(42); +static_assert(IsSame>::value); +A b = a; +static_assert(IsSame>::value); + +template +A(A) -> A>; + +A b2 = a; +static_assert(IsSame>>::value); +} diff --git a/clang/test/CXX/special/class.copy/p25-0x.cpp b/clang/test/CXX/special/class.copy/p25-0x.cpp index 133bb1a87ce263..c13c686bd6b540 100644 --- a/clang/test/CXX/special/class.copy/p25-0x.cpp +++ b/clang/test/CXX/special/class.copy/p25-0x.cpp @@ -1,8 +1,16 @@ // RUN: %clang_cc1 -std=c++11 -verify %s -Wno-deprecated-builtins // RUN: %clang_cc1 -std=c++11 -verify %s -Wno-deprecated-builtins -fclang-abi-compat=14 -DCLANG_ABI_COMPAT=14 +// RUN: %clang_cc1 -fsyntax-only -std=c++2b -DDEDUCING_THIS -Wno-deprecated-builtins %s -verify // expected-no-diagnostics +#if DEDUCING_THIS +#define EXPLICIT_PARAMETER(...) this __VA_ARGS__, +#else +#define EXPLICIT_PARAMETER(Param) +#endif + + template struct trivially_assignable_check { static_assert(B == __has_trivial_assign(T), ""); static_assert(B == __is_trivially_assignable(T&, T), ""); @@ -23,14 +31,18 @@ using _ = trivially_assignable; // A copy/move assignment operator for class X is trivial if it is not user-provided, struct UserProvided { - UserProvided &operator=(const UserProvided &); + UserProvided &operator=(EXPLICIT_PARAMETER(UserProvided&) + const UserProvided &); }; using _ = not_trivially_assignable; // its declared parameter type is the same as if it had been implicitly // declared, struct NonConstCopy { - NonConstCopy &operator=(NonConstCopy &) = default; + NonConstCopy &operator=(EXPLICIT_PARAMETER(NonConstCopy&) NonConstCopy &) = default; +#if DEDUCING_THIS + NonConstCopy &operator=(EXPLICIT_PARAMETER(NonConstCopy&&) NonConstCopy &) = default; +#endif }; #if defined(CLANG_ABI_COMPAT) && CLANG_ABI_COMPAT <= 14 // Up until (and including) Clang 14, non-const copy assignment operators were not trivial because @@ -50,9 +62,20 @@ static_assert(!__is_trivially_assignable(NonConstCopy &&, NonConstCopy), ""); static_assert(!__is_trivially_assignable(NonConstCopy &&, NonConstCopy &&), ""); struct DefaultedSpecialMembers { - DefaultedSpecialMembers &operator=(const DefaultedSpecialMembers &) = default; - DefaultedSpecialMembers &operator=(DefaultedSpecialMembers &) = default; - DefaultedSpecialMembers &operator=(DefaultedSpecialMembers &&) = default; + DefaultedSpecialMembers &operator=(EXPLICIT_PARAMETER(DefaultedSpecialMembers&) + const DefaultedSpecialMembers &) = default; + DefaultedSpecialMembers &operator=(EXPLICIT_PARAMETER(DefaultedSpecialMembers&) + DefaultedSpecialMembers &) = default; + DefaultedSpecialMembers &operator=(EXPLICIT_PARAMETER(DefaultedSpecialMembers&) + DefaultedSpecialMembers &&) = default; +#if DEDUCING_THIS + DefaultedSpecialMembers &operator=(EXPLICIT_PARAMETER(DefaultedSpecialMembers&&) + const DefaultedSpecialMembers &) = default; + DefaultedSpecialMembers &operator=(EXPLICIT_PARAMETER(DefaultedSpecialMembers&&) + DefaultedSpecialMembers &) = default; + DefaultedSpecialMembers &operator=(EXPLICIT_PARAMETER(DefaultedSpecialMembers&&) + DefaultedSpecialMembers &&) = default; +#endif }; using _ = trivially_assignable; #endif @@ -84,11 +107,16 @@ static_assert(__is_trivially_assignable(MutableTemplateCtorMember, MutableTempla // Both trivial and non-trivial special members. struct TNT { - TNT &operator=(const TNT &) = default; // trivial - TNT &operator=(TNT &); // non-trivial - - TNT &operator=(TNT &&) = default; // trivial - TNT &operator=(const TNT &&); // non-trivial + TNT &operator=(EXPLICIT_PARAMETER(TNT&) const TNT &) = default; // trivial + TNT &operator=(EXPLICIT_PARAMETER(TNT&) TNT &); // non-trivial + TNT &operator=(EXPLICIT_PARAMETER(TNT&) TNT &&) = default; // trivial + TNT &operator=(EXPLICIT_PARAMETER(TNT&) const TNT &&); // non-trivial +#if DEDUCING_THIS + TNT &operator=(this TNT&&, const TNT &) = default; // trivial + TNT &operator=(this TNT&&, TNT &); // non-trivial + TNT &operator=(this TNT&&, TNT &&) = default; // trivial + TNT &operator=(this TNT&&, const TNT &&); // non-trivial +#endif }; static_assert(!__has_trivial_assign(TNT), "lie deliberately for gcc compatibility"); diff --git a/clang/test/CodeGen/PowerPC/ppc64-inline-asm.c b/clang/test/CodeGen/PowerPC/ppc64-inline-asm.c index e3f2c2ff5507ce..005bf5c7fa1440 100644 --- a/clang/test/CodeGen/PowerPC/ppc64-inline-asm.c +++ b/clang/test/CodeGen/PowerPC/ppc64-inline-asm.c @@ -47,6 +47,6 @@ void testZ(void *addr) { void testZwOff(void *addr, long long off) { asm volatile ("dcbz %y0\n" :: "Z"(*(unsigned char *)(addr + off)) : "memory"); // CHECK-LABEL: void @testZwOff(ptr noundef %addr, i64 noundef %off) -// CHECK: %[[VAL:[^ ]+]] = getelementptr i8, ptr %addr, i64 %off +// CHECK: %[[VAL:[^ ]+]] = getelementptr inbounds i8, ptr %addr, i64 %off // CHECK: call void asm sideeffect "dcbz ${0:y}\0A", "*Z,~{memory}"(ptr elementtype(i8) %[[VAL]]) } diff --git a/clang/test/CodeGen/X86/avx-builtins.c b/clang/test/CodeGen/X86/avx-builtins.c index 2d54b506425071..9178ecaf3f8fe4 100644 --- a/clang/test/CodeGen/X86/avx-builtins.c +++ b/clang/test/CodeGen/X86/avx-builtins.c @@ -596,6 +596,54 @@ __m256 test_mm256_cmp_ps_true_us(__m256 a, __m256 b) { return _mm256_cmp_ps(a, b, _CMP_TRUE_US); } +__m128d test_mm_cmp_pd_eq_oq(__m128d a, __m128d b) { + // CHECK-LABEL: test_mm_cmp_pd_eq_oq + // CHECK: fcmp oeq <2 x double> %{{.*}}, %{{.*}} + return _mm_cmp_pd(a, b, _CMP_EQ_OQ); +} + +__m128d test_mm_cmp_pd_lt_os(__m128d a, __m128d b) { + // CHECK-LABEL: test_mm_cmp_pd_lt_os + // CHECK: fcmp olt <2 x double> %{{.*}}, %{{.*}} + return _mm_cmp_pd(a, b, _CMP_LT_OS); +} + +__m128d test_mm_cmp_pd_le_os(__m128d a, __m128d b) { + // CHECK-LABEL: test_mm_cmp_pd_le_os + // CHECK: fcmp ole <2 x double> %{{.*}}, %{{.*}} + return _mm_cmp_pd(a, b, _CMP_LE_OS); +} + +__m128d test_mm_cmp_pd_unord_q(__m128d a, __m128d b) { + // CHECK-LABEL: test_mm_cmp_pd_unord_q + // CHECK: fcmp uno <2 x double> %{{.*}}, %{{.*}} + return _mm_cmp_pd(a, b, _CMP_UNORD_Q); +} + +__m128d test_mm_cmp_pd_neq_uq(__m128d a, __m128d b) { + // CHECK-LABEL: test_mm_cmp_pd_neq_uq + // CHECK: fcmp une <2 x double> %{{.*}}, %{{.*}} + return _mm_cmp_pd(a, b, _CMP_NEQ_UQ); +} + +__m128d test_mm_cmp_pd_nlt_us(__m128d a, __m128d b) { + // CHECK-LABEL: test_mm_cmp_pd_nlt_us + // CHECK: fcmp uge <2 x double> %{{.*}}, %{{.*}} + return _mm_cmp_pd(a, b, _CMP_NLT_US); +} + +__m128d test_mm_cmp_pd_nle_us(__m128d a, __m128d b) { + // CHECK-LABEL: test_mm_cmp_pd_nle_us + // CHECK: fcmp ugt <2 x double> %{{.*}}, %{{.*}} + return _mm_cmp_pd(a, b, _CMP_NLE_US); +} + +__m128d test_mm_cmp_pd_ord_q(__m128d a, __m128d b) { + // CHECK-LABEL: test_mm_cmp_pd_ord_q + // CHECK: fcmp ord <2 x double> %{{.*}}, %{{.*}} + return _mm_cmp_pd(a, b, _CMP_ORD_Q); +} + __m128d test_mm_cmp_pd_eq_uq(__m128d a, __m128d b) { // CHECK-LABEL: test_mm_cmp_pd_eq_uq // CHECK: fcmp ueq <2 x double> %{{.*}}, %{{.*}} @@ -740,6 +788,54 @@ __m128d test_mm_cmp_pd_true_us(__m128d a, __m128d b) { return _mm_cmp_pd(a, b, _CMP_TRUE_US); } +__m128 test_mm_cmp_ps_eq_oq(__m128 a, __m128 b) { + // CHECK-LABEL: test_mm_cmp_ps_eq_oq + // CHECK: fcmp oeq <4 x float> %{{.*}}, %{{.*}} + return _mm_cmp_ps(a, b, _CMP_EQ_OQ); +} + +__m128 test_mm_cmp_ps_lt_os(__m128 a, __m128 b) { + // CHECK-LABEL: test_mm_cmp_ps_lt_os + // CHECK: fcmp olt <4 x float> %{{.*}}, %{{.*}} + return _mm_cmp_ps(a, b, _CMP_LT_OS); +} + +__m128 test_mm_cmp_ps_le_os(__m128 a, __m128 b) { + // CHECK-LABEL: test_mm_cmp_ps_le_os + // CHECK: fcmp ole <4 x float> %{{.*}}, %{{.*}} + return _mm_cmp_ps(a, b, _CMP_LE_OS); +} + +__m128 test_mm_cmp_ps_unord_q(__m128 a, __m128 b) { + // CHECK-LABEL: test_mm_cmp_ps_unord_q + // CHECK: fcmp uno <4 x float> %{{.*}}, %{{.*}} + return _mm_cmp_ps(a, b, _CMP_UNORD_Q); +} + +__m128 test_mm_cmp_ps_neq_uq(__m128 a, __m128 b) { + // CHECK-LABEL: test_mm_cmp_ps_neq_uq + // CHECK: fcmp une <4 x float> %{{.*}}, %{{.*}} + return _mm_cmp_ps(a, b, _CMP_NEQ_UQ); +} + +__m128 test_mm_cmp_ps_nlt_us(__m128 a, __m128 b) { + // CHECK-LABEL: test_mm_cmp_ps_nlt_us + // CHECK: fcmp uge <4 x float> %{{.*}}, %{{.*}} + return _mm_cmp_ps(a, b, _CMP_NLT_US); +} + +__m128 test_mm_cmp_ps_nle_us(__m128 a, __m128 b) { + // CHECK-LABEL: test_mm_cmp_ps_nle_us + // CHECK: fcmp ugt <4 x float> %{{.*}}, %{{.*}} + return _mm_cmp_ps(a, b, _CMP_NLE_US); +} + +__m128 test_mm_cmp_ps_ord_q(__m128 a, __m128 b) { + // CHECK-LABEL: test_mm_cmp_ps_ord_q + // CHECK: fcmp ord <4 x float> %{{.*}}, %{{.*}} + return _mm_cmp_ps(a, b, _CMP_ORD_Q); +} + __m128 test_mm_cmp_ps_eq_uq(__m128 a, __m128 b) { // CHECK-LABEL: test_mm_cmp_ps_eq_uq // CHECK: fcmp ueq <4 x float> %{{.*}}, %{{.*}} diff --git a/clang/test/CodeGen/X86/bitscan-builtins.c b/clang/test/CodeGen/X86/bitscan-builtins.c index a5a7808a82a234..9fd46664178519 100644 --- a/clang/test/CodeGen/X86/bitscan-builtins.c +++ b/clang/test/CodeGen/X86/bitscan-builtins.c @@ -1,9 +1,9 @@ -// RUN: %clang_cc1 -x c -ffreestanding %s -triple=x86_64-unknown-unknown -emit-llvm -o - | FileCheck %s -// RUN: %clang_cc1 -x c++ -std=c++11 -ffreestanding %s -triple=x86_64-unknown-unknown -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -x c -ffreestanding %s -triple=x86_64-unknown-unknown -no-enable-noundef-analysis -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -x c++ -std=c++11 -ffreestanding %s -triple=x86_64-unknown-unknown -no-enable-noundef-analysis -emit-llvm -o - | FileCheck %s // PR33722 -// RUN: %clang_cc1 -x c -ffreestanding %s -triple x86_64-unknown-unknown -fms-extensions -fms-compatibility-version=19.00 -emit-llvm -o - | FileCheck %s -// RUN: %clang_cc1 -x c++ -ffreestanding %s -triple x86_64-unknown-unknown -fms-extensions -fms-compatibility-version=19.00 -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -x c -ffreestanding %s -triple x86_64-unknown-unknown -fms-extensions -fms-compatibility-version=19.00 -no-enable-noundef-analysis -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -x c++ -ffreestanding %s -triple x86_64-unknown-unknown -fms-extensions -fms-compatibility-version=19.00 -no-enable-noundef-analysis -emit-llvm -o - | FileCheck %s #include diff --git a/clang/test/CodeGen/X86/cmp-avx-builtins-error.c b/clang/test/CodeGen/X86/cmp-avx-builtins-error.c deleted file mode 100644 index 2b35aa84492b64..00000000000000 --- a/clang/test/CodeGen/X86/cmp-avx-builtins-error.c +++ /dev/null @@ -1,22 +0,0 @@ -// RUN: %clang_cc1 %s -ffreestanding -triple=x86_64-unknown-unknown \ -// RUN: -target-feature +avx -emit-llvm -fsyntax-only -verify -// RUN: %clang_cc1 %s -ffreestanding -triple=i386-unknown-unknown \ -// RUN: -target-feature +avx -emit-llvm -fsyntax-only -verify - -#include - -__m128d test_mm_cmp_pd(__m128d a, __m128d b) { - return _mm_cmp_pd(a, b, 32); // expected-error {{argument value 32 is outside the valid range [0, 31]}} -} - -__m128d test_mm_cmp_sd(__m128d a, __m128d b) { - return _mm_cmp_sd(a, b, 32); // expected-error {{argument value 32 is outside the valid range [0, 31]}} -} - -__m128 test_mm_cmp_ps(__m128 a, __m128 b) { - return _mm_cmp_pd(a, b, 32); // expected-error {{argument value 32 is outside the valid range [0, 31]}} -} - -__m128 test_mm_cmp_ss(__m128 a, __m128 b) { - return _mm_cmp_sd(a, b, 32); // expected-error {{argument value 32 is outside the valid range [0, 31]}} -} diff --git a/clang/test/CodeGen/X86/popcnt-builtins.c b/clang/test/CodeGen/X86/popcnt-builtins.c index e59ffaa031a6a1..b27bc3f0597fb3 100644 --- a/clang/test/CodeGen/X86/popcnt-builtins.c +++ b/clang/test/CodeGen/X86/popcnt-builtins.c @@ -1,7 +1,7 @@ -// RUN: %clang_cc1 -x c -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +popcnt -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,CHECK-POPCNT -// RUN: %clang_cc1 -x c++ -std=c++11 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +popcnt -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,CHECK-POPCNT -// RUN: %clang_cc1 -x c -ffreestanding %s -triple=x86_64-apple-darwin -emit-llvm -o - | FileCheck %s -// RUN: %clang_cc1 -x c++ -std=c++11 -ffreestanding %s -triple=x86_64-apple-darwin -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -x c -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +popcnt -no-enable-noundef-analysis -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,CHECK-POPCNT +// RUN: %clang_cc1 -x c++ -std=c++11 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +popcnt -no-enable-noundef-analysis -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,CHECK-POPCNT +// RUN: %clang_cc1 -x c -ffreestanding %s -triple=x86_64-apple-darwin -no-enable-noundef-analysis -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -x c++ -std=c++11 -ffreestanding %s -triple=x86_64-apple-darwin -no-enable-noundef-analysis -emit-llvm -o - | FileCheck %s #include diff --git a/clang/test/CodeGen/X86/rot-intrinsics.c b/clang/test/CodeGen/X86/rot-intrinsics.c index f8c78119a1c4a7..5da300b024b5b8 100644 --- a/clang/test/CodeGen/X86/rot-intrinsics.c +++ b/clang/test/CodeGen/X86/rot-intrinsics.c @@ -1,16 +1,16 @@ -// RUN: %clang_cc1 -x c -ffreestanding -triple i686--linux -emit-llvm %s -o - | FileCheck %s --check-prefixes CHECK,CHECK-32BIT-LONG -// RUN: %clang_cc1 -x c -ffreestanding -triple x86_64--linux -emit-llvm %s -o - | FileCheck %s --check-prefixes CHECK,CHECK-64BIT-LONG -// RUN: %clang_cc1 -x c -fms-extensions -fms-compatibility -ffreestanding %s -triple=i686-windows-msvc -target-feature +sse2 -emit-llvm -o - -Wall -Werror | FileCheck %s --check-prefixes CHECK,CHECK-32BIT-LONG -// RUN: %clang_cc1 -x c -fms-extensions -fms-compatibility -ffreestanding %s -triple=x86_64-windows-msvc -target-feature +sse2 -emit-llvm -o - -Wall -Werror | FileCheck %s --check-prefixes CHECK,CHECK-32BIT-LONG -// RUN: %clang_cc1 -x c -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 -ffreestanding %s -triple=i686-windows-msvc -target-feature +sse2 -emit-llvm -o - -Wall -Werror | FileCheck %s --check-prefixes CHECK,CHECK-32BIT-LONG -// RUN: %clang_cc1 -x c -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 -ffreestanding %s -triple=x86_64-windows-msvc -target-feature +sse2 -emit-llvm -o - -Wall -Werror | FileCheck %s --check-prefixes CHECK,CHECK-32BIT-LONG - -// RUN: %clang_cc1 -x c++ -std=c++11 -ffreestanding -triple i686--linux -emit-llvm %s -o - | FileCheck %s --check-prefixes CHECK,CHECK-32BIT-LONG -// RUN: %clang_cc1 -x c++ -std=c++11 -ffreestanding -triple x86_64--linux -emit-llvm %s -o - | FileCheck %s --check-prefixes CHECK,CHECK-64BIT-LONG -// RUN: %clang_cc1 -x c++ -std=c++11 -fms-extensions -fms-compatibility -ffreestanding %s -triple=i686-windows-msvc -target-feature +sse2 -emit-llvm -o - -Wall -Werror | FileCheck %s --check-prefixes CHECK,CHECK-32BIT-LONG -// RUN: %clang_cc1 -x c++ -std=c++11 -fms-extensions -fms-compatibility -ffreestanding %s -triple=x86_64-windows-msvc -target-feature +sse2 -emit-llvm -o - -Wall -Werror | FileCheck %s --check-prefixes CHECK,CHECK-32BIT-LONG -// RUN: %clang_cc1 -x c++ -std=c++11 -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 -ffreestanding %s -triple=i686-windows-msvc -target-feature +sse2 -emit-llvm -o - -Wall -Werror | FileCheck %s --check-prefixes CHECK,CHECK-32BIT-LONG -// RUN: %clang_cc1 -x c++ -std=c++11 -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 -ffreestanding %s -triple=x86_64-windows-msvc -target-feature +sse2 -emit-llvm -o - -Wall -Werror | FileCheck %s --check-prefixes CHECK,CHECK-32BIT-LONG +// RUN: %clang_cc1 -x c -ffreestanding -triple i686--linux -no-enable-noundef-analysis -emit-llvm %s -o - | FileCheck %s --check-prefixes CHECK,CHECK-32BIT-LONG +// RUN: %clang_cc1 -x c -ffreestanding -triple x86_64--linux -no-enable-noundef-analysis -emit-llvm %s -o - | FileCheck %s --check-prefixes CHECK,CHECK-64BIT-LONG +// RUN: %clang_cc1 -x c -fms-extensions -fms-compatibility -ffreestanding %s -triple=i686-windows-msvc -target-feature +sse2 -no-enable-noundef-analysis -emit-llvm -o - -Wall -Werror | FileCheck %s --check-prefixes CHECK,CHECK-32BIT-LONG +// RUN: %clang_cc1 -x c -fms-extensions -fms-compatibility -ffreestanding %s -triple=x86_64-windows-msvc -target-feature +sse2 -no-enable-noundef-analysis -emit-llvm -o - -Wall -Werror | FileCheck %s --check-prefixes CHECK,CHECK-32BIT-LONG +// RUN: %clang_cc1 -x c -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 -ffreestanding %s -triple=i686-windows-msvc -target-feature +sse2 -no-enable-noundef-analysis -emit-llvm -o - -Wall -Werror | FileCheck %s --check-prefixes CHECK,CHECK-32BIT-LONG +// RUN: %clang_cc1 -x c -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 -ffreestanding %s -triple=x86_64-windows-msvc -target-feature +sse2 -no-enable-noundef-analysis -emit-llvm -o - -Wall -Werror | FileCheck %s --check-prefixes CHECK,CHECK-32BIT-LONG + +// RUN: %clang_cc1 -x c++ -std=c++11 -ffreestanding -triple i686--linux -no-enable-noundef-analysis -emit-llvm %s -o - | FileCheck %s --check-prefixes CHECK,CHECK-32BIT-LONG +// RUN: %clang_cc1 -x c++ -std=c++11 -ffreestanding -triple x86_64--linux -no-enable-noundef-analysis -emit-llvm %s -o - | FileCheck %s --check-prefixes CHECK,CHECK-64BIT-LONG +// RUN: %clang_cc1 -x c++ -std=c++11 -fms-extensions -fms-compatibility -ffreestanding %s -triple=i686-windows-msvc -target-feature +sse2 -no-enable-noundef-analysis -emit-llvm -o - -Wall -Werror | FileCheck %s --check-prefixes CHECK,CHECK-32BIT-LONG +// RUN: %clang_cc1 -x c++ -std=c++11 -fms-extensions -fms-compatibility -ffreestanding %s -triple=x86_64-windows-msvc -target-feature +sse2 -no-enable-noundef-analysis -emit-llvm -o - -Wall -Werror | FileCheck %s --check-prefixes CHECK,CHECK-32BIT-LONG +// RUN: %clang_cc1 -x c++ -std=c++11 -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 -ffreestanding %s -triple=i686-windows-msvc -target-feature +sse2 -no-enable-noundef-analysis -emit-llvm -o - -Wall -Werror | FileCheck %s --check-prefixes CHECK,CHECK-32BIT-LONG +// RUN: %clang_cc1 -x c++ -std=c++11 -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 -ffreestanding %s -triple=x86_64-windows-msvc -target-feature +sse2 -no-enable-noundef-analysis -emit-llvm -o - -Wall -Werror | FileCheck %s --check-prefixes CHECK,CHECK-32BIT-LONG #include diff --git a/clang/test/CodeGen/X86/sse-builtins.c b/clang/test/CodeGen/X86/sse-builtins.c index 82f67da39e02bb..885c82856522d2 100644 --- a/clang/test/CodeGen/X86/sse-builtins.c +++ b/clang/test/CodeGen/X86/sse-builtins.c @@ -813,57 +813,3 @@ __m128 test_mm_xor_ps(__m128 A, __m128 B) { // CHECK: xor <4 x i32> return _mm_xor_ps(A, B); } - -__m128 test_mm_cmp_ps_eq_oq(__m128 a, __m128 b) { - // CHECK-LABEL: test_mm_cmp_ps_eq_oq - // CHECK: fcmp oeq <4 x float> %{{.*}}, %{{.*}} - return _mm_cmp_ps(a, b, _CMP_EQ_OQ); -} - -__m128 test_mm_cmp_ps_lt_os(__m128 a, __m128 b) { - // CHECK-LABEL: test_mm_cmp_ps_lt_os - // CHECK: fcmp olt <4 x float> %{{.*}}, %{{.*}} - return _mm_cmp_ps(a, b, _CMP_LT_OS); -} - -__m128 test_mm_cmp_ps_le_os(__m128 a, __m128 b) { - // CHECK-LABEL: test_mm_cmp_ps_le_os - // CHECK: fcmp ole <4 x float> %{{.*}}, %{{.*}} - return _mm_cmp_ps(a, b, _CMP_LE_OS); -} - -__m128 test_mm_cmp_ps_unord_q(__m128 a, __m128 b) { - // CHECK-LABEL: test_mm_cmp_ps_unord_q - // CHECK: fcmp uno <4 x float> %{{.*}}, %{{.*}} - return _mm_cmp_ps(a, b, _CMP_UNORD_Q); -} - -__m128 test_mm_cmp_ps_neq_uq(__m128 a, __m128 b) { - // CHECK-LABEL: test_mm_cmp_ps_neq_uq - // CHECK: fcmp une <4 x float> %{{.*}}, %{{.*}} - return _mm_cmp_ps(a, b, _CMP_NEQ_UQ); -} - -__m128 test_mm_cmp_ps_nlt_us(__m128 a, __m128 b) { - // CHECK-LABEL: test_mm_cmp_ps_nlt_us - // CHECK: fcmp uge <4 x float> %{{.*}}, %{{.*}} - return _mm_cmp_ps(a, b, _CMP_NLT_US); -} - -__m128 test_mm_cmp_ps_nle_us(__m128 a, __m128 b) { - // CHECK-LABEL: test_mm_cmp_ps_nle_us - // CHECK: fcmp ugt <4 x float> %{{.*}}, %{{.*}} - return _mm_cmp_ps(a, b, _CMP_NLE_US); -} - -__m128 test_mm_cmp_ps_ord_q(__m128 a, __m128 b) { - // CHECK-LABEL: test_mm_cmp_ps_ord_q - // CHECK: fcmp ord <4 x float> %{{.*}}, %{{.*}} - return _mm_cmp_ps(a, b, _CMP_ORD_Q); -} - -__m128 test_mm_cmp_ss(__m128 A, __m128 B) { - // CHECK-LABEL: test_mm_cmp_ss - // CHECK: call <4 x float> @llvm.x86.sse.cmp.ss(<4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 7) - return _mm_cmp_ss(A, B, _CMP_ORD_Q); -} diff --git a/clang/test/CodeGen/X86/sse2-builtins.c b/clang/test/CodeGen/X86/sse2-builtins.c index 09b57e3a63727a..7165d2791827cf 100644 --- a/clang/test/CodeGen/X86/sse2-builtins.c +++ b/clang/test/CodeGen/X86/sse2-builtins.c @@ -1719,57 +1719,3 @@ __m128i test_mm_xor_si128(__m128i A, __m128i B) { // CHECK: xor <2 x i64> %{{.*}}, %{{.*}} return _mm_xor_si128(A, B); } - -__m128d test_mm_cmp_pd_eq_oq(__m128d a, __m128d b) { - // CHECK-LABEL: test_mm_cmp_pd_eq_oq - // CHECK: fcmp oeq <2 x double> %{{.*}}, %{{.*}} - return _mm_cmp_pd(a, b, _CMP_EQ_OQ); -} - -__m128d test_mm_cmp_pd_lt_os(__m128d a, __m128d b) { - // CHECK-LABEL: test_mm_cmp_pd_lt_os - // CHECK: fcmp olt <2 x double> %{{.*}}, %{{.*}} - return _mm_cmp_pd(a, b, _CMP_LT_OS); -} - -__m128d test_mm_cmp_pd_le_os(__m128d a, __m128d b) { - // CHECK-LABEL: test_mm_cmp_pd_le_os - // CHECK: fcmp ole <2 x double> %{{.*}}, %{{.*}} - return _mm_cmp_pd(a, b, _CMP_LE_OS); -} - -__m128d test_mm_cmp_pd_unord_q(__m128d a, __m128d b) { - // CHECK-LABEL: test_mm_cmp_pd_unord_q - // CHECK: fcmp uno <2 x double> %{{.*}}, %{{.*}} - return _mm_cmp_pd(a, b, _CMP_UNORD_Q); -} - -__m128d test_mm_cmp_pd_neq_uq(__m128d a, __m128d b) { - // CHECK-LABEL: test_mm_cmp_pd_neq_uq - // CHECK: fcmp une <2 x double> %{{.*}}, %{{.*}} - return _mm_cmp_pd(a, b, _CMP_NEQ_UQ); -} - -__m128d test_mm_cmp_pd_nlt_us(__m128d a, __m128d b) { - // CHECK-LABEL: test_mm_cmp_pd_nlt_us - // CHECK: fcmp uge <2 x double> %{{.*}}, %{{.*}} - return _mm_cmp_pd(a, b, _CMP_NLT_US); -} - -__m128d test_mm_cmp_pd_nle_us(__m128d a, __m128d b) { - // CHECK-LABEL: test_mm_cmp_pd_nle_us - // CHECK: fcmp ugt <2 x double> %{{.*}}, %{{.*}} - return _mm_cmp_pd(a, b, _CMP_NLE_US); -} - -__m128d test_mm_cmp_pd_ord_q(__m128d a, __m128d b) { - // CHECK-LABEL: test_mm_cmp_pd_ord_q - // CHECK: fcmp ord <2 x double> %{{.*}}, %{{.*}} - return _mm_cmp_pd(a, b, _CMP_ORD_Q); -} - -__m128d test_mm_cmp_sd(__m128d A, __m128d B) { - // CHECK-LABEL: test_mm_cmp_sd - // CHECK: call <2 x double> @llvm.x86.sse2.cmp.sd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, i8 7) - return _mm_cmp_sd(A, B, _CMP_ORD_Q); -} diff --git a/clang/test/CodeGen/X86/x86-bswap.c b/clang/test/CodeGen/X86/x86-bswap.c index fb4852c524087e..589dd83606983c 100644 --- a/clang/test/CodeGen/X86/x86-bswap.c +++ b/clang/test/CodeGen/X86/x86-bswap.c @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -x c -ffreestanding %s -triple=x86_64-apple-darwin -emit-llvm -o - | FileCheck %s -// RUN: %clang_cc1 -x c++ -std=c++11 -ffreestanding %s -triple=x86_64-apple-darwin -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -x c -ffreestanding %s -triple=x86_64-apple-darwin -no-enable-noundef-analysis -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -x c++ -std=c++11 -ffreestanding %s -triple=x86_64-apple-darwin -no-enable-noundef-analysis -emit-llvm -o - | FileCheck %s #include diff --git a/clang/test/CodeGen/aarch64-ls64.c b/clang/test/CodeGen/aarch64-ls64.c index 39def71d71c7b0..8a61a9643dd3de 100644 --- a/clang/test/CodeGen/aarch64-ls64.c +++ b/clang/test/CodeGen/aarch64-ls64.c @@ -206,7 +206,7 @@ EXTERN_C void test_st64b(void) // CHECK-CXX-NEXT: [[TMP14:%.*]] = load i64, ptr [[TMP13]], align 8 // CHECK-CXX-NEXT: [[TMP15:%.*]] = getelementptr i64, ptr [[AGG_TMP]], i32 7 // CHECK-CXX-NEXT: [[TMP16:%.*]] = load i64, ptr [[TMP15]], align 8 -// CHECK-CXX-NEXT: [[TMP17:%.*]] = call i64 @llvm.aarch64.st64bv(ptr [[TMP1]], i64 [[TMP2]], i64 [[TMP4]], i64 [[TMP6]], i64 [[TMP8]], i64 [[TMP10]], i64 [[TMP12]], i64 [[TMP14]], i64 [[TMP16]]) +// CHECK-CXX-NEXT: [[TMP17:%.*]] = call noundef i64 @llvm.aarch64.st64bv(ptr [[TMP1]], i64 [[TMP2]], i64 [[TMP4]], i64 [[TMP6]], i64 [[TMP8]], i64 [[TMP10]], i64 [[TMP12]], i64 [[TMP14]], i64 [[TMP16]]) // CHECK-CXX-NEXT: store i64 [[TMP17]], ptr @status, align 8 // CHECK-CXX-NEXT: ret void // @@ -269,7 +269,7 @@ EXTERN_C void test_st64bv(void) // CHECK-CXX-NEXT: [[TMP14:%.*]] = load i64, ptr [[TMP13]], align 8 // CHECK-CXX-NEXT: [[TMP15:%.*]] = getelementptr i64, ptr [[AGG_TMP]], i32 7 // CHECK-CXX-NEXT: [[TMP16:%.*]] = load i64, ptr [[TMP15]], align 8 -// CHECK-CXX-NEXT: [[TMP17:%.*]] = call i64 @llvm.aarch64.st64bv0(ptr [[TMP1]], i64 [[TMP2]], i64 [[TMP4]], i64 [[TMP6]], i64 [[TMP8]], i64 [[TMP10]], i64 [[TMP12]], i64 [[TMP14]], i64 [[TMP16]]) +// CHECK-CXX-NEXT: [[TMP17:%.*]] = call noundef i64 @llvm.aarch64.st64bv0(ptr [[TMP1]], i64 [[TMP2]], i64 [[TMP4]], i64 [[TMP6]], i64 [[TMP8]], i64 [[TMP10]], i64 [[TMP12]], i64 [[TMP14]], i64 [[TMP16]]) // CHECK-CXX-NEXT: store i64 [[TMP17]], ptr @status, align 8 // CHECK-CXX-NEXT: ret void // diff --git a/clang/test/CodeGen/address-space.c b/clang/test/CodeGen/address-space.c index 83a434d88b8e8b..c92fc0dd968706 100644 --- a/clang/test/CodeGen/address-space.c +++ b/clang/test/CodeGen/address-space.c @@ -53,7 +53,7 @@ void test4(MyStruct __attribute__((address_space(2))) *pPtr) { // X86: [[ALLOCA:%.*]] = alloca ptr addrspace(1) // X86-NEXT: store ptr addrspace(1) %arg, ptr [[ALLOCA]] // X86-NEXT: load ptr addrspace(1), ptr [[ALLOCA]] -// X86-NEXT: getelementptr i8, ptr addrspace(1) +// X86-NEXT: getelementptr inbounds i8, ptr addrspace(1) // X86-NEXT: ret ptr addrspace(1) void __attribute__((address_space(1)))* void_ptr_arithmetic_test(void __attribute__((address_space(1))) *arg) { diff --git a/clang/test/CodeGen/attr-counted-by.c b/clang/test/CodeGen/attr-counted-by.c new file mode 100644 index 00000000000000..a7eb0da6dd282a --- /dev/null +++ b/clang/test/CodeGen/attr-counted-by.c @@ -0,0 +1,227 @@ +// 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 + +typedef long unsigned int size_t; + +struct annotated { + unsigned long flags; + int count; + int array[] __counted_by(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: [[COUNT:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED:%.*]], ptr [[P]], i64 0, i32 1 +// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load i32, ptr [[COUNT]], align 8, !tbaa [[TBAA2:![0-9]+]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = sext i32 [[INDEX]] to i64, !nosanitize !6 +// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = zext i32 [[TMP0]] to i64, !nosanitize !6 +// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = icmp ult i64 [[TMP1]], [[TMP2]], !nosanitize !6 +// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP3]], label [[CONT7:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF7:![0-9]+]], !nosanitize !6 +// SANITIZE-WITH-ATTR: handler.out_of_bounds: +// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize !6 +// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB2:[0-9]+]], i64 [[TMP4]]) #[[ATTR2:[0-9]+]], !nosanitize !6 +// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize !6 +// SANITIZE-WITH-ATTR: cont7: +// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED]], ptr [[P]], i64 0, i32 2, i64 [[TMP1]] +// SANITIZE-WITH-ATTR-NEXT: store i32 [[VAL]], ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] +// 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: [[COUNT:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED:%.*]], ptr [[P]], i64 0, i32 1 +// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load i32, ptr [[COUNT]], align 8, !tbaa [[TBAA2]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = zext i32 [[TMP0]] to i64, !nosanitize !6 +// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = icmp ugt i64 [[TMP1]], [[INDEX]], !nosanitize !6 +// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP2]], label [[CONT12:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF7]], !nosanitize !6 +// 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]]) #[[ATTR2]], !nosanitize !6 +// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize !6 +// SANITIZE-WITH-ATTR: cont12: +// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED]], ptr [[P]], i64 0, i32 2, i64 [[INDEX]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = shl i32 [[TMP0]], 2 +// SANITIZE-WITH-ATTR-NEXT: store i32 [[TMP3]], ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] +// 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: [[COUNT:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED:%.*]], ptr [[P]], i64 0, i32 1 +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load i32, ptr [[COUNT]], align 8, !tbaa [[TBAA2]] +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = shl i32 [[TMP0]], 2 +// 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 [[TMP1]], 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 #[[ATTR1:[0-9]+]] { +// 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 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: [[COUNT:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED:%.*]], ptr [[P]], i64 0, i32 1 +// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load i32, ptr [[COUNT]], align 8, !tbaa [[TBAA2]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = zext i32 [[TMP0]] to i64, !nosanitize !6 +// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = icmp ugt i64 [[TMP1]], [[INDEX]], !nosanitize !6 +// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP2]], label [[CONT12:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF7]], !nosanitize !6 +// 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]]) #[[ATTR2]], !nosanitize !6 +// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize !6 +// SANITIZE-WITH-ATTR: cont12: +// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED]], ptr [[P]], i64 0, i32 2, i64 [[INDEX]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = shl i32 [[TMP0]], 2 +// SANITIZE-WITH-ATTR-NEXT: [[CONV:%.*]] = add i32 [[TMP3]], 16 +// SANITIZE-WITH-ATTR-NEXT: store i32 [[CONV]], ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] +// 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: [[COUNT:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED:%.*]], ptr [[P]], i64 0, i32 1 +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load i32, ptr [[COUNT]], align 8, !tbaa [[TBAA2]] +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = shl i32 [[TMP0]], 2 +// NO-SANITIZE-WITH-ATTR-NEXT: [[CONV:%.*]] = add i32 [[TMP1]], 16 +// 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 #[[ATTR1]] { +// 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); +} + +struct annotated_with_anon_struct { + unsigned long flags; + struct { + unsigned char count; + int array[] __counted_by(count); + }; +}; + +// SANITIZE-WITH-ATTR-LABEL: define dso_local void @test4( +// 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_ANNOTATED_WITH_ANON_STRUCT:%.*]], ptr [[P]], i64 0, i32 1 +// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = load i8, ptr [[TMP0]], align 8, !tbaa [[TBAA8:![0-9]+]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = sext i32 [[INDEX]] to i64, !nosanitize !6 +// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = zext i8 [[TMP1]] to i64, !nosanitize !6 +// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = icmp ult i64 [[TMP2]], [[TMP3]], !nosanitize !6 +// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP4]], label [[CONT18:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF7]], !nosanitize !6 +// SANITIZE-WITH-ATTR: handler.out_of_bounds: +// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize !6 +// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB6:[0-9]+]], i64 [[TMP5]]) #[[ATTR2]], !nosanitize !6 +// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize !6 +// SANITIZE-WITH-ATTR: cont18: +// SANITIZE-WITH-ATTR-NEXT: [[ARRAY:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 12 +// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i32], ptr [[ARRAY]], i64 0, i64 [[TMP2]] +// SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = shl i8 [[TMP1]], 2 +// SANITIZE-WITH-ATTR-NEXT: [[CONV:%.*]] = zext i8 [[TMP6]] to i32 +// SANITIZE-WITH-ATTR-NEXT: store i32 [[CONV]], ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] +// 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:%.*]]) local_unnamed_addr #[[ATTR1]] { +// NO-SANITIZE-WITH-ATTR-NEXT: entry: +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED_WITH_ANON_STRUCT:%.*]], ptr [[P]], i64 0, i32 1 +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = load i8, ptr [[TMP0]], align 8, !tbaa [[TBAA6:![0-9]+]] +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = shl i8 [[TMP1]], 2 +// NO-SANITIZE-WITH-ATTR-NEXT: [[CONV:%.*]] = zext i8 [[TMP2]] to i32 +// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAY:%.*]] = 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 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 @test4( +// 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 i8, ptr [[P]], i64 12 +// 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 @test4( +// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR1]] { +// NO-SANITIZE-WITHOUT-ATTR-NEXT: entry: +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAY:%.*]] = 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 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 test4(struct annotated_with_anon_struct *p, int index) { + p->array[index] = __builtin_dynamic_object_size(p->array, 1); +} diff --git a/clang/test/CodeGen/attr-target-version.c b/clang/test/CodeGen/attr-target-version.c index 8d4a4f137569cc..a7cd6f7bf802c5 100644 --- a/clang/test/CodeGen/attr-target-version.c +++ b/clang/test/CodeGen/attr-target-version.c @@ -35,7 +35,7 @@ inline int __attribute__((target_version("sve+sve-bf16"))) fmv_inline(void) { re inline int __attribute__((target_version("sve2-aes+sve2-sha3"))) fmv_inline(void) { return 5; } inline int __attribute__((target_version("sve2+sve2-pmull128+sve2-bitperm"))) fmv_inline(void) { return 9; } inline int __attribute__((target_version("sve2-sm4+memtag2"))) fmv_inline(void) { return 10; } -inline int __attribute__((target_version("memtag3"))) fmv_inline(void) { return 11; } +inline int __attribute__((target_version("memtag3+rcpc3"))) fmv_inline(void) { return 11; } inline int __attribute__((target_version("default"))) fmv_inline(void) { return 3; } __attribute__((target_version("ls64"))) int fmv_e(void); @@ -289,68 +289,68 @@ int hoo(void) { // CHECK-NEXT: ret ptr @fmv_inline._Msha3Mi8mmMf32mm // CHECK: resolver_else6: // CHECK-NEXT: [[TMP16:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8 -// CHECK-NEXT: [[TMP17:%.*]] = and i64 [[TMP16]], 19791209299968 -// CHECK-NEXT: [[TMP18:%.*]] = icmp eq i64 [[TMP17]], 19791209299968 +// CHECK-NEXT: [[TMP17:%.*]] = and i64 [[TMP16]], 288265560523800576 +// CHECK-NEXT: [[TMP18:%.*]] = icmp eq i64 [[TMP17]], 288265560523800576 // CHECK-NEXT: [[TMP19:%.*]] = and i1 true, [[TMP18]] // CHECK-NEXT: br i1 [[TMP19]], label [[RESOLVER_RETURN7:%.*]], label [[RESOLVER_ELSE8:%.*]] // CHECK: resolver_return7: -// CHECK-NEXT: ret ptr @fmv_inline._Msve2-sm4Mmemtag2 +// CHECK-NEXT: ret ptr @fmv_inline._Mrcpc3Mmemtag3 // CHECK: resolver_else8: // CHECK-NEXT: [[TMP20:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8 -// CHECK-NEXT: [[TMP21:%.*]] = and i64 [[TMP20]], 1236950581248 -// CHECK-NEXT: [[TMP22:%.*]] = icmp eq i64 [[TMP21]], 1236950581248 +// CHECK-NEXT: [[TMP21:%.*]] = and i64 [[TMP20]], 19791209299968 +// CHECK-NEXT: [[TMP22:%.*]] = icmp eq i64 [[TMP21]], 19791209299968 // CHECK-NEXT: [[TMP23:%.*]] = and i1 true, [[TMP22]] // CHECK-NEXT: br i1 [[TMP23]], label [[RESOLVER_RETURN9:%.*]], label [[RESOLVER_ELSE10:%.*]] // CHECK: resolver_return9: -// CHECK-NEXT: ret ptr @fmv_inline._Msve2-aesMsve2-sha3 +// CHECK-NEXT: ret ptr @fmv_inline._Msve2-sm4Mmemtag2 // CHECK: resolver_else10: // CHECK-NEXT: [[TMP24:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8 -// CHECK-NEXT: [[TMP25:%.*]] = and i64 [[TMP24]], 4295098368 -// CHECK-NEXT: [[TMP26:%.*]] = icmp eq i64 [[TMP25]], 4295098368 +// CHECK-NEXT: [[TMP25:%.*]] = and i64 [[TMP24]], 1236950581248 +// CHECK-NEXT: [[TMP26:%.*]] = icmp eq i64 [[TMP25]], 1236950581248 // CHECK-NEXT: [[TMP27:%.*]] = and i1 true, [[TMP26]] // CHECK-NEXT: br i1 [[TMP27]], label [[RESOLVER_RETURN11:%.*]], label [[RESOLVER_ELSE12:%.*]] // CHECK: resolver_return11: -// CHECK-NEXT: ret ptr @fmv_inline._MditMsve-ebf16 +// CHECK-NEXT: ret ptr @fmv_inline._Msve2-aesMsve2-sha3 // CHECK: resolver_else12: // CHECK-NEXT: [[TMP28:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8 -// CHECK-NEXT: [[TMP29:%.*]] = and i64 [[TMP28]], 3221225472 -// CHECK-NEXT: [[TMP30:%.*]] = icmp eq i64 [[TMP29]], 3221225472 +// CHECK-NEXT: [[TMP29:%.*]] = and i64 [[TMP28]], 4295098368 +// CHECK-NEXT: [[TMP30:%.*]] = icmp eq i64 [[TMP29]], 4295098368 // CHECK-NEXT: [[TMP31:%.*]] = and i1 true, [[TMP30]] // CHECK-NEXT: br i1 [[TMP31]], label [[RESOLVER_RETURN13:%.*]], label [[RESOLVER_ELSE14:%.*]] // CHECK: resolver_return13: -// CHECK-NEXT: ret ptr @fmv_inline._MsveMsve-bf16 +// CHECK-NEXT: ret ptr @fmv_inline._MditMsve-ebf16 // CHECK: resolver_else14: // CHECK-NEXT: [[TMP32:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8 -// CHECK-NEXT: [[TMP33:%.*]] = and i64 [[TMP32]], 20971520 -// CHECK-NEXT: [[TMP34:%.*]] = icmp eq i64 [[TMP33]], 20971520 +// CHECK-NEXT: [[TMP33:%.*]] = and i64 [[TMP32]], 3221225472 +// CHECK-NEXT: [[TMP34:%.*]] = icmp eq i64 [[TMP33]], 3221225472 // CHECK-NEXT: [[TMP35:%.*]] = and i1 true, [[TMP34]] // CHECK-NEXT: br i1 [[TMP35]], label [[RESOLVER_RETURN15:%.*]], label [[RESOLVER_ELSE16:%.*]] // CHECK: resolver_return15: -// CHECK-NEXT: ret ptr @fmv_inline._MrcpcMfrintts +// CHECK-NEXT: ret ptr @fmv_inline._MsveMsve-bf16 // CHECK: resolver_else16: // CHECK-NEXT: [[TMP36:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8 -// CHECK-NEXT: [[TMP37:%.*]] = and i64 [[TMP36]], 8650752 -// CHECK-NEXT: [[TMP38:%.*]] = icmp eq i64 [[TMP37]], 8650752 +// CHECK-NEXT: [[TMP37:%.*]] = and i64 [[TMP36]], 20971520 +// CHECK-NEXT: [[TMP38:%.*]] = icmp eq i64 [[TMP37]], 20971520 // CHECK-NEXT: [[TMP39:%.*]] = and i1 true, [[TMP38]] // CHECK-NEXT: br i1 [[TMP39]], label [[RESOLVER_RETURN17:%.*]], label [[RESOLVER_ELSE18:%.*]] // CHECK: resolver_return17: -// CHECK-NEXT: ret ptr @fmv_inline._MdpbMrcpc2 +// CHECK-NEXT: ret ptr @fmv_inline._MrcpcMfrintts // CHECK: resolver_else18: // CHECK-NEXT: [[TMP40:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8 -// CHECK-NEXT: [[TMP41:%.*]] = and i64 [[TMP40]], 1572864 -// CHECK-NEXT: [[TMP42:%.*]] = icmp eq i64 [[TMP41]], 1572864 +// CHECK-NEXT: [[TMP41:%.*]] = and i64 [[TMP40]], 8650752 +// CHECK-NEXT: [[TMP42:%.*]] = icmp eq i64 [[TMP41]], 8650752 // CHECK-NEXT: [[TMP43:%.*]] = and i1 true, [[TMP42]] // CHECK-NEXT: br i1 [[TMP43]], label [[RESOLVER_RETURN19:%.*]], label [[RESOLVER_ELSE20:%.*]] // CHECK: resolver_return19: -// CHECK-NEXT: ret ptr @fmv_inline._Mdpb2Mjscvt +// CHECK-NEXT: ret ptr @fmv_inline._MdpbMrcpc2 // CHECK: resolver_else20: // CHECK-NEXT: [[TMP44:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8 -// CHECK-NEXT: [[TMP45:%.*]] = and i64 [[TMP44]], 35184372088832 -// CHECK-NEXT: [[TMP46:%.*]] = icmp eq i64 [[TMP45]], 35184372088832 +// CHECK-NEXT: [[TMP45:%.*]] = and i64 [[TMP44]], 1572864 +// CHECK-NEXT: [[TMP46:%.*]] = icmp eq i64 [[TMP45]], 1572864 // CHECK-NEXT: [[TMP47:%.*]] = and i1 true, [[TMP46]] // CHECK-NEXT: br i1 [[TMP47]], label [[RESOLVER_RETURN21:%.*]], label [[RESOLVER_ELSE22:%.*]] // CHECK: resolver_return21: -// CHECK-NEXT: ret ptr @fmv_inline._Mmemtag3 +// CHECK-NEXT: ret ptr @fmv_inline._Mdpb2Mjscvt // CHECK: resolver_else22: // CHECK-NEXT: ret ptr @fmv_inline // CHECK-LABEL: @fmv_e.resolver( @@ -437,7 +437,7 @@ int hoo(void) { // CHECK-LABEL: @fmv_inline._Msve2-sm4Mmemtag2( // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 10 -// CHECK-LABEL: @fmv_inline._Mmemtag3( +// CHECK-LABEL: @fmv_inline._Mrcpc3Mmemtag3( // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 11 // CHECK-LABEL: @fmv_inline( @@ -534,7 +534,7 @@ int hoo(void) { // CHECK: attributes #20 = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+ls64,+neon,+sve,+sve2,+sve2-aes,+sve2-sha3" } // CHECK: attributes #21 = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+ls64,+neon,+sve,+sve2,+sve2-aes,+sve2-bitperm" } // CHECK: attributes #22 = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+ls64,+mte,+neon,+sve,+sve2,+sve2-sm4" } -// CHECK: attributes #23 = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fullfp16,+ls64,+mte" } +// CHECK: attributes #23 = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fullfp16,+ls64,+mte,+rcpc,+rcpc3" } // CHECK: attributes #24 = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fullfp16,+ls64,+sb" } // CHECK-NOFMV: attributes #0 = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="-fmv" } diff --git a/clang/test/CodeGen/auto.c b/clang/test/CodeGen/auto.c new file mode 100644 index 00000000000000..e5bc1bf66138f5 --- /dev/null +++ b/clang/test/CodeGen/auto.c @@ -0,0 +1,41 @@ +// RUN: %clang_cc1 -std=c2x -emit-llvm %s -o - | FileCheck %s + +void basic_types(void) { + auto nb = 4; // CHECK: alloca i32 + auto dbl = 4.3; // CHECK: alloca double + auto lng = 4UL; // CHECK: alloca i{{32|64}} + auto bl = true; // CHECK: alloca i8 + auto chr = 'A'; // CHECK: alloca i{{8|32}} + auto str = "Test"; // CHECK: alloca ptr + auto str2[] = "Test"; // CHECK: alloca [5 x i8] + auto nptr = nullptr; // CHECK: alloca ptr +} + +void misc_declarations(void) { + // FIXME: this should end up being rejected when we implement underspecified + // declarations in N3006. + auto strct_ptr = (struct { int a; } *)0; // CHECK: alloca ptr + auto int_cl = (int){13}; // CHECK: alloca i32 + auto double_cl = (double){2.5}; // CHECK: alloca double + + auto se = ({ // CHECK: alloca i32 + auto snb = 12; // CHECK: alloca i32 + snb; + }); +} + +void loop(void) { + auto j = 4; // CHECK: alloca i32 + for (auto i = j; i < 2 * j; i++); // CHECK: alloca i32 +} + +#define AUTO_MACRO(_NAME, ARG, ARG2, ARG3) auto _NAME = ARG + (ARG2 / ARG3); + +#define AUTO_INT_MACRO(_NAME, ARG, ARG2, ARG3) auto _NAME = (ARG ^ ARG2) & ARG3; + +int macros(int in_int) { + auto a = in_int + 1; // CHECK: alloca i32 + AUTO_MACRO(b, 1.3, 2.5f, 3); // CHECK: alloca double + AUTO_INT_MACRO(c, 64, 23, 0xff); // CHECK: alloca i32 + return (a + (int)b) - c; // CHECK: ret i32 %{{.*}} +} diff --git a/clang/test/CodeGen/catch-nullptr-and-nonzero-offset.c b/clang/test/CodeGen/catch-nullptr-and-nonzero-offset.c index 0e0a9b157464a6..015102940890a5 100644 --- a/clang/test/CodeGen/catch-nullptr-and-nonzero-offset.c +++ b/clang/test/CodeGen/catch-nullptr-and-nonzero-offset.c @@ -35,6 +35,7 @@ // CHECK-SANITIZE-ANYRECOVER-C-DAG: @[[LINE_1400:.*]] = {{.*}}, i32 1400, i32 15 } } // CHECK-SANITIZE-ANYRECOVER-DAG: @[[LINE_1500:.*]] = {{.*}}, i32 1500, i32 15 } } // CHECK-SANITIZE-ANYRECOVER-DAG: @[[LINE_1600:.*]] = {{.*}}, i32 1600, i32 15 } } +// CHECK-SANITIZE-ANYRECOVER-DAG: @[[LINE_1700:.*]] = {{.*}}, i32 1700, i32 15 } } #ifdef __cplusplus extern "C" { @@ -427,6 +428,48 @@ char *allones_allones_OK(void) { return base + offset; } +// C++ does not allow void* arithmetic even as a GNU extension. Replace void* +// with char* in that case to keep test expectations the same. +#ifdef __cplusplus +char *void_ptr(char *base, unsigned long offset) { +#else +char *void_ptr(void *base, unsigned long offset) { +#endif + // CHECK: define{{.*}} ptr @void_ptr(ptr noundef %[[BASE:.*]], i64 noundef %[[OFFSET:.*]]) + // CHECK-NEXT: [[ENTRY:.*]]: + // CHECK-NEXT: %[[BASE_ADDR:.*]] = alloca ptr, align 8 + // CHECK-NEXT: %[[OFFSET_ADDR:.*]] = alloca i64, align 8 + // CHECK-NEXT: store ptr %[[BASE]], ptr %[[BASE_ADDR]], align 8 + // CHECK-NEXT: store i64 %[[OFFSET]], ptr %[[OFFSET_ADDR]], align 8 + // CHECK-NEXT: %[[BASE_RELOADED:.*]] = load ptr, ptr %[[BASE_ADDR]], align 8 + // CHECK-NEXT: %[[OFFSET_RELOADED:.*]] = load i64, ptr %[[OFFSET_ADDR]], align 8 + // CHECK-NEXT: %[[ADD_PTR:.*]] = getelementptr inbounds i8, ptr %[[BASE_RELOADED]], i64 %[[OFFSET_RELOADED]] + // CHECK-SANITIZE-NEXT: %[[COMPUTED_OFFSET_AGGREGATE:.*]] = call { i64, i1 } @llvm.smul.with.overflow.i64(i64 1, i64 %[[OFFSET_RELOADED]]), !nosanitize + // CHECK-SANITIZE-NEXT: %[[COMPUTED_OFFSET_OVERFLOWED:.*]] = extractvalue { i64, i1 } %[[COMPUTED_OFFSET_AGGREGATE]], 1, !nosanitize + // CHECK-SANITIZE-NEXT: %[[OR_OV:.+]] = or i1 %[[COMPUTED_OFFSET_OVERFLOWED]], false, !nosanitize + // CHECK-SANITIZE-NEXT: %[[COMPUTED_OFFSET:.*]] = extractvalue { i64, i1 } %[[COMPUTED_OFFSET_AGGREGATE]], 0, !nosanitize + // CHECK-SANITIZE-NEXT: %[[BASE_RELOADED_INT:.*]] = ptrtoint ptr %[[BASE_RELOADED]] to i64, !nosanitize + // CHECK-SANITIZE-NEXT: %[[COMPUTED_GEP:.*]] = add i64 %[[BASE_RELOADED_INT]], %[[COMPUTED_OFFSET]], !nosanitize + // CHECK-SANITIZE-NEXT: %[[BASE_IS_NOT_NULLPTR:.*]] = icmp ne ptr %[[BASE_RELOADED]], null, !nosanitize + // CHECK-SANITIZE-NEXT: %[[COMPUTED_GEP_IS_NOT_NULL:.*]] = icmp ne i64 %[[COMPUTED_GEP]], 0, !nosanitize + // CHECK-SANITIZE-C-NEXT: %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = and i1 %[[BASE_IS_NOT_NULLPTR]], %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize + // CHECK-SANITIZE-CPP-NEXT: %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = icmp eq i1 %[[BASE_IS_NOT_NULLPTR]], %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize + // CHECK-SANITIZE-NEXT: %[[COMPUTED_OFFSET_DID_NOT_OVERFLOW:.*]] = xor i1 %[[OR_OV]], true, !nosanitize + // CHECK-SANITIZE-NEXT: %[[COMPUTED_GEP_IS_UGE_BASE:.*]] = icmp uge i64 %[[COMPUTED_GEP]], %[[BASE_RELOADED_INT]], !nosanitize + // CHECK-SANITIZE-NEXT: %[[GEP_DID_NOT_OVERFLOW:.*]] = and i1 %[[COMPUTED_GEP_IS_UGE_BASE]], %[[COMPUTED_OFFSET_DID_NOT_OVERFLOW]], !nosanitize + // CHECK-SANITIZE-NEXT: %[[GEP_IS_OKAY:.*]] = and i1 %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL]], %[[GEP_DID_NOT_OVERFLOW]], !nosanitize + // CHECK-SANITIZE-NEXT: br i1 %[[GEP_IS_OKAY]], label %[[CONT:.*]], label %[[HANDLER_POINTER_OVERFLOW:[^,]+]],{{.*}} !nosanitize + // CHECK-SANITIZE: [[HANDLER_POINTER_OVERFLOW]]: + // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_pointer_overflow_abort(ptr @[[LINE_1700]], i64 %[[BASE_RELOADED_INT]], i64 %[[COMPUTED_GEP]]) + // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_pointer_overflow(ptr @[[LINE_1700]], i64 %[[BASE_RELOADED_INT]], i64 %[[COMPUTED_GEP]]) + // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.ubsantrap(i8 19){{.*}}, !nosanitize + // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize + // CHECK-SANITIZE: [[CONT]]: + // CHECK-NEXT: ret ptr %[[ADD_PTR]] +#line 1700 + return base + offset; +} + #ifdef __cplusplus } #endif diff --git a/clang/test/CodeGen/code-coverage.c b/clang/test/CodeGen/code-coverage.c index af02a6ddaef990..d7994bab35d81a 100644 --- a/clang/test/CodeGen/code-coverage.c +++ b/clang/test/CodeGen/code-coverage.c @@ -15,10 +15,10 @@ // RUN: %clang_cc1 -emit-llvm-bc -o /dev/null -fdebug-pass-manager -coverage-data-file=/dev/null %s 2>&1 | FileCheck --check-prefix=NEWPM %s // RUN: %clang_cc1 -emit-llvm-bc -o /dev/null -fdebug-pass-manager -coverage-data-file=/dev/null -O3 %s 2>&1 | FileCheck --check-prefix=NEWPM-O3 %s -// NEWPM-NOT: Running pass +// NEWPM: Running pass: VerifierPass // NEWPM: Running pass: GCOVProfilerPass -// NEWPM-O3-NOT: Running pass +// NEWPM-O3: Running pass: VerifierPass // NEWPM-O3: Running pass: Annotation2MetadataPass // NEWPM-O3: Running pass: ForceFunctionAttrsPass // NEWPM-O3: Running pass: GCOVProfilerPass diff --git a/clang/test/CodeGen/constantexpr-fneg.c b/clang/test/CodeGen/constantexpr-fneg.c index f82b3ff726578b..3cd4db34f61acb 100644 --- a/clang/test/CodeGen/constantexpr-fneg.c +++ b/clang/test/CodeGen/constantexpr-fneg.c @@ -8,9 +8,11 @@ // CHECK: entry: // CHECK-NEXT: %retval = alloca i32 // CHECK-NEXT: store i32 0, ptr %retval +// CHECK-NEXT: [[ZEXT:%.*]] = zext i1 true to i32 +// CHECK-NEXT: [[SITOFP:%.*]] = sitofp i32 [[ZEXT]] to float // CHECK-NEXT: [[LV:%.*]] = load ptr, ptr @c -// CHECK-NEXT: store float 1.000000e+00, ptr [[LV]], align 4 -// CHECK-NEXT: [[FNEG:%.*]] = fneg float 1.000000e+00 +// CHECK-NEXT: store float [[SITOFP]], ptr [[LV]], align 4 +// CHECK-NEXT: [[FNEG:%.*]] = fneg float [[SITOFP]] // CHECK-NEXT: [[CONV:%.*]] = fptosi float [[FNEG]] to i32 // CHECK-NEXT: ret i32 [[CONV]] diff --git a/clang/test/CodeGen/fp-contract-fast-pragma.cpp b/clang/test/CodeGen/fp-contract-fast-pragma.cpp index a88ddac4037bb6..0bb01d6e17a1d6 100644 --- a/clang/test/CodeGen/fp-contract-fast-pragma.cpp +++ b/clang/test/CodeGen/fp-contract-fast-pragma.cpp @@ -46,7 +46,7 @@ float fp_contract_3(float a, float b, float c) { // CHECK: %[[M:.+]] = fmul contract float %a, %b // CHECK-NEXT: fadd contract float %[[M]], %c // STRICT: %[[M:.+]] = tail call contract float @llvm.experimental.constrained.fmul.f32(float %a, float %b, metadata !"round.tonearest", metadata !"fpexcept.strict") - // STRICT-NEXT: tail call contract float @llvm.experimental.constrained.fadd.f32(float %[[M]], float %c, metadata !"round.tonearest", metadata !"fpexcept.strict") + // STRICT-NEXT: tail call contract noundef float @llvm.experimental.constrained.fadd.f32(float %[[M]], float %c, metadata !"round.tonearest", metadata !"fpexcept.strict") return template_muladd(a, b, c); } diff --git a/clang/test/CodeGen/fp-contract-on-pragma.cpp b/clang/test/CodeGen/fp-contract-on-pragma.cpp index 812a7176b515ce..bfd82a8022e606 100644 --- a/clang/test/CodeGen/fp-contract-on-pragma.cpp +++ b/clang/test/CodeGen/fp-contract-on-pragma.cpp @@ -31,7 +31,7 @@ T template_muladd(T a, T b, T c) { float fp_contract_3(float a, float b, float c) { // CHECK: _Z13fp_contract_3fff - // CHECK: tail call float @llvm.fmuladd + // CHECK: tail call noundef float @llvm.fmuladd return template_muladd(a, b, c); } diff --git a/clang/test/CodeGen/fp-contract-pragma.cpp b/clang/test/CodeGen/fp-contract-pragma.cpp index a628d7c1bd228a..c503bf69147c4a 100644 --- a/clang/test/CodeGen/fp-contract-pragma.cpp +++ b/clang/test/CodeGen/fp-contract-pragma.cpp @@ -31,7 +31,7 @@ T template_muladd(T a, T b, T c) { float fp_contract_3(float a, float b, float c) { // CHECK: _Z13fp_contract_3fff -// CHECK: tail call float @llvm.fmuladd +// CHECK: tail call noundef float @llvm.fmuladd return template_muladd(a, b, c); } diff --git a/clang/test/CodeGen/large-data-threshold.c b/clang/test/CodeGen/large-data-threshold.c index 650a7fbb0094e6..29ae19e9b71899 100644 --- a/clang/test/CodeGen/large-data-threshold.c +++ b/clang/test/CodeGen/large-data-threshold.c @@ -5,7 +5,7 @@ // 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 0} +// IR-DEFAULT: !{i32 1, !"Large Data Threshold", i64 65535} // IR-CUSTOM: !{i32 1, !"Large Data Threshold", i64 200} // ASM-SMALL-NOT: movabsq diff --git a/clang/test/CodeGen/lto-newpm-pipeline.c b/clang/test/CodeGen/lto-newpm-pipeline.c index 1aaa7d46f3ff06..f58757efbf686f 100644 --- a/clang/test/CodeGen/lto-newpm-pipeline.c +++ b/clang/test/CodeGen/lto-newpm-pipeline.c @@ -25,7 +25,9 @@ // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm-bc -o /dev/null -mllvm -verify-analysis-invalidation=0 -fdebug-pass-manager -flto=thin -Oz %s 2>&1 | FileCheck %s \ // RUN: -check-prefix=CHECK-THIN-OPTIMIZED -// CHECK-FULL-O0: Running pass: AlwaysInlinerPass +// CHECK-FULL-O0: Running pass: VerifierPass +// CHECK-FULL-O0-NEXT: Running analysis: VerifierAnalysis +// CHECK-FULL-O0-NEXT: Running pass: AlwaysInlinerPass // CHECK-FULL-O0-NEXT: Running analysis: InnerAnalysisManagerProxy // CHECK-FULL-O0-NEXT: Running analysis: ProfileSummaryAnalysis // CHECK-FULL-O0-NEXT: Running pass: CoroConditionalWrapper @@ -34,10 +36,11 @@ // CHECK-FULL-O0-NEXT: Running pass: AnnotationRemarksPass // CHECK-FULL-O0-NEXT: Running analysis: TargetLibraryAnalysis // CHECK-FULL-O0-NEXT: Running pass: VerifierPass -// CHECK-FULL-O0-NEXT: Running analysis: VerifierAnalysis // CHECK-FULL-O0-NEXT: Running pass: BitcodeWriterPass -// CHECK-THIN-O0: Running pass: AlwaysInlinerPass +// CHECK-THIN-O0: Running pass: VerifierPass +// CHECK-THIN-O0-NEXT: Running analysis: VerifierAnalysis +// CHECK-THIN-O0-NEXT: Running pass: AlwaysInlinerPass // CHECK-THIN-O0-NEXT: Running analysis: InnerAnalysisManagerProxy // CHECK-THIN-O0-NEXT: Running analysis: ProfileSummaryAnalysis // CHECK-THIN-O0-NEXT: Running pass: CoroConditionalWrapper @@ -46,7 +49,6 @@ // CHECK-THIN-O0-NEXT: Running pass: AnnotationRemarksPass // CHECK-THIN-O0-NEXT: Running analysis: TargetLibraryAnalysis // CHECK-THIN-O0-NEXT: Running pass: VerifierPass -// CHECK-THIN-O0-NEXT: Running analysis: VerifierAnalysis // CHECK-THIN-O0-NEXT: Running pass: ThinLTOBitcodeWriterPass // TODO: The LTO pre-link pipeline currently invokes diff --git a/clang/test/CodeGen/target-features-error-2.c b/clang/test/CodeGen/target-features-error-2.c index 4f8bc8712aa51d..60586fb57f1c04 100644 --- a/clang/test/CodeGen/target-features-error-2.c +++ b/clang/test/CodeGen/target-features-error-2.c @@ -14,8 +14,8 @@ int baz(__m256i a) { #endif #if NEED_AVX_2 -__m256 need_avx(__m256 a, __m256 b) { - return _mm256_cmp_ps(a, b, 0); // expected-error {{'__builtin_ia32_cmpps256' needs target feature avx}} +__m128 need_avx(__m128 a, __m128 b) { + return _mm_cmp_ps(a, b, 0); // expected-error {{'__builtin_ia32_cmpps' needs target feature avx}} } #endif diff --git a/clang/test/CodeGen/ubsan-function-sugared.cpp b/clang/test/CodeGen/ubsan-function-sugared.cpp index 238bf31f4aba6d..fb2487c024ba90 100644 --- a/clang/test/CodeGen/ubsan-function-sugared.cpp +++ b/clang/test/CodeGen/ubsan-function-sugared.cpp @@ -40,5 +40,4 @@ void caller() { } // GNU: ![[FUNCSAN]] = !{i32 -1056584962, i32 905068220} -// FIXME: Wrong hash -// MSVC: ![[FUNCSAN]] = !{i32 -1056584962, i32 165986058} +// MSVC: ![[FUNCSAN]] = !{i32 -1056584962, i32 -1600339357} diff --git a/clang/test/CodeGenCUDA/cuda-builtin-vars.cu b/clang/test/CodeGenCUDA/cuda-builtin-vars.cu index e76e7a2f825290..ba5e5f13ebe707 100644 --- a/clang/test/CodeGenCUDA/cuda-builtin-vars.cu +++ b/clang/test/CodeGenCUDA/cuda-builtin-vars.cu @@ -6,21 +6,21 @@ __attribute__((global)) void kernel(int *out) { int i = 0; - out[i++] = threadIdx.x; // CHECK: call i32 @llvm.nvvm.read.ptx.sreg.tid.x() - out[i++] = threadIdx.y; // CHECK: call i32 @llvm.nvvm.read.ptx.sreg.tid.y() - out[i++] = threadIdx.z; // CHECK: call i32 @llvm.nvvm.read.ptx.sreg.tid.z() + out[i++] = threadIdx.x; // CHECK: call noundef i32 @llvm.nvvm.read.ptx.sreg.tid.x() + out[i++] = threadIdx.y; // CHECK: call noundef i32 @llvm.nvvm.read.ptx.sreg.tid.y() + out[i++] = threadIdx.z; // CHECK: call noundef i32 @llvm.nvvm.read.ptx.sreg.tid.z() - out[i++] = blockIdx.x; // CHECK: call i32 @llvm.nvvm.read.ptx.sreg.ctaid.x() - out[i++] = blockIdx.y; // CHECK: call i32 @llvm.nvvm.read.ptx.sreg.ctaid.y() - out[i++] = blockIdx.z; // CHECK: call i32 @llvm.nvvm.read.ptx.sreg.ctaid.z() + out[i++] = blockIdx.x; // CHECK: call noundef i32 @llvm.nvvm.read.ptx.sreg.ctaid.x() + out[i++] = blockIdx.y; // CHECK: call noundef i32 @llvm.nvvm.read.ptx.sreg.ctaid.y() + out[i++] = blockIdx.z; // CHECK: call noundef i32 @llvm.nvvm.read.ptx.sreg.ctaid.z() - out[i++] = blockDim.x; // CHECK: call i32 @llvm.nvvm.read.ptx.sreg.ntid.x() - out[i++] = blockDim.y; // CHECK: call i32 @llvm.nvvm.read.ptx.sreg.ntid.y() - out[i++] = blockDim.z; // CHECK: call i32 @llvm.nvvm.read.ptx.sreg.ntid.z() + out[i++] = blockDim.x; // CHECK: call noundef i32 @llvm.nvvm.read.ptx.sreg.ntid.x() + out[i++] = blockDim.y; // CHECK: call noundef i32 @llvm.nvvm.read.ptx.sreg.ntid.y() + out[i++] = blockDim.z; // CHECK: call noundef i32 @llvm.nvvm.read.ptx.sreg.ntid.z() - out[i++] = gridDim.x; // CHECK: call i32 @llvm.nvvm.read.ptx.sreg.nctaid.x() - out[i++] = gridDim.y; // CHECK: call i32 @llvm.nvvm.read.ptx.sreg.nctaid.y() - out[i++] = gridDim.z; // CHECK: call i32 @llvm.nvvm.read.ptx.sreg.nctaid.z() + out[i++] = gridDim.x; // CHECK: call noundef i32 @llvm.nvvm.read.ptx.sreg.nctaid.x() + out[i++] = gridDim.y; // CHECK: call noundef i32 @llvm.nvvm.read.ptx.sreg.nctaid.y() + out[i++] = gridDim.z; // CHECK: call noundef i32 @llvm.nvvm.read.ptx.sreg.nctaid.z() out[i++] = warpSize; // CHECK: store i32 32, diff --git a/clang/test/CodeGenCXX/RelativeVTablesABI/child-vtable-in-comdat.cpp b/clang/test/CodeGenCXX/RelativeVTablesABI/child-vtable-in-comdat.cpp index 48b1d8ed65d7e5..950921f67509f4 100644 --- a/clang/test/CodeGenCXX/RelativeVTablesABI/child-vtable-in-comdat.cpp +++ b/clang/test/CodeGenCXX/RelativeVTablesABI/child-vtable-in-comdat.cpp @@ -8,7 +8,6 @@ // CHECK-DAG: $_ZTS1B = comdat any // CHECK-DAG: $_ZTI1B = comdat any // CHECK-DAG: $_ZTI1B.rtti_proxy = comdat any -// CHECK-DAG: $_ZTI1A.rtti_proxy = comdat any // VTable for B is emitted here since we access it when creating an instance of B. The VTable is also linkonce_odr and in its own comdat. // CHECK-DAG: @_ZTV1B.local = linkonce_odr hidden unnamed_addr constant { [3 x i32] } { [3 x i32] [i32 0, i32 trunc (i64 sub (i64 ptrtoint (ptr @_ZTI1B.rtti_proxy to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [3 x i32] }, ptr @_ZTV1B.local, i32 0, i32 0, i32 2) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @_ZN1B3fooEv to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [3 x i32] }, ptr @_ZTV1B.local, i32 0, i32 0, i32 2) to i64)) to i32)] }, comdat($_ZTV1B), align 4 @@ -18,7 +17,7 @@ // CHECK-DAG: @_ZTS1B = // CHECK-DAG: @_ZTI1A = // CHECK-DAG: @_ZTI1B = -// CHECK-DAG: @_ZTI1B.rtti_proxy = hidden unnamed_addr constant ptr @_ZTI1B, comdat +// CHECK-DAG: @_ZTI1B.rtti_proxy = linkonce_odr hidden unnamed_addr constant ptr @_ZTI1B, comdat // We will emit a vtable for B here, so it does have an alias, but we will not // emit one for A. diff --git a/clang/test/CodeGenCXX/RelativeVTablesABI/parent-vtable-in-comdat.cpp b/clang/test/CodeGenCXX/RelativeVTablesABI/parent-vtable-in-comdat.cpp index 5f5f9edf411a80..ee710100152bfa 100644 --- a/clang/test/CodeGenCXX/RelativeVTablesABI/parent-vtable-in-comdat.cpp +++ b/clang/test/CodeGenCXX/RelativeVTablesABI/parent-vtable-in-comdat.cpp @@ -18,7 +18,7 @@ // CHECK: @_ZTVN10__cxxabiv117__class_type_infoE = external global [0 x ptr] // CHECK: @_ZTS1A = linkonce_odr constant [3 x i8] c"1A\00", comdat, align 1 // CHECK: @_ZTI1A = linkonce_odr constant { ptr, ptr } { ptr getelementptr inbounds (i8, ptr @_ZTVN10__cxxabiv117__class_type_infoE, i32 8), ptr @_ZTS1A }, comdat, align 8 -// CHECK: @_ZTI1A.rtti_proxy = hidden unnamed_addr constant ptr @_ZTI1A, comdat +// CHECK: @_ZTI1A.rtti_proxy = linkonce_odr hidden unnamed_addr constant ptr @_ZTI1A, comdat // CHECK: @_ZTV1A = linkonce_odr unnamed_addr alias { [3 x i32] }, ptr @_ZTV1A.local // CHECK: define linkonce_odr void @_ZN1A3fooEv(ptr {{.*}}%this) unnamed_addr #{{[0-9]+}} comdat diff --git a/clang/test/CodeGenCXX/RelativeVTablesABI/relative-vtables-hwasan.cpp b/clang/test/CodeGenCXX/RelativeVTablesABI/relative-vtables-hwasan.cpp index d0777b0f1245b6..7657a3bd0efdee 100644 --- a/clang/test/CodeGenCXX/RelativeVTablesABI/relative-vtables-hwasan.cpp +++ b/clang/test/CodeGenCXX/RelativeVTablesABI/relative-vtables-hwasan.cpp @@ -6,7 +6,7 @@ /// hwasan-instrumented. // CHECK-DAG: @_ZTV1A.local = private unnamed_addr constant { [3 x i32] } { [3 x i32] [i32 0, i32 trunc (i64 sub (i64 ptrtoint (ptr @_ZTI1A.rtti_proxy to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [3 x i32] }, ptr @_ZTV1A.local, i32 0, i32 0, i32 2) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @_ZN1A3fooEv to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [3 x i32] }, ptr @_ZTV1A.local, i32 0, i32 0, i32 2) to i64)) to i32)] }, no_sanitize_hwaddress, align 4 // CHECK-DAG: @_ZTV1A = unnamed_addr alias { [3 x i32] }, ptr @_ZTV1A.local -// CHECK-DAG: @_ZTI1A.rtti_proxy = hidden unnamed_addr constant ptr @_ZTI1A, no_sanitize_hwaddress, comdat +// CHECK-DAG: @_ZTI1A.rtti_proxy = linkonce_odr hidden unnamed_addr constant ptr @_ZTI1A, no_sanitize_hwaddress, comdat class A { public: @@ -22,7 +22,7 @@ void A_foo(A *a) { /// If the vtable happens to be hidden, then the alias is not needed. In this /// case, the original vtable struct itself should be unsanitized. // CHECK-DAG: @_ZTV1B = hidden unnamed_addr constant { [3 x i32] } { [3 x i32] [i32 0, i32 trunc (i64 sub (i64 ptrtoint (ptr @_ZTI1B.rtti_proxy to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [3 x i32] }, ptr @_ZTV1B, i32 0, i32 0, i32 2) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @_ZN1B3fooEv to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [3 x i32] }, ptr @_ZTV1B, i32 0, i32 0, i32 2) to i64)) to i32)] }, no_sanitize_hwaddress, align 4 -// CHECK-DAG: @_ZTI1B.rtti_proxy = hidden unnamed_addr constant ptr @_ZTI1B, no_sanitize_hwaddress, comdat +// CHECK-DAG: @_ZTI1B.rtti_proxy = linkonce_odr hidden unnamed_addr constant ptr @_ZTI1B, no_sanitize_hwaddress, comdat class __attribute__((visibility("hidden"))) B { public: diff --git a/clang/test/CodeGenCXX/RelativeVTablesABI/simple-vtable-definition.cpp b/clang/test/CodeGenCXX/RelativeVTablesABI/simple-vtable-definition.cpp index 76de83d9d2cd46..5ed4745b9a0691 100644 --- a/clang/test/CodeGenCXX/RelativeVTablesABI/simple-vtable-definition.cpp +++ b/clang/test/CodeGenCXX/RelativeVTablesABI/simple-vtable-definition.cpp @@ -14,7 +14,7 @@ // CHECK: @_ZTI1A ={{.*}} constant { ptr, ptr } { ptr getelementptr inbounds (i8, ptr @_ZTVN10__cxxabiv117__class_type_infoE, i32 8), ptr @_ZTS1A }, align 8 // The rtti should be in a comdat -// CHECK: @_ZTI1A.rtti_proxy = hidden unnamed_addr constant ptr @_ZTI1A, comdat +// CHECK: @_ZTI1A.rtti_proxy = {{.*}}comdat // The vtable symbol is exposed through an alias. // @_ZTV1A = dso_local unnamed_addr alias { [3 x i32] }, ptr @_ZTV1A.local diff --git a/clang/test/CodeGenCXX/RelativeVTablesABI/type-info.cpp b/clang/test/CodeGenCXX/RelativeVTablesABI/type-info.cpp index 42f28a770e7277..bc10461187b758 100644 --- a/clang/test/CodeGenCXX/RelativeVTablesABI/type-info.cpp +++ b/clang/test/CodeGenCXX/RelativeVTablesABI/type-info.cpp @@ -13,8 +13,8 @@ // CHECK: @_ZTVN10__cxxabiv120__si_class_type_infoE = external global [0 x ptr] // CHECK: @_ZTS1B ={{.*}} constant [3 x i8] c"1B\00", align 1 // CHECK: @_ZTI1B ={{.*}} constant { ptr, ptr, ptr } { ptr getelementptr inbounds (i8, ptr @_ZTVN10__cxxabiv120__si_class_type_infoE, i32 8), ptr @_ZTS1B, ptr @_ZTI1A }, align 8 -// CHECK: @_ZTI1A.rtti_proxy = hidden unnamed_addr constant ptr @_ZTI1A, comdat -// CHECK: @_ZTI1B.rtti_proxy = hidden unnamed_addr constant ptr @_ZTI1B, comdat +// CHECK: @_ZTI1A.rtti_proxy = linkonce_odr hidden unnamed_addr constant ptr @_ZTI1A, comdat +// CHECK: @_ZTI1B.rtti_proxy = linkonce_odr hidden unnamed_addr constant ptr @_ZTI1B, comdat // CHECK: define {{.*}}ptr @_Z11getTypeInfov() local_unnamed_addr // CHECK-NEXT: entry: diff --git a/clang/test/CodeGenCXX/cxx2b-deducing-this-cc.cpp b/clang/test/CodeGenCXX/cxx2b-deducing-this-cc.cpp new file mode 100644 index 00000000000000..bfbb24fcf23d9a --- /dev/null +++ b/clang/test/CodeGenCXX/cxx2b-deducing-this-cc.cpp @@ -0,0 +1,40 @@ +// RUN: %clang_cc1 -std=c++2b %s -emit-llvm -triple i386-windows-msvc -o - | FileCheck %s + +namespace CC { + +struct T { + static void f(T&); + void __cdecl g(this T&); + void __thiscall h(this T&); + void i(this T&); +}; + +void a() { + T t; + T::f(t); +} +// CHECK: define dso_local void @"?a@CC@@YAXXZ"{{.*}} +// CHECK: call void @"?f@T@CC@@SAXAAU12@@Z"{{.*}} + +void b() { + T t; + t.g(); +} +// CHECK: define dso_local void @"?b@CC@@YAXXZ"{{.*}} +// CHECK: call void @"?g@T@CC@@SAX_VAAU12@@Z"{{.*}} + +void c() { + T t; + t.h(); +} +// CHECK: define dso_local void @"?c@CC@@YAXXZ"{{.*}} +// CHECK: call x86_thiscallcc void @"?h@T@CC@@SEX_VAAU12@@Z"{{.*}} + +void d() { + T t; + t.i(); +} +// CHECK: define dso_local void @"?d@CC@@YAXXZ"{{.*}} +// CHECK: call void @"?i@T@CC@@SAX_VAAU12@@Z"{{.*}} + +} diff --git a/clang/test/CodeGenCXX/cxx2b-deducing-this.cpp b/clang/test/CodeGenCXX/cxx2b-deducing-this.cpp new file mode 100644 index 00000000000000..de8c124c050eb0 --- /dev/null +++ b/clang/test/CodeGenCXX/cxx2b-deducing-this.cpp @@ -0,0 +1,111 @@ +// RUN: %clang_cc1 -std=c++2b %s -emit-llvm -triple x86_64-linux -o - | FileCheck %s + +struct TrivialStruct { + void explicit_object_function(this TrivialStruct) {} +}; +void test() { + TrivialStruct s; + s.explicit_object_function(); +} +// CHECK: define {{.*}}test{{.*}} +// CHECK-NEXT: entry: +// CHECK: {{.*}} = alloca %struct.TrivialStruct, align 1 +// CHECK: {{.*}} = alloca %struct.TrivialStruct, align 1 +// CHECK: call void {{.*}}explicit_object_function{{.*}} +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK: define {{.*}}explicit_object_function{{.*}} +// CHECK-NEXT: entry: +// CHECK: {{.*}} = alloca %struct.TrivialStruct, align 1 +// CHECK: ret void +// CHECK-NEXT: } + + +void test_lambda() { + [](this auto This) -> int { + return This(); + }(); +} + +//CHECK: define dso_local void @{{.*}}test_lambda{{.*}}() #0 { +//CHECK: entry: +//CHECK: %agg.tmp = alloca %class.anon, align 1 +//CHECK: %ref.tmp = alloca %class.anon, align 1 +//CHECK: %call = call noundef i32 @"_ZZ11test_lambdavENH3$_0clIS_EEiT_"() +//CHECK: ret void +//CHECK: } + +//CHECK: define internal noundef i32 @"_ZZ11test_lambdavENH3$_0clIS_EEiT_"() #0 align 2 { +//CHECK: entry: +//CHECK: %This = alloca %class.anon, align 1 +//CHECK: %agg.tmp = alloca %class.anon, align 1 +//CHECK: %call = call noundef i32 @"_ZZ11test_lambdavENH3$_0clIS_EEiT_"() +//CHECK: ret i32 %call +//CHECK: } + +void test_lambda_ref() { + auto l = [i = 42](this auto & This, int j) -> int { + return This(j); + }; + l(0); +} + +// CHECK: define dso_local void @_Z15test_lambda_refv() #0 { +// CHECK: entry: +// CHECK: %[[This_address:.]] = alloca %class.anon{{.*}}, align 4 +// CHECK: %[[i_addr:.*]] = getelementptr inbounds %class.anon{{.*}}, ptr %[[This_address]], i32 0, i32 0 +// CHECK: store i32 42, ptr %[[i_addr]], align 4 +// CHECK: %call = call noundef i32 @"_ZZ15test_lambda_refvENH3$_0clIS_EEiRT_i"{{.*}} +// CHECK: ret void +// CHECK: } + +// CHECK: define internal noundef i32 @"_ZZ15test_lambda_refvENH3$_0clIS_EEiRT_i"{{.*}} +// CHECK: entry: +// CHECK: %This.addr = alloca ptr, align 8 +// CHECK: %j.addr = alloca i32, align 4 +// CHECK: store ptr %This, ptr %This.addr, align 8 +// CHECK: store i32 %j, ptr %j.addr, align 4 +// CHECK: %[[this_addr:.*]] = load ptr, ptr %This.addr, align 8 +// CHECK: %[[j_addr:.*]] = load i32, ptr %j.addr, align 4 +// CHECK: %call = call noundef i32 @"_ZZ15test_lambda_refvENH3$_0clIS_EEiRT_i"(ptr noundef nonnull align 4 dereferenceable(4) %[[this_addr]], i32 noundef %[[j_addr]]) +// CHECK: ret i32 %call +// CHECK: } + + +struct TestPointer { + void f(this TestPointer &); +}; + +void test_pointer() { + TestPointer t; + using Fn = void(TestPointer&); + Fn* fn = &TestPointer::f; + fn(t); +} +//CHECK: define dso_local void @_Z12test_pointerv() #0 { +//CHECK-NEXT: entry: +//CHECK-NEXT: %t = alloca %struct.TestPointer, align 1 +//CHECK-NEXT: %fn = alloca ptr, align 8 +//CHECK-NEXT: store ptr @_ZNH11TestPointer1fERS_, ptr %fn, align 8 +//CHECK: %[[fn_ptr:.*]] = load ptr, ptr %fn, align 8 +//CHECK-NEXT: call void %[[fn_ptr]](ptr noundef nonnull align 1 dereferenceable(1) %t) +//CHECK-NEXT: ret void +//CHECK-NEXT: } + + +struct MaterializedTemporary { + void foo(this MaterializedTemporary&&); + MaterializedTemporary(); + ~MaterializedTemporary(); +}; + +void test_temporary() { + MaterializedTemporary{}.foo(); +} + +//CHECK: define dso_local void @_Z14test_temporaryv(){{.*}} +//CHECK-NEXT: entry: +//CHECK: %ref.tmp = alloca %struct.MaterializedTemporary, align 1 +//CHECK: call void @_ZN21MaterializedTemporaryC1Ev(ptr noundef nonnull align 1 dereferenceable(1) %ref.tmp){{.*}} +//CHECK invoke void @_ZNH21MaterializedTemporary3fooEOS_(ptr noundef nonnull align 1 dereferenceable(1) %ref.tmp){{.*}} diff --git a/clang/test/CodeGenCXX/cxx2b-mangle-deducing-this.cpp b/clang/test/CodeGenCXX/cxx2b-mangle-deducing-this.cpp new file mode 100644 index 00000000000000..579e757e36fc80 --- /dev/null +++ b/clang/test/CodeGenCXX/cxx2b-mangle-deducing-this.cpp @@ -0,0 +1,64 @@ +// RUN: %clang_cc1 -std=c++2b -emit-llvm -triple x86_64-linux -o - %s 2>/dev/null | FileCheck %s + +struct S { +friend void test(); +public: + void a(this auto){} + void b(this auto&){} + void c(this S){} + void c(this S, int){} +private: + void d(this auto){} + void e(this auto&){} + void f(this S){} + void f(this S, int){} +protected: + void g(this auto){} + void h(this auto&){} + void i(this S){} + void i(this S, int){} +}; + + +void test() { + S s; + s.a(); + // CHECK: call void @_ZNH1S1aIS_EEvT_ + s.b(); + // CHECK: call void @_ZNH1S1bIS_EEvRT_ + s.c(); + // CHECK: call void @_ZNH1S1cES_ + s.c(0); + // CHECK: call void @_ZNH1S1cES_i + s.d(); + // CHECK: call void @_ZNH1S1dIS_EEvT_ + s.e(); + // CHECK: call void @_ZNH1S1eIS_EEvRT_ + s.f(); + // CHECK: call void @_ZNH1S1fES_ + s.f(0); + // CHECK: call void @_ZNH1S1fES_i + s.g(); + // CHECK: call void @_ZNH1S1gIS_EEvT_ + s.h(); + // CHECK: call void @_ZNH1S1hIS_EEvRT_ + s.i(); + // CHECK: call void @_ZNH1S1iES_ + s.i(0); + // CHECK: call void @_ZNH1S1iES_i +} + +struct StaticAndExplicit { + static void f(StaticAndExplicit); + void f(this StaticAndExplicit); +}; + +void test2() { + StaticAndExplicit s; + + StaticAndExplicit::f(s); + // CHECK: call void @_ZN17StaticAndExplicit1fES_ + + s.f(); + // CHECK: call void @_ZNH17StaticAndExplicit1fES_ +} diff --git a/clang/test/CodeGenCXX/microsoft-abi-explicit-object-parameters.cpp b/clang/test/CodeGenCXX/microsoft-abi-explicit-object-parameters.cpp new file mode 100644 index 00000000000000..b633f6c4ad3f2b --- /dev/null +++ b/clang/test/CodeGenCXX/microsoft-abi-explicit-object-parameters.cpp @@ -0,0 +1,70 @@ +// RUN: %clang_cc1 -std=c++2b -emit-llvm -triple=x86_64-pc-win32 -o - %s 2>/dev/null | FileCheck %s + +struct S { +friend void test(); +public: + void a(this auto){} + void b(this auto&){} + void c(this S){} + void c(this S, int){} +private: + void d(this auto){} + void e(this auto&){} + void f(this S){} + void f(this S, int){} +protected: + void g(this auto){} + void h(this auto&){} + void i(this S){} + void i(this S, int){} +}; + +void test() { + S s; + s.a(); + // CHECK: call void @"??$a@US@@@S@@SAX_VU0@@Z" + s.b(); + // CHECK: call void @"??$b@US@@@S@@SAX_VAEAU0@@Z" + s.c(); + // CHECK: call void @"?c@S@@SAX_VU1@@Z" + s.c(0); + // CHECK: call void @"?c@S@@SAX_VU1@H@Z" + s.d(); + // CHECK: call void @"??$d@US@@@S@@CAX_VU0@@Z" + s.e(); + // CHECK: call void @"??$e@US@@@S@@CAX_VAEAU0@@Z" + s.f(); + // CHECK: call void @"?f@S@@CAX_VU1@@Z" + s.f(0); + // CHECK: call void @"?f@S@@CAX_VU1@H@Z" + s.g(); + // CHECK: call void @"??$g@US@@@S@@KAX_VU0@@Z" + s.h(); + // CHECK: call void @"??$h@US@@@S@@KAX_VAEAU0@@Z" + s.i(); + // CHECK: call void @"?i@S@@KAX_VU1@@Z" + s.i(0); + // CHECK: call void @"?i@S@@KAX_VU1@H@Z" +} + + +struct S2 { + int i = 0; + void foo(this const S2&, int); +}; +struct T { + S2 bar(this const T&, int); +}; +void chain_test() { + T t; + t.bar(0).foo(0); +} +// CHECK: define {{.*}}chain_test{{.*}} +// CHECK-NEXT: entry: +// CHECK: {{.*}} = alloca %struct.T, align 1 +// CHECK: {{.*}} = alloca %struct.S2, align 4 +// CHECK: %call = call i32 @"?bar@T@@SA?AUS2@@_VAEBU1@H@Z"{{.*}} +// CHECK: %coerce.dive = getelementptr inbounds %struct.S2, {{.*}} %{{.*}}, i32 0, i32 0 +// CHECK store i32 %call, ptr %coerce.dive, align 4 +// CHECK: call void @"?foo@S2@@SAX_VAEBU1@H@Z" +// CHECK: ret void diff --git a/clang/test/CodeGenCXX/strict-vtable-pointers-GH67937.cpp b/clang/test/CodeGenCXX/strict-vtable-pointers-GH67937.cpp new file mode 100644 index 00000000000000..692ca23a69abe6 --- /dev/null +++ b/clang/test/CodeGenCXX/strict-vtable-pointers-GH67937.cpp @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 %s -I%S -triple=x86_64-pc-windows-msvc -fstrict-vtable-pointers -disable-llvm-passes -O1 -emit-llvm -o %t.ll +// RUN: FileCheck %s < %t.ll + +struct A { + virtual ~A(); +}; +struct B : virtual A {}; +class C : B {}; +C foo; + +// CHECK-LABEL: define {{.*}} @"??0C@@QEAA@XZ"(ptr {{.*}} %this, i32 {{.*}} %is_most_derived) +// CHECK: ctor.init_vbases: +// CHECK-NEXT: %0 = getelementptr inbounds i8, ptr %this1, i64 0 +// CHECK-NEXT: store ptr @"??_8C@@7B@", ptr %0 +// CHECK-NEXT: %1 = call ptr @llvm.launder.invariant.group.p0(ptr %this1) +// CHECK-NEXT: %2 = getelementptr inbounds i8, ptr %1, i64 8 +// CHECK-NEXT: %call = call noundef ptr @"??0A@@QEAA@XZ"(ptr {{.*}} %2) #2 +// CHECK-NEXT: br label %ctor.skip_vbases +// CHECK-EMPTY: +// CHECK-NEXT: ctor.skip_vbases: +// CHECK-NEXT: %3 = call ptr @llvm.launder.invariant.group.p0(ptr %this1) +// CHECK-NEXT: %call3 = call noundef ptr @"??0B@@QEAA@XZ"(ptr {{.*}} %3, i32 noundef 0) #2 diff --git a/clang/test/CodeGenCXX/weak-external.cpp b/clang/test/CodeGenCXX/weak-external.cpp index af636ccb4a3aef..5fc37f73bb4697 100644 --- a/clang/test/CodeGenCXX/weak-external.cpp +++ b/clang/test/CodeGenCXX/weak-external.cpp @@ -80,19 +80,23 @@ namespace not_weak_on_first { namespace constant_eval { [[gnu::weak]] extern int a; // CHECK-LABEL: define {{.*}} @__cxx_global_var_init - // CHECK: store i8 zext (i1 icmp ne (ptr @_ZN13constant_eval1aE, ptr null) to i8), ptr @_ZN13constant_eval6has_a1E, + // CHECK: [[ZEXT:%.*]] = zext i1 icmp ne (ptr @_ZN13constant_eval1aE, ptr null) to i8 + // CHECK: store i8 [[ZEXT]], ptr @_ZN13constant_eval6has_a1E, bool has_a1 = &a; // CHECK-LABEL: define {{.*}} @__cxx_global_var_init - // CHECK: store i8 zext (i1 icmp ne (ptr @_ZN13constant_eval1aE, ptr null) to i8), ptr @_ZN13constant_eval6has_a2E, + // CHECK: [[ZEXT:%.*]] = zext i1 icmp ne (ptr @_ZN13constant_eval1aE, ptr null) to i8 + // CHECK: store i8 [[ZEXT]], ptr @_ZN13constant_eval6has_a2E, bool has_a2 = &a != nullptr; struct X { [[gnu::weak]] void f(); }; // CHECK-LABEL: define {{.*}} @__cxx_global_var_init - // CHECK: store i8 zext (i1 icmp ne (i{{32|64}} ptrtoint (ptr @_ZN13constant_eval1X1fEv to i{{32|64}}), i{{32|64}} 0) to i8), ptr @_ZN13constant_eval6has_f1E, + // CHECK: [[ZEXT:%.*]] = zext i1 icmp ne (i{{32|64}} ptrtoint (ptr @_ZN13constant_eval1X1fEv to i{{32|64}}), i{{32|64}} 0) to i8 + // CHECK: store i8 [[ZEXT]], ptr @_ZN13constant_eval6has_f1E, bool has_f1 = &X::f; // CHECK-LABEL: define {{.*}} @__cxx_global_var_init - // CHECK: store i8 zext (i1 icmp ne (i{{32|64}} ptrtoint (ptr @_ZN13constant_eval1X1fEv to i{{32|64}}), i{{32|64}} 0) to i8), ptr @_ZN13constant_eval6has_f2E, + // CHECK: [[ZEXT:%.*]] = zext i1 icmp ne (i{{32|64}} ptrtoint (ptr @_ZN13constant_eval1X1fEv to i{{32|64}}), i{{32|64}} 0) to i8 + // CHECK: store i8 [[ZEXT]], ptr @_ZN13constant_eval6has_f2E, bool has_f2 = &X::f != nullptr; } diff --git a/clang/test/CodeGenOpenCL/amdgpu-nullptr.cl b/clang/test/CodeGenOpenCL/amdgpu-nullptr.cl index cb3ca514c584fb..8a04456b5df044 100644 --- a/clang/test/CodeGenOpenCL/amdgpu-nullptr.cl +++ b/clang/test/CodeGenOpenCL/amdgpu-nullptr.cl @@ -606,7 +606,8 @@ int test_and_ptr(private char* p1, local char* p2) { // NOOPT: store ptr addrspace(1) null, ptr addrspace(5) %glob, align 8 // NOOPT: %{{.*}} = sub i64 %{{.*}}, 0 // NOOPT: call void @test_fold_callee -// NOOPT: %{{.*}} = add nsw i64 %1, sext (i32 ptrtoint (ptr addrspace(5) addrspacecast (ptr null to ptr addrspace(5)) to i32) to i64) +// NOOPT: %[[SEXT:.*]] = sext i32 ptrtoint (ptr addrspace(5) addrspacecast (ptr null to ptr addrspace(5)) to i32) to i64 +// NOOPT: %{{.*}} = add nsw i64 %1, %[[SEXT]] // NOOPT: %{{.*}} = sub nsw i64 %{{.*}}, 1 void test_fold_callee(void); void test_fold_private(void) { @@ -621,7 +622,8 @@ void test_fold_private(void) { // NOOPT: store ptr addrspace(1) null, ptr addrspace(5) %glob, align 8 // NOOPT: %{{.*}} = sub i64 %{{.*}}, 0 // NOOPT: call void @test_fold_callee -// NOOPT: %{{.*}} = add nsw i64 %{{.*}}, sext (i32 ptrtoint (ptr addrspace(3) addrspacecast (ptr null to ptr addrspace(3)) to i32) to i64) +// NOOPT: %[[SEXT:.*]] = sext i32 ptrtoint (ptr addrspace(3) addrspacecast (ptr null to ptr addrspace(3)) to i32) to i64 +// NOOPT: %{{.*}} = add nsw i64 %{{.*}}, %[[SEXT]] // NOOPT: %{{.*}} = sub nsw i64 %{{.*}}, 1 void test_fold_local(void) { global int* glob = (test_fold_callee(), (global int*)(generic char*)0); diff --git a/clang/test/Driver/Inputs/hipstdpar/hipstdpar_lib.hpp b/clang/test/Driver/Inputs/hipstdpar/hipstdpar_lib.hpp new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/clang/test/Driver/Inputs/hipstdpar/rocprim/.keep b/clang/test/Driver/Inputs/hipstdpar/rocprim/.keep new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/clang/test/Driver/Inputs/hipstdpar/rocprim/rocprim/.keep b/clang/test/Driver/Inputs/hipstdpar/rocprim/rocprim/.keep new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/clang/test/Driver/Inputs/hipstdpar/thrust/.keep b/clang/test/Driver/Inputs/hipstdpar/thrust/.keep new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/clang/test/Driver/Inputs/hipstdpar/thrust/thrust/.keep b/clang/test/Driver/Inputs/hipstdpar/thrust/thrust/.keep new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/clang/test/Driver/clang-offload-bundler-zlib.c b/clang/test/Driver/clang-offload-bundler-zlib.c new file mode 100644 index 00000000000000..c46c32a4a0537b --- /dev/null +++ b/clang/test/Driver/clang-offload-bundler-zlib.c @@ -0,0 +1,75 @@ +// REQUIRES: zlib +// REQUIRES: x86-registered-target +// UNSUPPORTED: target={{.*}}-darwin{{.*}}, target={{.*}}-aix{{.*}} + +// +// Generate the host binary to be bundled. +// +// RUN: %clang -O0 -target %itanium_abi_triple %s -c -emit-llvm -o %t.bc + +// +// Generate an empty file to help with the checks of empty files. +// +// RUN: touch %t.empty + +// +// Generate device binaries to be bundled. +// +// RUN: echo 'Content of device file 1' > %t.tgt1 +// RUN: echo 'Content of device file 2' > %t.tgt2 + +// +// Check compression/decompression of offload bundle. +// +// RUN: env OFFLOAD_BUNDLER_COMPRESS=1 OFFLOAD_BUNDLER_VERBOSE=1 \ +// RUN: clang-offload-bundler -type=bc -targets=hip-amdgcn-amd-amdhsa--gfx900,hip-amdgcn-amd-amdhsa--gfx906 \ +// RUN: -input=%t.tgt1 -input=%t.tgt2 -output=%t.hip.bundle.bc 2>&1 | \ +// RUN: FileCheck -check-prefix=COMPRESS %s +// RUN: clang-offload-bundler -type=bc -list -input=%t.hip.bundle.bc | FileCheck -check-prefix=NOHOST %s +// RUN: env OFFLOAD_BUNDLER_VERBOSE=1 \ +// RUN: clang-offload-bundler -type=bc -targets=hip-amdgcn-amd-amdhsa--gfx900,hip-amdgcn-amd-amdhsa--gfx906 \ +// RUN: -output=%t.res.tgt1 -output=%t.res.tgt2 -input=%t.hip.bundle.bc -unbundle 2>&1 | \ +// RUN: FileCheck -check-prefix=DECOMPRESS %s +// RUN: diff %t.tgt1 %t.res.tgt1 +// RUN: diff %t.tgt2 %t.res.tgt2 + +// +// COMPRESS: Compression method used: +// DECOMPRESS: Decompression method: +// NOHOST-NOT: host- +// NOHOST-DAG: hip-amdgcn-amd-amdhsa--gfx900 +// NOHOST-DAG: hip-amdgcn-amd-amdhsa--gfx906 +// + +// +// Check -bundle-align option. +// + +// RUN: clang-offload-bundler -bundle-align=4096 -type=bc -targets=host-%itanium_abi_triple,openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu -input=%t.bc -input=%t.tgt1 -input=%t.tgt2 -output=%t.bundle3.bc -compress +// RUN: clang-offload-bundler -type=bc -targets=host-%itanium_abi_triple,openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu -output=%t.res.bc -output=%t.res.tgt1 -output=%t.res.tgt2 -input=%t.bundle3.bc -unbundle +// RUN: diff %t.bc %t.res.bc +// RUN: diff %t.tgt1 %t.res.tgt1 +// RUN: diff %t.tgt2 %t.res.tgt2 + +// +// Check unbundling archive. +// +// RUN: clang-offload-bundler -type=bc -targets=hip-amdgcn-amd-amdhsa--gfx900,hip-amdgcn-amd-amdhsa--gfx906 \ +// RUN: -input=%t.tgt1 -input=%t.tgt2 -output=%T/hip_bundle1.bc -compress +// RUN: clang-offload-bundler -type=bc -targets=hip-amdgcn-amd-amdhsa--gfx900,hip-amdgcn-amd-amdhsa--gfx906 \ +// RUN: -input=%t.tgt1 -input=%t.tgt2 -output=%T/hip_bundle2.bc -compress +// RUN: llvm-ar cr %T/hip_archive.a %T/hip_bundle1.bc %T/hip_bundle2.bc +// RUN: clang-offload-bundler -unbundle -type=a -targets=hip-amdgcn-amd-amdhsa--gfx900,hip-amdgcn-amd-amdhsa--gfx906 \ +// RUN: -output=%T/hip_900.a -output=%T/hip_906.a -input=%T/hip_archive.a +// RUN: llvm-ar t %T/hip_900.a | FileCheck -check-prefix=HIP-AR-900 %s +// RUN: llvm-ar t %T/hip_906.a | FileCheck -check-prefix=HIP-AR-906 %s +// HIP-AR-900-DAG: hip_bundle1-hip-amdgcn-amd-amdhsa--gfx900 +// HIP-AR-900-DAG: hip_bundle2-hip-amdgcn-amd-amdhsa--gfx900 +// HIP-AR-906-DAG: hip_bundle1-hip-amdgcn-amd-amdhsa--gfx906 +// HIP-AR-906-DAG: hip_bundle2-hip-amdgcn-amd-amdhsa--gfx906 + +// Some code so that we can create a binary out of this file. +int A = 0; +void test_func(void) { + ++A; +} diff --git a/clang/test/Driver/clang-offload-bundler-zstd.c b/clang/test/Driver/clang-offload-bundler-zstd.c new file mode 100644 index 00000000000000..b2b588b72d4d6f --- /dev/null +++ b/clang/test/Driver/clang-offload-bundler-zstd.c @@ -0,0 +1,72 @@ +// REQUIRES: zstd +// REQUIRES: x86-registered-target +// UNSUPPORTED: target={{.*}}-darwin{{.*}}, target={{.*}}-aix{{.*}} + +// +// Generate the host binary to be bundled. +// +// RUN: %clang -O0 -target %itanium_abi_triple %s -c -emit-llvm -o %t.bc + +// +// Generate an empty file to help with the checks of empty files. +// +// RUN: touch %t.empty + +// +// Generate device binaries to be bundled. +// +// RUN: echo 'Content of device file 1' > %t.tgt1 +// RUN: echo 'Content of device file 2' > %t.tgt2 + +// +// Check compression/decompression of offload bundle. +// +// RUN: clang-offload-bundler -type=bc -targets=hip-amdgcn-amd-amdhsa--gfx900,hip-amdgcn-amd-amdhsa--gfx906 \ +// RUN: -input=%t.tgt1 -input=%t.tgt2 -output=%t.hip.bundle.bc -compress -verbose 2>&1 | \ +// RUN: FileCheck -check-prefix=COMPRESS %s +// RUN: clang-offload-bundler -type=bc -list -input=%t.hip.bundle.bc | FileCheck -check-prefix=NOHOST %s +// RUN: clang-offload-bundler -type=bc -targets=hip-amdgcn-amd-amdhsa--gfx900,hip-amdgcn-amd-amdhsa--gfx906 \ +// RUN: -output=%t.res.tgt1 -output=%t.res.tgt2 -input=%t.hip.bundle.bc -unbundle -verbose 2>&1 | \ +// RUN: FileCheck -check-prefix=DECOMPRESS %s +// RUN: diff %t.tgt1 %t.res.tgt1 +// RUN: diff %t.tgt2 %t.res.tgt2 +// +// COMPRESS: Compression method used +// DECOMPRESS: Decompression method +// NOHOST-NOT: host- +// NOHOST-DAG: hip-amdgcn-amd-amdhsa--gfx900 +// NOHOST-DAG: hip-amdgcn-amd-amdhsa--gfx906 +// + +// +// Check -bundle-align option. +// + +// RUN: clang-offload-bundler -bundle-align=4096 -type=bc -targets=host-%itanium_abi_triple,openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu -input=%t.bc -input=%t.tgt1 -input=%t.tgt2 -output=%t.bundle3.bc -compress +// RUN: clang-offload-bundler -type=bc -targets=host-%itanium_abi_triple,openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu -output=%t.res.bc -output=%t.res.tgt1 -output=%t.res.tgt2 -input=%t.bundle3.bc -unbundle +// RUN: diff %t.bc %t.res.bc +// RUN: diff %t.tgt1 %t.res.tgt1 +// RUN: diff %t.tgt2 %t.res.tgt2 + +// +// Check unbundling archive. +// +// RUN: clang-offload-bundler -type=bc -targets=hip-amdgcn-amd-amdhsa--gfx900,hip-amdgcn-amd-amdhsa--gfx906 \ +// RUN: -input=%t.tgt1 -input=%t.tgt2 -output=%T/hip_bundle1.bc -compress +// RUN: clang-offload-bundler -type=bc -targets=hip-amdgcn-amd-amdhsa--gfx900,hip-amdgcn-amd-amdhsa--gfx906 \ +// RUN: -input=%t.tgt1 -input=%t.tgt2 -output=%T/hip_bundle2.bc -compress +// RUN: llvm-ar cr %T/hip_archive.a %T/hip_bundle1.bc %T/hip_bundle2.bc +// RUN: clang-offload-bundler -unbundle -type=a -targets=hip-amdgcn-amd-amdhsa--gfx900,hip-amdgcn-amd-amdhsa--gfx906 \ +// RUN: -output=%T/hip_900.a -output=%T/hip_906.a -input=%T/hip_archive.a +// RUN: llvm-ar t %T/hip_900.a | FileCheck -check-prefix=HIP-AR-900 %s +// RUN: llvm-ar t %T/hip_906.a | FileCheck -check-prefix=HIP-AR-906 %s +// HIP-AR-900-DAG: hip_bundle1-hip-amdgcn-amd-amdhsa--gfx900 +// HIP-AR-900-DAG: hip_bundle2-hip-amdgcn-amd-amdhsa--gfx900 +// HIP-AR-906-DAG: hip_bundle1-hip-amdgcn-amd-amdhsa--gfx906 +// HIP-AR-906-DAG: hip_bundle2-hip-amdgcn-amd-amdhsa--gfx906 + +// Some code so that we can create a binary out of this file. +int A = 0; +void test_func(void) { + ++A; +} diff --git a/clang/test/Driver/clang_f_opts.c b/clang/test/Driver/clang_f_opts.c index 7a3616a2e9f0a4..ebe8a0520bf0fc 100644 --- a/clang/test/Driver/clang_f_opts.c +++ b/clang/test/Driver/clang_f_opts.c @@ -520,6 +520,11 @@ // CHECK-COVERAGE-COMPILATION-DIR: "-fcoverage-compilation-dir=." // CHECK-COVERAGE-COMPILATION-DIR-NOT: "-ffile-compilation-dir=." +// RUN: %clang -### -S -fverify-intermediate-code %s 2>&1 | FileCheck -check-prefix=CHECK-VERIFY-INTERMEDIATE-CODE %s +// RUN: %clang -### -S -fno-verify-intermediate-code %s 2>&1 | FileCheck -check-prefix=CHECK-NO-VERIFY-INTERMEDIATE-CODE %s +// CHECK-VERIFY-INTERMEDIATE-CODE-NOT: "-disable-llvm-verifier" +// CHECK-NO-VERIFY-INTERMEDIATE-CODE: "-disable-llvm-verifier" + // RUN: %clang -### -S -fdiscard-value-names %s 2>&1 | FileCheck -check-prefix=CHECK-DISCARD-NAMES %s // RUN: %clang -### -S -fno-discard-value-names %s 2>&1 | FileCheck -check-prefix=CHECK-NO-DISCARD-NAMES %s // CHECK-DISCARD-NAMES: "-discard-value-names" diff --git a/clang/test/Driver/hip-offload-compress-zlib.hip b/clang/test/Driver/hip-offload-compress-zlib.hip new file mode 100644 index 00000000000000..a29b6d037350d4 --- /dev/null +++ b/clang/test/Driver/hip-offload-compress-zlib.hip @@ -0,0 +1,45 @@ +// REQUIRES: zlib +// REQUIRES: x86-registered-target +// REQUIRES: amdgpu-registered-target + +// Test compress bundled bitcode. + +// RUN: rm -rf %T/a.bc +// RUN: %clang -c -v --target=x86_64-linux-gnu \ +// RUN: -x hip --offload-arch=gfx1100 --offload-arch=gfx1101 \ +// RUN: -fgpu-rdc -nogpuinc -nogpulib \ +// RUN: %S/Inputs/hip_multiple_inputs/a.cu \ +// RUN: --offload-compress --offload-device-only --gpu-bundle-output \ +// RUN: -o %T/a.bc \ +// RUN: 2>&1 | FileCheck %s + +// CHECK: clang-offload-bundler{{.*}} -type=bc +// CHECK-SAME: -targets={{.*}}hip-amdgcn-amd-amdhsa-gfx1100,hip-amdgcn-amd-amdhsa-gfx1101 +// CHECK-SAME: -compress -verbose +// CHECK: Compressed bundle format + +// Test uncompress of bundled bitcode. + +// RUN: %clang --hip-link -### -v --target=x86_64-linux-gnu \ +// RUN: --offload-arch=gfx1100 --offload-arch=gfx1101 \ +// RUN: -fgpu-rdc -nogpulib \ +// RUN: %T/a.bc --offload-device-only \ +// RUN: 2>&1 | FileCheck -check-prefix=UNBUNDLE %s + +// UNBUNDLE: clang-offload-bundler{{.*}} "-type=bc" +// UNBUNDLE-SAME: -targets={{.*}}hip-amdgcn-amd-amdhsa-gfx1100,hip-amdgcn-amd-amdhsa-gfx1101 +// UNBUNDLE-SAME: -unbundle +// UNBUNDLE-SAME: -verbose + +// Test compress bundled code objects. + +// RUN: %clang -c -### -v --target=x86_64-linux-gnu \ +// RUN: -x hip --offload-arch=gfx1100 --offload-arch=gfx1101 \ +// RUN: -nogpuinc -nogpulib \ +// RUN: %S/Inputs/hip_multiple_inputs/a.cu \ +// RUN: --offload-compress \ +// RUN: 2>&1 | FileCheck -check-prefix=CO %s + +// CO: clang-offload-bundler{{.*}} "-type=o" +// CO-SAME: -targets={{.*}}hipv4-amdgcn-amd-amdhsa--gfx1100,hipv4-amdgcn-amd-amdhsa--gfx1101 +// CO-SAME: "-compress" "-verbose" diff --git a/clang/test/Driver/hip-offload-compress-zstd.hip b/clang/test/Driver/hip-offload-compress-zstd.hip new file mode 100644 index 00000000000000..688c2c85329c19 --- /dev/null +++ b/clang/test/Driver/hip-offload-compress-zstd.hip @@ -0,0 +1,45 @@ +// REQUIRES: zstd +// REQUIRES: x86-registered-target +// REQUIRES: amdgpu-registered-target + +// Test compress bundled bitcode. + +// RUN: rm -rf %T/a.bc +// RUN: %clang -c -v --target=x86_64-linux-gnu \ +// RUN: -x hip --offload-arch=gfx1100 --offload-arch=gfx1101 \ +// RUN: -fgpu-rdc -nogpuinc -nogpulib \ +// RUN: %S/Inputs/hip_multiple_inputs/a.cu \ +// RUN: --offload-compress --offload-device-only --gpu-bundle-output \ +// RUN: -o %T/a.bc \ +// RUN: 2>&1 | FileCheck %s + +// CHECK: clang-offload-bundler{{.*}} -type=bc +// CHECK-SAME: -targets={{.*}}hip-amdgcn-amd-amdhsa-gfx1100,hip-amdgcn-amd-amdhsa-gfx1101 +// CHECK-SAME: -compress -verbose +// CHECK: Compressed bundle format + +// Test uncompress of bundled bitcode. + +// RUN: %clang --hip-link -### -v --target=x86_64-linux-gnu \ +// RUN: --offload-arch=gfx1100 --offload-arch=gfx1101 \ +// RUN: -fgpu-rdc -nogpulib \ +// RUN: %T/a.bc --offload-device-only \ +// RUN: 2>&1 | FileCheck -check-prefix=UNBUNDLE %s + +// UNBUNDLE: clang-offload-bundler{{.*}} "-type=bc" +// UNBUNDLE-SAME: -targets={{.*}}hip-amdgcn-amd-amdhsa-gfx1100,hip-amdgcn-amd-amdhsa-gfx1101 +// UNBUNDLE-SAME: -unbundle +// UNBUNDLE-SAME: -verbose + +// Test compress bundled code objects. + +// RUN: %clang -c -### -v --target=x86_64-linux-gnu \ +// RUN: -x hip --offload-arch=gfx1100 --offload-arch=gfx1101 \ +// RUN: -nogpuinc -nogpulib \ +// RUN: %S/Inputs/hip_multiple_inputs/a.cu \ +// RUN: --offload-compress \ +// RUN: 2>&1 | FileCheck -check-prefix=CO %s + +// CO: clang-offload-bundler{{.*}} "-type=o" +// CO-SAME: -targets={{.*}}hipv4-amdgcn-amd-amdhsa--gfx1100,hipv4-amdgcn-amd-amdhsa--gfx1101 +// CO-SAME: "-compress" "-verbose" diff --git a/clang/test/Driver/hipstdpar.c b/clang/test/Driver/hipstdpar.c new file mode 100644 index 00000000000000..69c5b177d170cd --- /dev/null +++ b/clang/test/Driver/hipstdpar.c @@ -0,0 +1,25 @@ +// REQUIRES: x86-registered-target +// REQUIRES: amdgpu-registered-target +// REQUIRES: system-linux +// XFAIL: target={{.*}}hexagon{{.*}} +// XFAIL: target={{.*}}-scei{{.*}} +// XFAIL: target={{.*}}-sie{{.*}} + +// RUN: not %clang -### --hipstdpar -nogpulib -nogpuinc --compile %s 2>&1 | \ +// RUN: FileCheck --check-prefix=HIPSTDPAR-MISSING-LIB %s +// RUN: %clang -### --hipstdpar --hipstdpar-path=%S/Inputs/hipstdpar \ +// RUN: --hipstdpar-thrust-path=%S/Inputs/hipstdpar/thrust \ +// RUN: --hipstdpar-prim-path=%S/Inputs/hipstdpar/rocprim \ +// RUN: -nogpulib -nogpuinc --compile %s 2>&1 | \ +// RUN: FileCheck --check-prefix=HIPSTDPAR-COMPILE %s +// RUN: touch %t.o +// RUN: %clang -### --hipstdpar %t.o 2>&1 | FileCheck --check-prefix=HIPSTDPAR-LINK %s + +// HIPSTDPAR-MISSING-LIB: error: cannot find HIP Standard Parallelism Acceleration library; provide it via '--hipstdpar-path' +// HIPSTDPAR-COMPILE: "-x" "hip" +// HIPSTDPAR-COMPILE: "-idirafter" "{{.*/thrust}}" +// HIPSTDPAR-COMPILE: "-idirafter" "{{.*/rocprim}}" +// HIPSTDPAR-COMPILE: "-idirafter" "{{.*/Inputs/hipstdpar}}" +// HIPSTDPAR-COMPILE: "-include" "hipstdpar_lib.hpp" +// HIPSTDPAR-LINK: "-rpath" +// HIPSTDPAR-LINK: "-l{{.*hip.*}}" diff --git a/clang/test/Driver/lto-jobs.c b/clang/test/Driver/lto-jobs.c index 73d7a94dd289cf..43a478b0664d84 100644 --- a/clang/test/Driver/lto-jobs.c +++ b/clang/test/Driver/lto-jobs.c @@ -17,3 +17,8 @@ // RUN: FileCheck -check-prefix=CHECK-LINK-THIN-JOBS2-ACTION < %t %s // // CHECK-LINK-THIN-JOBS2-ACTION: "-mllvm" "-threads={{[0-9]+}}" + +// RUN: %clang --target=powerpc-ibm-aix -### %s -flto=thin -flto-jobs=5 2> %t +// RUN: FileCheck -check-prefix=CHECK-AIX-LINK-THIN-JOBS-ACTION < %t %s +// +// CHECK-AIX-LINK-THIN-JOBS-ACTION: "-bplugin_opt:-threads=5" diff --git a/clang/test/Driver/mingw-linker-options.c b/clang/test/Driver/mingw-linker-options.c new file mode 100644 index 00000000000000..b4f1d05a719f3a --- /dev/null +++ b/clang/test/Driver/mingw-linker-options.c @@ -0,0 +1,10 @@ +// RUN: %clang --target=x86_64-windows-gnu -c -mwindows %s -### 2>&1 | FileCheck %s --check-prefix=WARNING +// RUN: %clang --target=x86_64-windows-gnu -c -mconsole %s -### 2>&1 | FileCheck %s --check-prefix=WARNING +// RUN: %clang --target=x86_64-windows-gnu -c -mdll %s -### 2>&1 | FileCheck %s --check-prefix=WARNING +// RUN: %clang --target=x86_64-windows-gnu -c -mthreads %s -### 2>&1 | FileCheck %s --check-prefix=WARNING +// RUN: not %clang --target=x86_64-windows-msvc -c -mwindows %s -### 2>&1 | FileCheck %s --check-prefix=ERROR +// RUN: not %clang --target=x86_64-windows-msvc -c -mconsole %s -### 2>&1 | FileCheck %s --check-prefix=ERROR +// RUN: not %clang --target=x86_64-windows-msvc -c -mdll %s -### 2>&1 | FileCheck %s --check-prefix=ERROR +// RUN: not %clang --target=x86_64-windows-msvc -c -mthreads %s -### 2>&1 | FileCheck %s --check-prefix=ERROR +// WARNING: warning: argument unused during compilation: '{{.*}}' [-Wunused-command-line-argument] +// ERROR: error: unsupported option '{{.*}}' for target '{{.*}}' diff --git a/clang/test/Driver/riscv-arch.c b/clang/test/Driver/riscv-arch.c index 92a6a59cba2317..0ac81ea982f1b6 100644 --- a/clang/test/Driver/riscv-arch.c +++ b/clang/test/Driver/riscv-arch.c @@ -372,24 +372,24 @@ // RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-ZFHMIN %s // RV32-ZFHMIN: "-target-feature" "+zfhmin" -// RUN: not %clang --target=riscv32-unknown-elf -march=rv32izfa -### %s \ +// RUN: not %clang --target=riscv32-unknown-elf -march=rv32iztso -### %s \ // RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-EXPERIMENTAL-NOFLAG %s -// RV32-EXPERIMENTAL-NOFLAG: error: invalid arch name 'rv32izfa' +// RV32-EXPERIMENTAL-NOFLAG: error: invalid arch name 'rv32iztso' // RV32-EXPERIMENTAL-NOFLAG: requires '-menable-experimental-extensions' -// RUN: not %clang --target=riscv32-unknown-elf -march=rv32izfa -menable-experimental-extensions -### %s \ +// RUN: not %clang --target=riscv32-unknown-elf -march=rv32iztso -menable-experimental-extensions -### %s \ // RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-EXPERIMENTAL-NOVERS %s -// RV32-EXPERIMENTAL-NOVERS: error: invalid arch name 'rv32izfa' +// RV32-EXPERIMENTAL-NOVERS: error: invalid arch name 'rv32iztso' // RV32-EXPERIMENTAL-NOVERS: experimental extension requires explicit version number -// RUN: not %clang --target=riscv32-unknown-elf -march=rv32izfa0p1 -menable-experimental-extensions -### %s \ +// RUN: not %clang --target=riscv32-unknown-elf -march=rv32iztso0p7 -menable-experimental-extensions -### %s \ // RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-EXPERIMENTAL-BADVERS %s -// RV32-EXPERIMENTAL-BADVERS: error: invalid arch name 'rv32izfa0p1' -// RV32-EXPERIMENTAL-BADVERS: unsupported version number 0.1 for experimental extension 'zfa' (this compiler supports 0.2) +// RV32-EXPERIMENTAL-BADVERS: error: invalid arch name 'rv32iztso0p7' +// RV32-EXPERIMENTAL-BADVERS: unsupported version number 0.7 for experimental extension 'ztso' (this compiler supports 0.1) -// RUN: %clang --target=riscv32-unknown-elf -march=rv32izfa0p2 -menable-experimental-extensions -### %s \ +// RUN: %clang --target=riscv32-unknown-elf -march=rv32iztso0p1 -menable-experimental-extensions -### %s \ // RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-EXPERIMENTAL-GOODVERS %s -// RV32-EXPERIMENTAL-GOODVERS: "-target-feature" "+experimental-zfa" +// RV32-EXPERIMENTAL-GOODVERS: "-target-feature" "+experimental-ztso" // RUN: %clang --target=riscv32-unknown-elf -march=rv32izbb1p0 -### %s \ // RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-ZBB %s diff --git a/clang/test/FixIt/fixit-deducing-this.cpp b/clang/test/FixIt/fixit-deducing-this.cpp new file mode 100644 index 00000000000000..c073fd38ffc2c5 --- /dev/null +++ b/clang/test/FixIt/fixit-deducing-this.cpp @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 -verify -std=c++2c %s +// RUN: cp %s %t +// RUN: not %clang_cc1 -x c++ -std=c++2c -fixit %t +// RUN: %clang_cc1 -x c++ -std=c++2c %t +// RUN: not %clang_cc1 -std=c++2c -x c++ -fsyntax-only -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s +struct S { + void f(this S); + void g() { + (void)&f; // expected-error {{must explicitly qualify name of member function when taking its address}} +// CHECK: fix-it:{{.*}}:{9:16-9:16}:"S::" + } +}; + +struct S2 { + void f(this S2 foo) { + g(); // expected-error {{call to non-static member function without an object argument}} +// CHECK: fix-it:{{.*}}:{16:9-16:9}:"foo." + + h(); // expected-error {{call to explicit member function without an object argument}} +// CHECK: fix-it:{{.*}}:{19:9-19:9}:"foo." + + i(); + + var; // expected-error {{invalid use of member 'var' in explicit object member function}} +// CHECK: fix-it:{{.*}}:{24:9-24:9}:"foo." + + } + void g(); + void h(this S2 s); + static void i(); + int var; +}; diff --git a/clang/test/FixIt/format-darwin-enum-class.cpp b/clang/test/FixIt/format-darwin-enum-class.cpp new file mode 100644 index 00000000000000..5aa1a80d8614c2 --- /dev/null +++ b/clang/test/FixIt/format-darwin-enum-class.cpp @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin -fsyntax-only -verify -Wformat %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin -fsyntax-only -fdiagnostics-parseable-fixits -Wformat %s 2>&1 | FileCheck %s + +extern "C" int printf(const char * restrict, ...); + +#if __LP64__ +typedef long CFIndex; +typedef long NSInteger; +typedef unsigned long NSUInteger; +#else +typedef int CFIndex; +typedef int NSInteger; +typedef unsigned int NSUInteger; +#endif + +enum class CFIndexEnum : CFIndex { One }; +enum class NSIntegerEnum : NSInteger { Two }; +enum class NSUIntegerEnum : NSUInteger { Three }; + +void f() { + printf("%d", CFIndexEnum::One); // expected-warning{{format specifies type 'int' but the argument has type 'CFIndexEnum'}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%ld" + // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:16-[[@LINE-2]]:16}:"static_cast(" + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:32-[[@LINE-3]]:32}:")" + + printf("%d", NSIntegerEnum::Two); // expected-warning{{format specifies type 'int' but the argument has type 'NSIntegerEnum'}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%ld" + // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:16-[[@LINE-2]]:16}:"static_cast(" + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:34-[[@LINE-3]]:34}:")" + + printf("%d", NSUIntegerEnum::Three); // expected-warning{{format specifies type 'int' but the argument has type 'NSUIntegerEnum'}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%lu" + // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:16-[[@LINE-2]]:16}:"static_cast(" + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:37-[[@LINE-3]]:37}:")" +} diff --git a/clang/test/FixIt/format.cpp b/clang/test/FixIt/format.cpp index 5016ee587ed1c4..4e6573a4f9e54e 100644 --- a/clang/test/FixIt/format.cpp +++ b/clang/test/FixIt/format.cpp @@ -12,21 +12,33 @@ struct S { N::E Type; }; +using uint32_t = unsigned; +enum class FixedE : uint32_t { Two }; + void a(N::E NEVal, S *SPtr, S &SRef) { printf("%d", N::E::One); // expected-warning{{format specifies type 'int' but the argument has type 'N::E'}} // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:16-[[@LINE-1]]:16}:"static_cast(" // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:25-[[@LINE-2]]:25}:")" printf("%hd", N::E::One); // expected-warning{{format specifies type 'short' but the argument has type 'N::E'}} - // CHECK: "static_cast(" + // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:14}:"%d" + // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:17-[[@LINE-2]]:17}:"static_cast(" + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:26-[[@LINE-3]]:26}:")" printf("%hu", N::E::One); // expected-warning{{format specifies type 'unsigned short' but the argument has type 'N::E'}} - // CHECK: "static_cast(" + // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:14}:"%d" + // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:17-[[@LINE-2]]:17}:"static_cast(" + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:26-[[@LINE-3]]:26}:")" LOG("%d", N::E::One); // expected-warning{{format specifies type 'int' but the argument has type 'N::E'}} // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:13-[[@LINE-1]]:13}:"static_cast(" // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:22-[[@LINE-2]]:22}:")" + LOG("%s", N::E::One); // expected-warning{{format specifies type 'char *' but the argument has type 'N::E'}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:8-[[@LINE-1]]:10}:"%d" + // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:13-[[@LINE-2]]:13}:"static_cast(" + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:22-[[@LINE-3]]:22}:")" + printf("%d", NEVal); // expected-warning{{format specifies type 'int' but the argument has type 'N::E'}} // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:16-[[@LINE-1]]:16}:"static_cast(" // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:21-[[@LINE-2]]:21}:")" @@ -58,4 +70,8 @@ void a(N::E NEVal, S *SPtr, S &SRef) { SRef.Type); // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:7-[[@LINE-1]]:7}:"static_cast(" // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:16-[[@LINE-2]]:16}:")" + + printf("%u", FixedE::Two); //expected-warning{{format specifies type 'unsigned int' but the argument has type 'FixedE'}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:16-[[@LINE-1]]:16}:"static_cast(" + // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:27-[[@LINE-2]]:27}:")" } diff --git a/clang/test/Headers/__clang_hip_cmath.hip b/clang/test/Headers/__clang_hip_cmath.hip index f66f5f3c3ee440..c194f4437890d0 100644 --- a/clang/test/Headers/__clang_hip_cmath.hip +++ b/clang/test/Headers/__clang_hip_cmath.hip @@ -18,12 +18,12 @@ // DEFAULT-LABEL: @test_fma_f16( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract half @llvm.fma.f16(half [[X:%.*]], half [[Y:%.*]], half [[Z:%.*]]) +// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract noundef half @llvm.fma.f16(half [[X:%.*]], half [[Y:%.*]], half [[Z:%.*]]) // DEFAULT-NEXT: ret half [[TMP0]] // // FINITEONLY-LABEL: @test_fma_f16( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract half @llvm.fma.f16(half [[X:%.*]], half [[Y:%.*]], half [[Z:%.*]]) +// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract noundef half @llvm.fma.f16(half [[X:%.*]], half [[Y:%.*]], half [[Z:%.*]]) // FINITEONLY-NEXT: ret half [[TMP0]] // extern "C" __device__ _Float16 test_fma_f16(_Float16 x, _Float16 y, @@ -33,12 +33,12 @@ extern "C" __device__ _Float16 test_fma_f16(_Float16 x, _Float16 y, // DEFAULT-LABEL: @test_pow_f16( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract half @__ocml_pown_f16(half noundef [[X:%.*]], i32 noundef [[Y:%.*]]) #[[ATTR7:[0-9]+]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef half @__ocml_pown_f16(half noundef [[X:%.*]], i32 noundef [[Y:%.*]]) #[[ATTR7:[0-9]+]] // DEFAULT-NEXT: ret half [[CALL_I]] // // FINITEONLY-LABEL: @test_pow_f16( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) half @__ocml_pown_f16(half noundef nofpclass(nan inf) [[X:%.*]], i32 noundef [[Y:%.*]]) #[[ATTR7:[0-9]+]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) half @__ocml_pown_f16(half noundef nofpclass(nan inf) [[X:%.*]], i32 noundef [[Y:%.*]]) #[[ATTR7:[0-9]+]] // FINITEONLY-NEXT: ret half [[CALL_I]] // extern "C" __device__ _Float16 test_pow_f16(_Float16 x, int y) { @@ -47,12 +47,12 @@ extern "C" __device__ _Float16 test_pow_f16(_Float16 x, int y) { // DEFAULT-LABEL: @test_fabs_f32( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract float @llvm.fabs.f32(float [[X:%.*]]) +// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract noundef float @llvm.fabs.f32(float [[X:%.*]]) // DEFAULT-NEXT: ret float [[TMP0]] // // FINITEONLY-LABEL: @test_fabs_f32( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract float @llvm.fabs.f32(float [[X:%.*]]) +// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract noundef float @llvm.fabs.f32(float [[X:%.*]]) // FINITEONLY-NEXT: ret float [[TMP0]] // extern "C" __device__ float test_fabs_f32(float x) { @@ -61,12 +61,12 @@ extern "C" __device__ float test_fabs_f32(float x) { // DEFAULT-LABEL: @test_sin_f32( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I_I:%.*]] = tail call contract float @__ocml_sin_f32(float noundef [[X:%.*]]) #[[ATTR8:[0-9]+]] +// DEFAULT-NEXT: [[CALL_I_I:%.*]] = tail call contract noundef float @__ocml_sin_f32(float noundef [[X:%.*]]) #[[ATTR8:[0-9]+]] // DEFAULT-NEXT: ret float [[CALL_I_I]] // // FINITEONLY-LABEL: @test_sin_f32( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) float @__ocml_sin_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR8:[0-9]+]] +// FINITEONLY-NEXT: [[CALL_I_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_sin_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR8:[0-9]+]] // FINITEONLY-NEXT: ret float [[CALL_I_I]] // extern "C" __device__ float test_sin_f32(float x) { @@ -75,12 +75,12 @@ extern "C" __device__ float test_sin_f32(float x) { // DEFAULT-LABEL: @test_cos_f32( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I_I:%.*]] = tail call contract float @__ocml_cos_f32(float noundef [[X:%.*]]) #[[ATTR8]] +// DEFAULT-NEXT: [[CALL_I_I:%.*]] = tail call contract noundef float @__ocml_cos_f32(float noundef [[X:%.*]]) #[[ATTR8]] // DEFAULT-NEXT: ret float [[CALL_I_I]] // // FINITEONLY-LABEL: @test_cos_f32( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) float @__ocml_cos_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR8]] +// FINITEONLY-NEXT: [[CALL_I_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_cos_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR8]] // FINITEONLY-NEXT: ret float [[CALL_I_I]] // extern "C" __device__ float test_cos_f32(float x) { diff --git a/clang/test/Headers/__clang_hip_math.hip b/clang/test/Headers/__clang_hip_math.hip index aa69bac6b624d6..15eccc3b2baba0 100644 --- a/clang/test/Headers/__clang_hip_math.hip +++ b/clang/test/Headers/__clang_hip_math.hip @@ -231,8 +231,8 @@ extern "C" __device__ uint64_t test___make_mantissa(const char *p) { // CHECK-LABEL: @test_abs( // CHECK-NEXT: entry: -// CHECK-NEXT: [[ABS_I:%.*]] = tail call i32 @llvm.abs.i32(i32 [[X:%.*]], i1 true) -// CHECK-NEXT: ret i32 [[ABS_I]] +// CHECK-NEXT: [[TMP0:%.*]] = tail call noundef i32 @llvm.abs.i32(i32 [[X:%.*]], i1 true) +// CHECK-NEXT: ret i32 [[TMP0]] // extern "C" __device__ int test_abs(int x) { return abs(x); @@ -240,8 +240,8 @@ extern "C" __device__ int test_abs(int x) { // CHECK-LABEL: @test_labs( // CHECK-NEXT: entry: -// CHECK-NEXT: [[ABS_I:%.*]] = tail call i64 @llvm.abs.i64(i64 [[X:%.*]], i1 true) -// CHECK-NEXT: ret i64 [[ABS_I]] +// CHECK-NEXT: [[TMP0:%.*]] = tail call noundef i64 @llvm.abs.i64(i64 [[X:%.*]], i1 true) +// CHECK-NEXT: ret i64 [[TMP0]] // extern "C" __device__ long test_labs(long x) { return labs(x); @@ -249,8 +249,8 @@ extern "C" __device__ long test_labs(long x) { // CHECK-LABEL: @test_llabs( // CHECK-NEXT: entry: -// CHECK-NEXT: [[ABS_I:%.*]] = tail call i64 @llvm.abs.i64(i64 [[X:%.*]], i1 true) -// CHECK-NEXT: ret i64 [[ABS_I]] +// CHECK-NEXT: [[TMP0:%.*]] = tail call noundef i64 @llvm.abs.i64(i64 [[X:%.*]], i1 true) +// CHECK-NEXT: ret i64 [[TMP0]] // extern "C" __device__ long long test_llabs(long x) { return llabs(x); @@ -258,17 +258,17 @@ extern "C" __device__ long long test_llabs(long x) { // DEFAULT-LABEL: @test_acosf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_acos_f32(float noundef [[X:%.*]]) #[[ATTR14:[0-9]+]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_acos_f32(float noundef [[X:%.*]]) #[[ATTR14:[0-9]+]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_acosf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) float @__ocml_acos_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR14:[0-9]+]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_acos_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR14:[0-9]+]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_acosf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_acos_f32(float noundef [[X:%.*]]) #[[ATTR14:[0-9]+]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_acos_f32(float noundef [[X:%.*]]) #[[ATTR14:[0-9]+]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_acosf(float x) { @@ -277,17 +277,17 @@ extern "C" __device__ float test_acosf(float x) { // DEFAULT-LABEL: @test_acos( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_acos_f64(double noundef [[X:%.*]]) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_acos_f64(double noundef [[X:%.*]]) #[[ATTR14]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_acos( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) double @__ocml_acos_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_acos_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR14]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_acos( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_acos_f64(double noundef [[X:%.*]]) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_acos_f64(double noundef [[X:%.*]]) #[[ATTR14]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_acos(double x) { @@ -296,17 +296,17 @@ extern "C" __device__ double test_acos(double x) { // DEFAULT-LABEL: @test_acoshf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_acosh_f32(float noundef [[X:%.*]]) #[[ATTR15:[0-9]+]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_acosh_f32(float noundef [[X:%.*]]) #[[ATTR15:[0-9]+]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_acoshf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) float @__ocml_acosh_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15:[0-9]+]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_acosh_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15:[0-9]+]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_acoshf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_acosh_f32(float noundef [[X:%.*]]) #[[ATTR15:[0-9]+]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_acosh_f32(float noundef [[X:%.*]]) #[[ATTR15:[0-9]+]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_acoshf(float x) { @@ -315,17 +315,17 @@ extern "C" __device__ float test_acoshf(float x) { // DEFAULT-LABEL: @test_acosh( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_acosh_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_acosh_f64(double noundef [[X:%.*]]) #[[ATTR15]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_acosh( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) double @__ocml_acosh_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_acosh_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_acosh( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_acosh_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_acosh_f64(double noundef [[X:%.*]]) #[[ATTR15]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_acosh(double x) { @@ -334,17 +334,17 @@ extern "C" __device__ double test_acosh(double x) { // DEFAULT-LABEL: @test_asinf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_asin_f32(float noundef [[X:%.*]]) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_asin_f32(float noundef [[X:%.*]]) #[[ATTR14]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_asinf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) float @__ocml_asin_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_asin_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR14]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_asinf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_asin_f32(float noundef [[X:%.*]]) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_asin_f32(float noundef [[X:%.*]]) #[[ATTR14]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_asinf(float x) { @@ -353,17 +353,17 @@ extern "C" __device__ float test_asinf(float x) { // DEFAULT-LABEL: @test_asin( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_asin_f64(double noundef [[X:%.*]]) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_asin_f64(double noundef [[X:%.*]]) #[[ATTR14]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_asin( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) double @__ocml_asin_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_asin_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR14]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_asin( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_asin_f64(double noundef [[X:%.*]]) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_asin_f64(double noundef [[X:%.*]]) #[[ATTR14]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_asin(double x) { @@ -373,17 +373,17 @@ extern "C" __device__ double test_asin(double x) { // DEFAULT-LABEL: @test_asinhf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_asinh_f32(float noundef [[X:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_asinh_f32(float noundef [[X:%.*]]) #[[ATTR15]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_asinhf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) float @__ocml_asinh_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_asinh_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_asinhf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_asinh_f32(float noundef [[X:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_asinh_f32(float noundef [[X:%.*]]) #[[ATTR15]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_asinhf(float x) { @@ -392,17 +392,17 @@ extern "C" __device__ float test_asinhf(float x) { // DEFAULT-LABEL: @test_asinh( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_asinh_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_asinh_f64(double noundef [[X:%.*]]) #[[ATTR15]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_asinh( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) double @__ocml_asinh_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_asinh_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_asinh( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_asinh_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_asinh_f64(double noundef [[X:%.*]]) #[[ATTR15]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_asinh(double x) { @@ -411,17 +411,17 @@ extern "C" __device__ double test_asinh(double x) { // DEFAULT-LABEL: @test_atan2f( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_atan2_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_atan2_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR14]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_atan2f( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) float @__ocml_atan2_f32(float noundef nofpclass(nan inf) [[X:%.*]], float noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_atan2_f32(float noundef nofpclass(nan inf) [[X:%.*]], float noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR14]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_atan2f( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_atan2_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_atan2_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR14]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_atan2f(float x, float y) { @@ -430,17 +430,17 @@ extern "C" __device__ float test_atan2f(float x, float y) { // DEFAULT-LABEL: @test_atan2( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_atan2_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_atan2_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR14]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_atan2( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) double @__ocml_atan2_f64(double noundef nofpclass(nan inf) [[X:%.*]], double noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_atan2_f64(double noundef nofpclass(nan inf) [[X:%.*]], double noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR14]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_atan2( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_atan2_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_atan2_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR14]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_atan2(double x, double y) { @@ -449,17 +449,17 @@ extern "C" __device__ double test_atan2(double x, double y) { // DEFAULT-LABEL: @test_atanf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_atan_f32(float noundef [[X:%.*]]) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_atan_f32(float noundef [[X:%.*]]) #[[ATTR14]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_atanf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) float @__ocml_atan_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_atan_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR14]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_atanf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_atan_f32(float noundef [[X:%.*]]) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_atan_f32(float noundef [[X:%.*]]) #[[ATTR14]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_atanf(float x) { @@ -468,17 +468,17 @@ extern "C" __device__ float test_atanf(float x) { // DEFAULT-LABEL: @test_atan( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_atan_f64(double noundef [[X:%.*]]) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_atan_f64(double noundef [[X:%.*]]) #[[ATTR14]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_atan( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) double @__ocml_atan_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_atan_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR14]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_atan( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_atan_f64(double noundef [[X:%.*]]) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_atan_f64(double noundef [[X:%.*]]) #[[ATTR14]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_atan(double x) { @@ -487,17 +487,17 @@ extern "C" __device__ double test_atan(double x) { // DEFAULT-LABEL: @test_atanhf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_atanh_f32(float noundef [[X:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_atanh_f32(float noundef [[X:%.*]]) #[[ATTR15]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_atanhf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) float @__ocml_atanh_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_atanh_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_atanhf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_atanh_f32(float noundef [[X:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_atanh_f32(float noundef [[X:%.*]]) #[[ATTR15]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_atanhf(float x) { @@ -506,17 +506,17 @@ extern "C" __device__ float test_atanhf(float x) { // DEFAULT-LABEL: @test_atanh( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_atanh_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_atanh_f64(double noundef [[X:%.*]]) #[[ATTR15]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_atanh( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) double @__ocml_atanh_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_atanh_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_atanh( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_atanh_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_atanh_f64(double noundef [[X:%.*]]) #[[ATTR15]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_atanh(double x) { @@ -525,17 +525,17 @@ extern "C" __device__ double test_atanh(double x) { // DEFAULT-LABEL: @test_cbrtf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_cbrt_f32(float noundef [[X:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_cbrt_f32(float noundef [[X:%.*]]) #[[ATTR15]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_cbrtf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) float @__ocml_cbrt_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_cbrt_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_cbrtf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_cbrt_f32(float noundef [[X:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_cbrt_f32(float noundef [[X:%.*]]) #[[ATTR15]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_cbrtf(float x) { @@ -544,17 +544,17 @@ extern "C" __device__ float test_cbrtf(float x) { // DEFAULT-LABEL: @test_cbrt( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_cbrt_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_cbrt_f64(double noundef [[X:%.*]]) #[[ATTR15]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_cbrt( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) double @__ocml_cbrt_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_cbrt_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_cbrt( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_cbrt_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_cbrt_f64(double noundef [[X:%.*]]) #[[ATTR15]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_cbrt(double x) { @@ -563,17 +563,17 @@ extern "C" __device__ double test_cbrt(double x) { // DEFAULT-LABEL: @test_ceilf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract float @llvm.ceil.f32(float [[X:%.*]]) +// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract noundef float @llvm.ceil.f32(float [[X:%.*]]) // DEFAULT-NEXT: ret float [[TMP0]] // // FINITEONLY-LABEL: @test_ceilf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract float @llvm.ceil.f32(float [[X:%.*]]) +// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract noundef float @llvm.ceil.f32(float [[X:%.*]]) // FINITEONLY-NEXT: ret float [[TMP0]] // // APPROX-LABEL: @test_ceilf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[TMP0:%.*]] = tail call contract float @llvm.ceil.f32(float [[X:%.*]]) +// APPROX-NEXT: [[TMP0:%.*]] = tail call contract noundef float @llvm.ceil.f32(float [[X:%.*]]) // APPROX-NEXT: ret float [[TMP0]] // extern "C" __device__ float test_ceilf(float x) { @@ -582,17 +582,17 @@ extern "C" __device__ float test_ceilf(float x) { // DEFAULT-LABEL: @test_ceil( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract double @llvm.ceil.f64(double [[X:%.*]]) +// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract noundef double @llvm.ceil.f64(double [[X:%.*]]) // DEFAULT-NEXT: ret double [[TMP0]] // // FINITEONLY-LABEL: @test_ceil( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract double @llvm.ceil.f64(double [[X:%.*]]) +// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract noundef double @llvm.ceil.f64(double [[X:%.*]]) // FINITEONLY-NEXT: ret double [[TMP0]] // // APPROX-LABEL: @test_ceil( // APPROX-NEXT: entry: -// APPROX-NEXT: [[TMP0:%.*]] = tail call contract double @llvm.ceil.f64(double [[X:%.*]]) +// APPROX-NEXT: [[TMP0:%.*]] = tail call contract noundef double @llvm.ceil.f64(double [[X:%.*]]) // APPROX-NEXT: ret double [[TMP0]] // extern "C" __device__ double test_ceil(double x) { @@ -601,17 +601,17 @@ extern "C" __device__ double test_ceil(double x) { // DEFAULT-LABEL: @test_copysignf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract float @llvm.copysign.f32(float [[X:%.*]], float [[Y:%.*]]) +// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract noundef float @llvm.copysign.f32(float [[X:%.*]], float [[Y:%.*]]) // DEFAULT-NEXT: ret float [[TMP0]] // // FINITEONLY-LABEL: @test_copysignf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract float @llvm.copysign.f32(float [[X:%.*]], float [[Y:%.*]]) +// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract noundef float @llvm.copysign.f32(float [[X:%.*]], float [[Y:%.*]]) // FINITEONLY-NEXT: ret float [[TMP0]] // // APPROX-LABEL: @test_copysignf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[TMP0:%.*]] = tail call contract float @llvm.copysign.f32(float [[X:%.*]], float [[Y:%.*]]) +// APPROX-NEXT: [[TMP0:%.*]] = tail call contract noundef float @llvm.copysign.f32(float [[X:%.*]], float [[Y:%.*]]) // APPROX-NEXT: ret float [[TMP0]] // extern "C" __device__ float test_copysignf(float x, float y) { @@ -620,17 +620,17 @@ extern "C" __device__ float test_copysignf(float x, float y) { // DEFAULT-LABEL: @test_copysign( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract double @llvm.copysign.f64(double [[X:%.*]], double [[Y:%.*]]) +// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract noundef double @llvm.copysign.f64(double [[X:%.*]], double [[Y:%.*]]) // DEFAULT-NEXT: ret double [[TMP0]] // // FINITEONLY-LABEL: @test_copysign( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract double @llvm.copysign.f64(double [[X:%.*]], double [[Y:%.*]]) +// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract noundef double @llvm.copysign.f64(double [[X:%.*]], double [[Y:%.*]]) // FINITEONLY-NEXT: ret double [[TMP0]] // // APPROX-LABEL: @test_copysign( // APPROX-NEXT: entry: -// APPROX-NEXT: [[TMP0:%.*]] = tail call contract double @llvm.copysign.f64(double [[X:%.*]], double [[Y:%.*]]) +// APPROX-NEXT: [[TMP0:%.*]] = tail call contract noundef double @llvm.copysign.f64(double [[X:%.*]], double [[Y:%.*]]) // APPROX-NEXT: ret double [[TMP0]] // extern "C" __device__ double test_copysign(double x, double y) { @@ -639,17 +639,17 @@ extern "C" __device__ double test_copysign(double x, double y) { // DEFAULT-LABEL: @test_cosf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_cos_f32(float noundef [[X:%.*]]) #[[ATTR16:[0-9]+]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_cos_f32(float noundef [[X:%.*]]) #[[ATTR16:[0-9]+]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_cosf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) float @__ocml_cos_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16:[0-9]+]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_cos_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16:[0-9]+]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_cosf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I_I:%.*]] = tail call contract float @__ocml_native_cos_f32(float noundef [[X:%.*]]) #[[ATTR16:[0-9]+]] +// APPROX-NEXT: [[CALL_I_I:%.*]] = tail call contract noundef float @__ocml_native_cos_f32(float noundef [[X:%.*]]) #[[ATTR16:[0-9]+]] // APPROX-NEXT: ret float [[CALL_I_I]] // extern "C" __device__ float test_cosf(float x) { @@ -658,17 +658,17 @@ extern "C" __device__ float test_cosf(float x) { // DEFAULT-LABEL: @test_cos( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_cos_f64(double noundef [[X:%.*]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_cos_f64(double noundef [[X:%.*]]) #[[ATTR16]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_cos( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) double @__ocml_cos_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_cos_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_cos( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_cos_f64(double noundef [[X:%.*]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_cos_f64(double noundef [[X:%.*]]) #[[ATTR16]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_cos(double x) { @@ -677,17 +677,17 @@ extern "C" __device__ double test_cos(double x) { // DEFAULT-LABEL: @test_coshf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_cosh_f32(float noundef [[X:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_cosh_f32(float noundef [[X:%.*]]) #[[ATTR15]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_coshf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) float @__ocml_cosh_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_cosh_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_coshf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_cosh_f32(float noundef [[X:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_cosh_f32(float noundef [[X:%.*]]) #[[ATTR15]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_coshf(float x) { @@ -696,17 +696,17 @@ extern "C" __device__ float test_coshf(float x) { // DEFAULT-LABEL: @test_cosh( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_cosh_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_cosh_f64(double noundef [[X:%.*]]) #[[ATTR15]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_cosh( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) double @__ocml_cosh_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_cosh_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_cosh( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_cosh_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_cosh_f64(double noundef [[X:%.*]]) #[[ATTR15]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_cosh(double x) { @@ -715,17 +715,17 @@ extern "C" __device__ double test_cosh(double x) { // DEFAULT-LABEL: @test_cospif( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_cospi_f32(float noundef [[X:%.*]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_cospi_f32(float noundef [[X:%.*]]) #[[ATTR16]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_cospif( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) float @__ocml_cospi_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_cospi_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_cospif( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_cospi_f32(float noundef [[X:%.*]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_cospi_f32(float noundef [[X:%.*]]) #[[ATTR16]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_cospif(float x) { @@ -734,17 +734,17 @@ extern "C" __device__ float test_cospif(float x) { // DEFAULT-LABEL: @test_cospi( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_cospi_f64(double noundef [[X:%.*]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_cospi_f64(double noundef [[X:%.*]]) #[[ATTR16]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_cospi( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) double @__ocml_cospi_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_cospi_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_cospi( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_cospi_f64(double noundef [[X:%.*]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_cospi_f64(double noundef [[X:%.*]]) #[[ATTR16]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_cospi(double x) { @@ -753,17 +753,17 @@ extern "C" __device__ double test_cospi(double x) { // DEFAULT-LABEL: @test_cyl_bessel_i0f( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_i0_f32(float noundef [[X:%.*]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_i0_f32(float noundef [[X:%.*]]) #[[ATTR16]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_cyl_bessel_i0f( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) float @__ocml_i0_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_i0_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_cyl_bessel_i0f( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_i0_f32(float noundef [[X:%.*]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_i0_f32(float noundef [[X:%.*]]) #[[ATTR16]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_cyl_bessel_i0f(float x) { @@ -772,17 +772,17 @@ extern "C" __device__ float test_cyl_bessel_i0f(float x) { // DEFAULT-LABEL: @test_cyl_bessel_i0( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_i0_f64(double noundef [[X:%.*]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_i0_f64(double noundef [[X:%.*]]) #[[ATTR16]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_cyl_bessel_i0( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) double @__ocml_i0_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_i0_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_cyl_bessel_i0( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_i0_f64(double noundef [[X:%.*]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_i0_f64(double noundef [[X:%.*]]) #[[ATTR16]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_cyl_bessel_i0(double x) { @@ -791,17 +791,17 @@ extern "C" __device__ double test_cyl_bessel_i0(double x) { // DEFAULT-LABEL: @test_cyl_bessel_i1f( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_i1_f32(float noundef [[X:%.*]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_i1_f32(float noundef [[X:%.*]]) #[[ATTR16]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_cyl_bessel_i1f( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) float @__ocml_i1_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_i1_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_cyl_bessel_i1f( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_i1_f32(float noundef [[X:%.*]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_i1_f32(float noundef [[X:%.*]]) #[[ATTR16]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_cyl_bessel_i1f(float x) { @@ -810,17 +810,17 @@ extern "C" __device__ float test_cyl_bessel_i1f(float x) { // DEFAULT-LABEL: @test_cyl_bessel_i1( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_i1_f64(double noundef [[X:%.*]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_i1_f64(double noundef [[X:%.*]]) #[[ATTR16]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_cyl_bessel_i1( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) double @__ocml_i1_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_i1_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_cyl_bessel_i1( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_i1_f64(double noundef [[X:%.*]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_i1_f64(double noundef [[X:%.*]]) #[[ATTR16]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_cyl_bessel_i1(double x) { @@ -829,17 +829,17 @@ extern "C" __device__ double test_cyl_bessel_i1(double x) { // DEFAULT-LABEL: @test_erfcf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_erfc_f32(float noundef [[X:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_erfc_f32(float noundef [[X:%.*]]) #[[ATTR15]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_erfcf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) float @__ocml_erfc_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_erfc_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_erfcf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_erfc_f32(float noundef [[X:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_erfc_f32(float noundef [[X:%.*]]) #[[ATTR15]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_erfcf(float x) { @@ -848,17 +848,17 @@ extern "C" __device__ float test_erfcf(float x) { // DEFAULT-LABEL: @test_erfc( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_erfc_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_erfc_f64(double noundef [[X:%.*]]) #[[ATTR15]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_erfc( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) double @__ocml_erfc_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_erfc_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_erfc( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_erfc_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_erfc_f64(double noundef [[X:%.*]]) #[[ATTR15]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_erfc(double x) { @@ -867,17 +867,17 @@ extern "C" __device__ double test_erfc(double x) { // DEFAULT-LABEL: @test_erfinvf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_erfinv_f32(float noundef [[X:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_erfinv_f32(float noundef [[X:%.*]]) #[[ATTR15]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_erfinvf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) float @__ocml_erfinv_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_erfinv_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_erfinvf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_erfinv_f32(float noundef [[X:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_erfinv_f32(float noundef [[X:%.*]]) #[[ATTR15]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_erfinvf(float x) { @@ -886,17 +886,17 @@ extern "C" __device__ float test_erfinvf(float x) { // DEFAULT-LABEL: @test_erfinv( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_erfinv_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_erfinv_f64(double noundef [[X:%.*]]) #[[ATTR15]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_erfinv( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) double @__ocml_erfinv_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_erfinv_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_erfinv( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_erfinv_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_erfinv_f64(double noundef [[X:%.*]]) #[[ATTR15]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_erfinv(double x) { @@ -905,17 +905,17 @@ extern "C" __device__ double test_erfinv(double x) { // DEFAULT-LABEL: @test_exp10f( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_exp10_f32(float noundef [[X:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_exp10_f32(float noundef [[X:%.*]]) #[[ATTR15]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_exp10f( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) float @__ocml_exp10_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_exp10_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_exp10f( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_exp10_f32(float noundef [[X:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_exp10_f32(float noundef [[X:%.*]]) #[[ATTR15]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_exp10f(float x) { @@ -924,17 +924,17 @@ extern "C" __device__ float test_exp10f(float x) { // DEFAULT-LABEL: @test_exp10( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_exp10_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_exp10_f64(double noundef [[X:%.*]]) #[[ATTR15]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_exp10( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) double @__ocml_exp10_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_exp10_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_exp10( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_exp10_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_exp10_f64(double noundef [[X:%.*]]) #[[ATTR15]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_exp10(double x) { @@ -943,17 +943,17 @@ extern "C" __device__ double test_exp10(double x) { // DEFAULT-LABEL: @test_exp2f( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract float @llvm.exp2.f32(float [[X:%.*]]) +// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract noundef float @llvm.exp2.f32(float [[X:%.*]]) // DEFAULT-NEXT: ret float [[TMP0]] // // FINITEONLY-LABEL: @test_exp2f( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract float @llvm.exp2.f32(float [[X:%.*]]) +// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract noundef float @llvm.exp2.f32(float [[X:%.*]]) // FINITEONLY-NEXT: ret float [[TMP0]] // // APPROX-LABEL: @test_exp2f( // APPROX-NEXT: entry: -// APPROX-NEXT: [[TMP0:%.*]] = tail call contract float @llvm.exp2.f32(float [[X:%.*]]) +// APPROX-NEXT: [[TMP0:%.*]] = tail call contract noundef float @llvm.exp2.f32(float [[X:%.*]]) // APPROX-NEXT: ret float [[TMP0]] // extern "C" __device__ float test_exp2f(float x) { @@ -962,17 +962,17 @@ extern "C" __device__ float test_exp2f(float x) { // DEFAULT-LABEL: @test_exp2( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_exp2_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_exp2_f64(double noundef [[X:%.*]]) #[[ATTR15]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_exp2( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) double @__ocml_exp2_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_exp2_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_exp2( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_exp2_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_exp2_f64(double noundef [[X:%.*]]) #[[ATTR15]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_exp2(double x) { @@ -981,17 +981,17 @@ extern "C" __device__ double test_exp2(double x) { // DEFAULT-LABEL: @test_expf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract float @llvm.exp.f32(float [[X:%.*]]) +// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract noundef float @llvm.exp.f32(float [[X:%.*]]) // DEFAULT-NEXT: ret float [[TMP0]] // // FINITEONLY-LABEL: @test_expf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract float @llvm.exp.f32(float [[X:%.*]]) +// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract noundef float @llvm.exp.f32(float [[X:%.*]]) // FINITEONLY-NEXT: ret float [[TMP0]] // // APPROX-LABEL: @test_expf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[TMP0:%.*]] = tail call contract float @llvm.exp.f32(float [[X:%.*]]) +// APPROX-NEXT: [[TMP0:%.*]] = tail call contract noundef float @llvm.exp.f32(float [[X:%.*]]) // APPROX-NEXT: ret float [[TMP0]] // extern "C" __device__ float test_expf(float x) { @@ -1000,17 +1000,17 @@ extern "C" __device__ float test_expf(float x) { // DEFAULT-LABEL: @test_exp( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_exp_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_exp_f64(double noundef [[X:%.*]]) #[[ATTR15]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_exp( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) double @__ocml_exp_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_exp_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_exp( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_exp_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_exp_f64(double noundef [[X:%.*]]) #[[ATTR15]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_exp(double x) { @@ -1019,17 +1019,17 @@ extern "C" __device__ double test_exp(double x) { // DEFAULT-LABEL: @test_expm1f( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_expm1_f32(float noundef [[X:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_expm1_f32(float noundef [[X:%.*]]) #[[ATTR15]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_expm1f( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) float @__ocml_expm1_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_expm1_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_expm1f( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_expm1_f32(float noundef [[X:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_expm1_f32(float noundef [[X:%.*]]) #[[ATTR15]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_expm1f(float x) { @@ -1038,17 +1038,17 @@ extern "C" __device__ float test_expm1f(float x) { // DEFAULT-LABEL: @test_expm1( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_expm1_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_expm1_f64(double noundef [[X:%.*]]) #[[ATTR15]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_expm1( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) double @__ocml_expm1_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_expm1_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_expm1( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_expm1_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_expm1_f64(double noundef [[X:%.*]]) #[[ATTR15]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_expm1(double x) { @@ -1057,17 +1057,17 @@ extern "C" __device__ double test_expm1(double x) { // DEFAULT-LABEL: @test_fabsf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract float @llvm.fabs.f32(float [[X:%.*]]) +// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract noundef float @llvm.fabs.f32(float [[X:%.*]]) // DEFAULT-NEXT: ret float [[TMP0]] // // FINITEONLY-LABEL: @test_fabsf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract float @llvm.fabs.f32(float [[X:%.*]]) +// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract noundef float @llvm.fabs.f32(float [[X:%.*]]) // FINITEONLY-NEXT: ret float [[TMP0]] // // APPROX-LABEL: @test_fabsf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[TMP0:%.*]] = tail call contract float @llvm.fabs.f32(float [[X:%.*]]) +// APPROX-NEXT: [[TMP0:%.*]] = tail call contract noundef float @llvm.fabs.f32(float [[X:%.*]]) // APPROX-NEXT: ret float [[TMP0]] // extern "C" __device__ float test_fabsf(float x) { @@ -1076,17 +1076,17 @@ extern "C" __device__ float test_fabsf(float x) { // DEFAULT-LABEL: @test_fabs( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract double @llvm.fabs.f64(double [[X:%.*]]) +// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract noundef double @llvm.fabs.f64(double [[X:%.*]]) // DEFAULT-NEXT: ret double [[TMP0]] // // FINITEONLY-LABEL: @test_fabs( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract double @llvm.fabs.f64(double [[X:%.*]]) +// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract noundef double @llvm.fabs.f64(double [[X:%.*]]) // FINITEONLY-NEXT: ret double [[TMP0]] // // APPROX-LABEL: @test_fabs( // APPROX-NEXT: entry: -// APPROX-NEXT: [[TMP0:%.*]] = tail call contract double @llvm.fabs.f64(double [[X:%.*]]) +// APPROX-NEXT: [[TMP0:%.*]] = tail call contract noundef double @llvm.fabs.f64(double [[X:%.*]]) // APPROX-NEXT: ret double [[TMP0]] // extern "C" __device__ double test_fabs(double x) { @@ -1095,17 +1095,17 @@ extern "C" __device__ double test_fabs(double x) { // DEFAULT-LABEL: @test_fdimf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_fdim_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_fdim_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR14]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_fdimf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) float @__ocml_fdim_f32(float noundef nofpclass(nan inf) [[X:%.*]], float noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_fdim_f32(float noundef nofpclass(nan inf) [[X:%.*]], float noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR14]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_fdimf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_fdim_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_fdim_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR14]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_fdimf(float x, float y) { @@ -1114,17 +1114,17 @@ extern "C" __device__ float test_fdimf(float x, float y) { // DEFAULT-LABEL: @test_fdim( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_fdim_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_fdim_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR14]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_fdim( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) double @__ocml_fdim_f64(double noundef nofpclass(nan inf) [[X:%.*]], double noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_fdim_f64(double noundef nofpclass(nan inf) [[X:%.*]], double noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR14]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_fdim( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_fdim_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_fdim_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR14]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_fdim(double x, double y) { @@ -1152,17 +1152,17 @@ extern "C" __device__ float test_fdividef(float x, float y) { // DEFAULT-LABEL: @test_floorf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract float @llvm.floor.f32(float [[X:%.*]]) +// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract noundef float @llvm.floor.f32(float [[X:%.*]]) // DEFAULT-NEXT: ret float [[TMP0]] // // FINITEONLY-LABEL: @test_floorf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract float @llvm.floor.f32(float [[X:%.*]]) +// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract noundef float @llvm.floor.f32(float [[X:%.*]]) // FINITEONLY-NEXT: ret float [[TMP0]] // // APPROX-LABEL: @test_floorf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[TMP0:%.*]] = tail call contract float @llvm.floor.f32(float [[X:%.*]]) +// APPROX-NEXT: [[TMP0:%.*]] = tail call contract noundef float @llvm.floor.f32(float [[X:%.*]]) // APPROX-NEXT: ret float [[TMP0]] // extern "C" __device__ float test_floorf(float x) { @@ -1171,17 +1171,17 @@ extern "C" __device__ float test_floorf(float x) { // DEFAULT-LABEL: @test_floor( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract double @llvm.floor.f64(double [[X:%.*]]) +// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract noundef double @llvm.floor.f64(double [[X:%.*]]) // DEFAULT-NEXT: ret double [[TMP0]] // // FINITEONLY-LABEL: @test_floor( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract double @llvm.floor.f64(double [[X:%.*]]) +// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract noundef double @llvm.floor.f64(double [[X:%.*]]) // FINITEONLY-NEXT: ret double [[TMP0]] // // APPROX-LABEL: @test_floor( // APPROX-NEXT: entry: -// APPROX-NEXT: [[TMP0:%.*]] = tail call contract double @llvm.floor.f64(double [[X:%.*]]) +// APPROX-NEXT: [[TMP0:%.*]] = tail call contract noundef double @llvm.floor.f64(double [[X:%.*]]) // APPROX-NEXT: ret double [[TMP0]] // extern "C" __device__ double test_floor(double x) { @@ -1190,17 +1190,17 @@ extern "C" __device__ double test_floor(double x) { // DEFAULT-LABEL: @test_fmaf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract float @llvm.fma.f32(float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]]) +// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract noundef float @llvm.fma.f32(float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]]) // DEFAULT-NEXT: ret float [[TMP0]] // // FINITEONLY-LABEL: @test_fmaf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract float @llvm.fma.f32(float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]]) +// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract noundef float @llvm.fma.f32(float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]]) // FINITEONLY-NEXT: ret float [[TMP0]] // // APPROX-LABEL: @test_fmaf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[TMP0:%.*]] = tail call contract float @llvm.fma.f32(float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]]) +// APPROX-NEXT: [[TMP0:%.*]] = tail call contract noundef float @llvm.fma.f32(float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]]) // APPROX-NEXT: ret float [[TMP0]] // extern "C" __device__ float test_fmaf(float x, float y, float z) { @@ -1209,17 +1209,17 @@ extern "C" __device__ float test_fmaf(float x, float y, float z) { // DEFAULT-LABEL: @test_fma( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract double @llvm.fma.f64(double [[X:%.*]], double [[Y:%.*]], double [[Z:%.*]]) +// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract noundef double @llvm.fma.f64(double [[X:%.*]], double [[Y:%.*]], double [[Z:%.*]]) // DEFAULT-NEXT: ret double [[TMP0]] // // FINITEONLY-LABEL: @test_fma( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract double @llvm.fma.f64(double [[X:%.*]], double [[Y:%.*]], double [[Z:%.*]]) +// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract noundef double @llvm.fma.f64(double [[X:%.*]], double [[Y:%.*]], double [[Z:%.*]]) // FINITEONLY-NEXT: ret double [[TMP0]] // // APPROX-LABEL: @test_fma( // APPROX-NEXT: entry: -// APPROX-NEXT: [[TMP0:%.*]] = tail call contract double @llvm.fma.f64(double [[X:%.*]], double [[Y:%.*]], double [[Z:%.*]]) +// APPROX-NEXT: [[TMP0:%.*]] = tail call contract noundef double @llvm.fma.f64(double [[X:%.*]], double [[Y:%.*]], double [[Z:%.*]]) // APPROX-NEXT: ret double [[TMP0]] // extern "C" __device__ double test_fma(double x, double y, double z) { @@ -1228,17 +1228,17 @@ extern "C" __device__ double test_fma(double x, double y, double z) { // DEFAULT-LABEL: @test_fma_rn( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract double @llvm.fma.f64(double [[X:%.*]], double [[Y:%.*]], double [[Z:%.*]]) +// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract noundef double @llvm.fma.f64(double [[X:%.*]], double [[Y:%.*]], double [[Z:%.*]]) // DEFAULT-NEXT: ret double [[TMP0]] // // FINITEONLY-LABEL: @test_fma_rn( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract double @llvm.fma.f64(double [[X:%.*]], double [[Y:%.*]], double [[Z:%.*]]) +// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract noundef double @llvm.fma.f64(double [[X:%.*]], double [[Y:%.*]], double [[Z:%.*]]) // FINITEONLY-NEXT: ret double [[TMP0]] // // APPROX-LABEL: @test_fma_rn( // APPROX-NEXT: entry: -// APPROX-NEXT: [[TMP0:%.*]] = tail call contract double @llvm.fma.f64(double [[X:%.*]], double [[Y:%.*]], double [[Z:%.*]]) +// APPROX-NEXT: [[TMP0:%.*]] = tail call contract noundef double @llvm.fma.f64(double [[X:%.*]], double [[Y:%.*]], double [[Z:%.*]]) // APPROX-NEXT: ret double [[TMP0]] // extern "C" __device__ double test_fma_rn(double x, double y, double z) { @@ -1247,17 +1247,17 @@ extern "C" __device__ double test_fma_rn(double x, double y, double z) { // DEFAULT-LABEL: @test_fmaxf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]]) +// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract noundef float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]]) // DEFAULT-NEXT: ret float [[TMP0]] // // FINITEONLY-LABEL: @test_fmaxf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]]) +// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract noundef float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]]) // FINITEONLY-NEXT: ret float [[TMP0]] // // APPROX-LABEL: @test_fmaxf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[TMP0:%.*]] = tail call contract float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]]) +// APPROX-NEXT: [[TMP0:%.*]] = tail call contract noundef float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]]) // APPROX-NEXT: ret float [[TMP0]] // extern "C" __device__ float test_fmaxf(float x, float y) { @@ -1266,17 +1266,17 @@ extern "C" __device__ float test_fmaxf(float x, float y) { // DEFAULT-LABEL: @test_fmax( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract double @llvm.maxnum.f64(double [[X:%.*]], double [[Y:%.*]]) +// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract noundef double @llvm.maxnum.f64(double [[X:%.*]], double [[Y:%.*]]) // DEFAULT-NEXT: ret double [[TMP0]] // // FINITEONLY-LABEL: @test_fmax( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract double @llvm.maxnum.f64(double [[X:%.*]], double [[Y:%.*]]) +// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract noundef double @llvm.maxnum.f64(double [[X:%.*]], double [[Y:%.*]]) // FINITEONLY-NEXT: ret double [[TMP0]] // // APPROX-LABEL: @test_fmax( // APPROX-NEXT: entry: -// APPROX-NEXT: [[TMP0:%.*]] = tail call contract double @llvm.maxnum.f64(double [[X:%.*]], double [[Y:%.*]]) +// APPROX-NEXT: [[TMP0:%.*]] = tail call contract noundef double @llvm.maxnum.f64(double [[X:%.*]], double [[Y:%.*]]) // APPROX-NEXT: ret double [[TMP0]] // extern "C" __device__ double test_fmax(double x, double y) { @@ -1285,17 +1285,17 @@ extern "C" __device__ double test_fmax(double x, double y) { // DEFAULT-LABEL: @test_fminf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]]) +// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract noundef float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]]) // DEFAULT-NEXT: ret float [[TMP0]] // // FINITEONLY-LABEL: @test_fminf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]]) +// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract noundef float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]]) // FINITEONLY-NEXT: ret float [[TMP0]] // // APPROX-LABEL: @test_fminf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[TMP0:%.*]] = tail call contract float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]]) +// APPROX-NEXT: [[TMP0:%.*]] = tail call contract noundef float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]]) // APPROX-NEXT: ret float [[TMP0]] // extern "C" __device__ float test_fminf(float x, float y) { @@ -1304,17 +1304,17 @@ extern "C" __device__ float test_fminf(float x, float y) { // DEFAULT-LABEL: @test_fmin( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract double @llvm.minnum.f64(double [[X:%.*]], double [[Y:%.*]]) +// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract noundef double @llvm.minnum.f64(double [[X:%.*]], double [[Y:%.*]]) // DEFAULT-NEXT: ret double [[TMP0]] // // FINITEONLY-LABEL: @test_fmin( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract double @llvm.minnum.f64(double [[X:%.*]], double [[Y:%.*]]) +// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract noundef double @llvm.minnum.f64(double [[X:%.*]], double [[Y:%.*]]) // FINITEONLY-NEXT: ret double [[TMP0]] // // APPROX-LABEL: @test_fmin( // APPROX-NEXT: entry: -// APPROX-NEXT: [[TMP0:%.*]] = tail call contract double @llvm.minnum.f64(double [[X:%.*]], double [[Y:%.*]]) +// APPROX-NEXT: [[TMP0:%.*]] = tail call contract noundef double @llvm.minnum.f64(double [[X:%.*]], double [[Y:%.*]]) // APPROX-NEXT: ret double [[TMP0]] // extern "C" __device__ double test_fmin(double x, double y) { @@ -1323,17 +1323,17 @@ extern "C" __device__ double test_fmin(double x, double y) { // DEFAULT-LABEL: @test_fmodf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_fmod_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_fmod_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR14]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_fmodf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) float @__ocml_fmod_f32(float noundef nofpclass(nan inf) [[X:%.*]], float noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_fmod_f32(float noundef nofpclass(nan inf) [[X:%.*]], float noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR14]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_fmodf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_fmod_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_fmod_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR14]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_fmodf(float x, float y) { @@ -1342,17 +1342,17 @@ extern "C" __device__ float test_fmodf(float x, float y) { // DEFAULT-LABEL: @test_fmod( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_fmod_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_fmod_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR14]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_fmod( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) double @__ocml_fmod_f64(double noundef nofpclass(nan inf) [[X:%.*]], double noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_fmod_f64(double noundef nofpclass(nan inf) [[X:%.*]], double noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR14]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_fmod( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_fmod_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_fmod_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR14]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_fmod(double x, double y) { @@ -1385,17 +1385,17 @@ extern "C" __device__ double test_frexp(double x, int* y) { // DEFAULT-LABEL: @test_hypotf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_hypot_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_hypot_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR14]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_hypotf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) float @__ocml_hypot_f32(float noundef nofpclass(nan inf) [[X:%.*]], float noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_hypot_f32(float noundef nofpclass(nan inf) [[X:%.*]], float noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR14]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_hypotf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_hypot_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_hypot_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR14]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_hypotf(float x, float y) { @@ -1404,17 +1404,17 @@ extern "C" __device__ float test_hypotf(float x, float y) { // DEFAULT-LABEL: @test_hypot( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_hypot_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_hypot_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR14]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_hypot( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) double @__ocml_hypot_f64(double noundef nofpclass(nan inf) [[X:%.*]], double noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_hypot_f64(double noundef nofpclass(nan inf) [[X:%.*]], double noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR14]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_hypot( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_hypot_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_hypot_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR14]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_hypot(double x, double y) { @@ -1423,17 +1423,17 @@ extern "C" __device__ double test_hypot(double x, double y) { // DEFAULT-LABEL: @test_ilogbf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call i32 @__ocml_ilogb_f32(float noundef [[X:%.*]]) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call noundef i32 @__ocml_ilogb_f32(float noundef [[X:%.*]]) #[[ATTR14]] // DEFAULT-NEXT: ret i32 [[CALL_I]] // // FINITEONLY-LABEL: @test_ilogbf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call i32 @__ocml_ilogb_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call noundef i32 @__ocml_ilogb_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR14]] // FINITEONLY-NEXT: ret i32 [[CALL_I]] // // APPROX-LABEL: @test_ilogbf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call i32 @__ocml_ilogb_f32(float noundef [[X:%.*]]) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call noundef i32 @__ocml_ilogb_f32(float noundef [[X:%.*]]) #[[ATTR14]] // APPROX-NEXT: ret i32 [[CALL_I]] // extern "C" __device__ int test_ilogbf(float x) { @@ -1442,17 +1442,17 @@ extern "C" __device__ int test_ilogbf(float x) { // DEFAULT-LABEL: @test_ilogb( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call i32 @__ocml_ilogb_f64(double noundef [[X:%.*]]) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call noundef i32 @__ocml_ilogb_f64(double noundef [[X:%.*]]) #[[ATTR14]] // DEFAULT-NEXT: ret i32 [[CALL_I]] // // FINITEONLY-LABEL: @test_ilogb( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call i32 @__ocml_ilogb_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call noundef i32 @__ocml_ilogb_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR14]] // FINITEONLY-NEXT: ret i32 [[CALL_I]] // // APPROX-LABEL: @test_ilogb( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call i32 @__ocml_ilogb_f64(double noundef [[X:%.*]]) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call noundef i32 @__ocml_ilogb_f64(double noundef [[X:%.*]]) #[[ATTR14]] // APPROX-NEXT: ret i32 [[CALL_I]] // extern "C" __device__ int test_ilogb(double x) { @@ -1589,17 +1589,17 @@ extern "C" __device__ BOOL_TYPE test___isnan(double x) { // DEFAULT-LABEL: @test_j0f( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_j0_f32(float noundef [[X:%.*]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_j0_f32(float noundef [[X:%.*]]) #[[ATTR16]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_j0f( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) float @__ocml_j0_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_j0_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_j0f( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_j0_f32(float noundef [[X:%.*]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_j0_f32(float noundef [[X:%.*]]) #[[ATTR16]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_j0f(float x) { @@ -1608,17 +1608,17 @@ extern "C" __device__ float test_j0f(float x) { // DEFAULT-LABEL: @test_j0( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_j0_f64(double noundef [[X:%.*]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_j0_f64(double noundef [[X:%.*]]) #[[ATTR16]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_j0( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) double @__ocml_j0_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_j0_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_j0( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_j0_f64(double noundef [[X:%.*]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_j0_f64(double noundef [[X:%.*]]) #[[ATTR16]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_j0(double x) { @@ -1627,17 +1627,17 @@ extern "C" __device__ double test_j0(double x) { // DEFAULT-LABEL: @test_j1f( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_j1_f32(float noundef [[X:%.*]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_j1_f32(float noundef [[X:%.*]]) #[[ATTR16]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_j1f( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) float @__ocml_j1_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_j1_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_j1f( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_j1_f32(float noundef [[X:%.*]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_j1_f32(float noundef [[X:%.*]]) #[[ATTR16]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_j1f(float x) { @@ -1646,17 +1646,17 @@ extern "C" __device__ float test_j1f(float x) { // DEFAULT-LABEL: @test_j1( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_j1_f64(double noundef [[X:%.*]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_j1_f64(double noundef [[X:%.*]]) #[[ATTR16]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_j1( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) double @__ocml_j1_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_j1_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_j1( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_j1_f64(double noundef [[X:%.*]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_j1_f64(double noundef [[X:%.*]]) #[[ATTR16]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_j1(double x) { @@ -1670,14 +1670,14 @@ extern "C" __device__ double test_j1(double x) { // DEFAULT-NEXT: i32 1, label [[IF_THEN2_I:%.*]] // DEFAULT-NEXT: ] // DEFAULT: if.then.i: -// DEFAULT-NEXT: [[CALL_I_I:%.*]] = tail call contract float @__ocml_j0_f32(float noundef [[Y:%.*]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I_I:%.*]] = tail call contract noundef float @__ocml_j0_f32(float noundef [[Y:%.*]]) #[[ATTR16]] // DEFAULT-NEXT: br label [[_ZL3JNFIF_EXIT:%.*]] // DEFAULT: if.then2.i: -// DEFAULT-NEXT: [[CALL_I20_I:%.*]] = tail call contract float @__ocml_j1_f32(float noundef [[Y]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I20_I:%.*]] = tail call contract noundef float @__ocml_j1_f32(float noundef [[Y]]) #[[ATTR16]] // DEFAULT-NEXT: br label [[_ZL3JNFIF_EXIT]] // DEFAULT: if.end4.i: -// DEFAULT-NEXT: [[CALL_I21_I:%.*]] = tail call contract float @__ocml_j0_f32(float noundef [[Y]]) #[[ATTR16]] -// DEFAULT-NEXT: [[CALL_I22_I:%.*]] = tail call contract float @__ocml_j1_f32(float noundef [[Y]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I21_I:%.*]] = tail call contract noundef float @__ocml_j0_f32(float noundef [[Y]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I22_I:%.*]] = tail call contract noundef float @__ocml_j1_f32(float noundef [[Y]]) #[[ATTR16]] // DEFAULT-NEXT: [[CMP723_I:%.*]] = icmp sgt i32 [[X]], 1 // DEFAULT-NEXT: br i1 [[CMP723_I]], label [[FOR_BODY_I:%.*]], label [[_ZL3JNFIF_EXIT]] // DEFAULT: for.body.i: @@ -1703,14 +1703,14 @@ extern "C" __device__ double test_j1(double x) { // FINITEONLY-NEXT: i32 1, label [[IF_THEN2_I:%.*]] // FINITEONLY-NEXT: ] // FINITEONLY: if.then.i: -// FINITEONLY-NEXT: [[CALL_I_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) float @__ocml_j0_f32(float noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_j0_f32(float noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR16]] // FINITEONLY-NEXT: br label [[_ZL3JNFIF_EXIT:%.*]] // FINITEONLY: if.then2.i: -// FINITEONLY-NEXT: [[CALL_I20_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) float @__ocml_j1_f32(float noundef nofpclass(nan inf) [[Y]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I20_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_j1_f32(float noundef nofpclass(nan inf) [[Y]]) #[[ATTR16]] // FINITEONLY-NEXT: br label [[_ZL3JNFIF_EXIT]] // FINITEONLY: if.end4.i: -// FINITEONLY-NEXT: [[CALL_I21_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) float @__ocml_j0_f32(float noundef nofpclass(nan inf) [[Y]]) #[[ATTR16]] -// FINITEONLY-NEXT: [[CALL_I22_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) float @__ocml_j1_f32(float noundef nofpclass(nan inf) [[Y]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I21_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_j0_f32(float noundef nofpclass(nan inf) [[Y]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I22_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_j1_f32(float noundef nofpclass(nan inf) [[Y]]) #[[ATTR16]] // FINITEONLY-NEXT: [[CMP723_I:%.*]] = icmp sgt i32 [[X]], 1 // FINITEONLY-NEXT: br i1 [[CMP723_I]], label [[FOR_BODY_I:%.*]], label [[_ZL3JNFIF_EXIT]] // FINITEONLY: for.body.i: @@ -1736,14 +1736,14 @@ extern "C" __device__ double test_j1(double x) { // APPROX-NEXT: i32 1, label [[IF_THEN2_I:%.*]] // APPROX-NEXT: ] // APPROX: if.then.i: -// APPROX-NEXT: [[CALL_I_I:%.*]] = tail call contract float @__ocml_j0_f32(float noundef [[Y:%.*]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I_I:%.*]] = tail call contract noundef float @__ocml_j0_f32(float noundef [[Y:%.*]]) #[[ATTR16]] // APPROX-NEXT: br label [[_ZL3JNFIF_EXIT:%.*]] // APPROX: if.then2.i: -// APPROX-NEXT: [[CALL_I20_I:%.*]] = tail call contract float @__ocml_j1_f32(float noundef [[Y]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I20_I:%.*]] = tail call contract noundef float @__ocml_j1_f32(float noundef [[Y]]) #[[ATTR16]] // APPROX-NEXT: br label [[_ZL3JNFIF_EXIT]] // APPROX: if.end4.i: -// APPROX-NEXT: [[CALL_I21_I:%.*]] = tail call contract float @__ocml_j0_f32(float noundef [[Y]]) #[[ATTR16]] -// APPROX-NEXT: [[CALL_I22_I:%.*]] = tail call contract float @__ocml_j1_f32(float noundef [[Y]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I21_I:%.*]] = tail call contract noundef float @__ocml_j0_f32(float noundef [[Y]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I22_I:%.*]] = tail call contract noundef float @__ocml_j1_f32(float noundef [[Y]]) #[[ATTR16]] // APPROX-NEXT: [[CMP723_I:%.*]] = icmp sgt i32 [[X]], 1 // APPROX-NEXT: br i1 [[CMP723_I]], label [[FOR_BODY_I:%.*]], label [[_ZL3JNFIF_EXIT]] // APPROX: for.body.i: @@ -1773,14 +1773,14 @@ extern "C" __device__ float test_jnf(int x, float y) { // DEFAULT-NEXT: i32 1, label [[IF_THEN2_I:%.*]] // DEFAULT-NEXT: ] // DEFAULT: if.then.i: -// DEFAULT-NEXT: [[CALL_I_I:%.*]] = tail call contract double @__ocml_j0_f64(double noundef [[Y:%.*]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I_I:%.*]] = tail call contract noundef double @__ocml_j0_f64(double noundef [[Y:%.*]]) #[[ATTR16]] // DEFAULT-NEXT: br label [[_ZL2JNID_EXIT:%.*]] // DEFAULT: if.then2.i: -// DEFAULT-NEXT: [[CALL_I20_I:%.*]] = tail call contract double @__ocml_j1_f64(double noundef [[Y]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I20_I:%.*]] = tail call contract noundef double @__ocml_j1_f64(double noundef [[Y]]) #[[ATTR16]] // DEFAULT-NEXT: br label [[_ZL2JNID_EXIT]] // DEFAULT: if.end4.i: -// DEFAULT-NEXT: [[CALL_I21_I:%.*]] = tail call contract double @__ocml_j0_f64(double noundef [[Y]]) #[[ATTR16]] -// DEFAULT-NEXT: [[CALL_I22_I:%.*]] = tail call contract double @__ocml_j1_f64(double noundef [[Y]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I21_I:%.*]] = tail call contract noundef double @__ocml_j0_f64(double noundef [[Y]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I22_I:%.*]] = tail call contract noundef double @__ocml_j1_f64(double noundef [[Y]]) #[[ATTR16]] // DEFAULT-NEXT: [[CMP723_I:%.*]] = icmp sgt i32 [[X]], 1 // DEFAULT-NEXT: br i1 [[CMP723_I]], label [[FOR_BODY_I:%.*]], label [[_ZL2JNID_EXIT]] // DEFAULT: for.body.i: @@ -1806,14 +1806,14 @@ extern "C" __device__ float test_jnf(int x, float y) { // FINITEONLY-NEXT: i32 1, label [[IF_THEN2_I:%.*]] // FINITEONLY-NEXT: ] // FINITEONLY: if.then.i: -// FINITEONLY-NEXT: [[CALL_I_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) double @__ocml_j0_f64(double noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_j0_f64(double noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR16]] // FINITEONLY-NEXT: br label [[_ZL2JNID_EXIT:%.*]] // FINITEONLY: if.then2.i: -// FINITEONLY-NEXT: [[CALL_I20_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) double @__ocml_j1_f64(double noundef nofpclass(nan inf) [[Y]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I20_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_j1_f64(double noundef nofpclass(nan inf) [[Y]]) #[[ATTR16]] // FINITEONLY-NEXT: br label [[_ZL2JNID_EXIT]] // FINITEONLY: if.end4.i: -// FINITEONLY-NEXT: [[CALL_I21_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) double @__ocml_j0_f64(double noundef nofpclass(nan inf) [[Y]]) #[[ATTR16]] -// FINITEONLY-NEXT: [[CALL_I22_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) double @__ocml_j1_f64(double noundef nofpclass(nan inf) [[Y]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I21_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_j0_f64(double noundef nofpclass(nan inf) [[Y]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I22_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_j1_f64(double noundef nofpclass(nan inf) [[Y]]) #[[ATTR16]] // FINITEONLY-NEXT: [[CMP723_I:%.*]] = icmp sgt i32 [[X]], 1 // FINITEONLY-NEXT: br i1 [[CMP723_I]], label [[FOR_BODY_I:%.*]], label [[_ZL2JNID_EXIT]] // FINITEONLY: for.body.i: @@ -1839,14 +1839,14 @@ extern "C" __device__ float test_jnf(int x, float y) { // APPROX-NEXT: i32 1, label [[IF_THEN2_I:%.*]] // APPROX-NEXT: ] // APPROX: if.then.i: -// APPROX-NEXT: [[CALL_I_I:%.*]] = tail call contract double @__ocml_j0_f64(double noundef [[Y:%.*]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I_I:%.*]] = tail call contract noundef double @__ocml_j0_f64(double noundef [[Y:%.*]]) #[[ATTR16]] // APPROX-NEXT: br label [[_ZL2JNID_EXIT:%.*]] // APPROX: if.then2.i: -// APPROX-NEXT: [[CALL_I20_I:%.*]] = tail call contract double @__ocml_j1_f64(double noundef [[Y]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I20_I:%.*]] = tail call contract noundef double @__ocml_j1_f64(double noundef [[Y]]) #[[ATTR16]] // APPROX-NEXT: br label [[_ZL2JNID_EXIT]] // APPROX: if.end4.i: -// APPROX-NEXT: [[CALL_I21_I:%.*]] = tail call contract double @__ocml_j0_f64(double noundef [[Y]]) #[[ATTR16]] -// APPROX-NEXT: [[CALL_I22_I:%.*]] = tail call contract double @__ocml_j1_f64(double noundef [[Y]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I21_I:%.*]] = tail call contract noundef double @__ocml_j0_f64(double noundef [[Y]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I22_I:%.*]] = tail call contract noundef double @__ocml_j1_f64(double noundef [[Y]]) #[[ATTR16]] // APPROX-NEXT: [[CMP723_I:%.*]] = icmp sgt i32 [[X]], 1 // APPROX-NEXT: br i1 [[CMP723_I]], label [[FOR_BODY_I:%.*]], label [[_ZL2JNID_EXIT]] // APPROX: for.body.i: @@ -1871,17 +1871,17 @@ extern "C" __device__ double test_jn(int x, double y) { // DEFAULT-LABEL: @test_ldexpf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract float @llvm.ldexp.f32.i32(float [[X:%.*]], i32 [[Y:%.*]]) +// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract noundef float @llvm.ldexp.f32.i32(float [[X:%.*]], i32 [[Y:%.*]]) // DEFAULT-NEXT: ret float [[TMP0]] // // FINITEONLY-LABEL: @test_ldexpf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract float @llvm.ldexp.f32.i32(float [[X:%.*]], i32 [[Y:%.*]]) +// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract noundef float @llvm.ldexp.f32.i32(float [[X:%.*]], i32 [[Y:%.*]]) // FINITEONLY-NEXT: ret float [[TMP0]] // // APPROX-LABEL: @test_ldexpf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[TMP0:%.*]] = tail call contract float @llvm.ldexp.f32.i32(float [[X:%.*]], i32 [[Y:%.*]]) +// APPROX-NEXT: [[TMP0:%.*]] = tail call contract noundef float @llvm.ldexp.f32.i32(float [[X:%.*]], i32 [[Y:%.*]]) // APPROX-NEXT: ret float [[TMP0]] // extern "C" __device__ float test_ldexpf(float x, int y) { @@ -1890,17 +1890,17 @@ extern "C" __device__ float test_ldexpf(float x, int y) { // DEFAULT-LABEL: @test_ldexp( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract double @llvm.ldexp.f64.i32(double [[X:%.*]], i32 [[Y:%.*]]) +// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract noundef double @llvm.ldexp.f64.i32(double [[X:%.*]], i32 [[Y:%.*]]) // DEFAULT-NEXT: ret double [[TMP0]] // // FINITEONLY-LABEL: @test_ldexp( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract double @llvm.ldexp.f64.i32(double [[X:%.*]], i32 [[Y:%.*]]) +// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract noundef double @llvm.ldexp.f64.i32(double [[X:%.*]], i32 [[Y:%.*]]) // FINITEONLY-NEXT: ret double [[TMP0]] // // APPROX-LABEL: @test_ldexp( // APPROX-NEXT: entry: -// APPROX-NEXT: [[TMP0:%.*]] = tail call contract double @llvm.ldexp.f64.i32(double [[X:%.*]], i32 [[Y:%.*]]) +// APPROX-NEXT: [[TMP0:%.*]] = tail call contract noundef double @llvm.ldexp.f64.i32(double [[X:%.*]], i32 [[Y:%.*]]) // APPROX-NEXT: ret double [[TMP0]] // extern "C" __device__ double test_ldexp(double x, int y) { @@ -1909,17 +1909,17 @@ extern "C" __device__ double test_ldexp(double x, int y) { // DEFAULT-LABEL: @test_lgammaf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_lgamma_f32(float noundef [[X:%.*]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_lgamma_f32(float noundef [[X:%.*]]) #[[ATTR16]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_lgammaf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) float @__ocml_lgamma_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_lgamma_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_lgammaf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_lgamma_f32(float noundef [[X:%.*]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_lgamma_f32(float noundef [[X:%.*]]) #[[ATTR16]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_lgammaf(float x) { @@ -1928,17 +1928,17 @@ extern "C" __device__ float test_lgammaf(float x) { // DEFAULT-LABEL: @test_lgamma( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_lgamma_f64(double noundef [[X:%.*]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_lgamma_f64(double noundef [[X:%.*]]) #[[ATTR16]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_lgamma( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) double @__ocml_lgamma_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_lgamma_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_lgamma( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_lgamma_f64(double noundef [[X:%.*]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_lgamma_f64(double noundef [[X:%.*]]) #[[ATTR16]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_lgamma(double x) { @@ -2035,17 +2035,17 @@ extern "C" __device__ long long int test_llround(double x) { // DEFAULT-LABEL: @test_log10f( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract float @llvm.log10.f32(float [[X:%.*]]) +// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract noundef float @llvm.log10.f32(float [[X:%.*]]) // DEFAULT-NEXT: ret float [[TMP0]] // // FINITEONLY-LABEL: @test_log10f( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract float @llvm.log10.f32(float [[X:%.*]]) +// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract noundef float @llvm.log10.f32(float [[X:%.*]]) // FINITEONLY-NEXT: ret float [[TMP0]] // // APPROX-LABEL: @test_log10f( // APPROX-NEXT: entry: -// APPROX-NEXT: [[TMP0:%.*]] = tail call contract float @llvm.log10.f32(float [[X:%.*]]) +// APPROX-NEXT: [[TMP0:%.*]] = tail call contract noundef float @llvm.log10.f32(float [[X:%.*]]) // APPROX-NEXT: ret float [[TMP0]] // extern "C" __device__ float test_log10f(float x) { @@ -2054,17 +2054,17 @@ extern "C" __device__ float test_log10f(float x) { // DEFAULT-LABEL: @test_log10( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_log10_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_log10_f64(double noundef [[X:%.*]]) #[[ATTR15]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_log10( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) double @__ocml_log10_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_log10_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_log10( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_log10_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_log10_f64(double noundef [[X:%.*]]) #[[ATTR15]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_log10(double x) { @@ -2073,17 +2073,17 @@ extern "C" __device__ double test_log10(double x) { // DEFAULT-LABEL: @test_log1pf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_log1p_f32(float noundef [[X:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_log1p_f32(float noundef [[X:%.*]]) #[[ATTR15]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_log1pf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) float @__ocml_log1p_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_log1p_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_log1pf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_log1p_f32(float noundef [[X:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_log1p_f32(float noundef [[X:%.*]]) #[[ATTR15]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_log1pf(float x) { @@ -2092,17 +2092,17 @@ extern "C" __device__ float test_log1pf(float x) { // DEFAULT-LABEL: @test_log1p( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_log1p_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_log1p_f64(double noundef [[X:%.*]]) #[[ATTR15]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_log1p( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) double @__ocml_log1p_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_log1p_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_log1p( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_log1p_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_log1p_f64(double noundef [[X:%.*]]) #[[ATTR15]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_log1p(double x) { @@ -2111,17 +2111,17 @@ extern "C" __device__ double test_log1p(double x) { // DEFAULT-LABEL: @test_log2f( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_log2_f32(float noundef [[X:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_log2_f32(float noundef [[X:%.*]]) #[[ATTR15]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_log2f( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) float @__ocml_log2_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_log2_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_log2f( // APPROX-NEXT: entry: -// APPROX-NEXT: [[TMP0:%.*]] = tail call contract float @llvm.amdgcn.log.f32(float [[X:%.*]]) +// APPROX-NEXT: [[TMP0:%.*]] = tail call contract noundef float @llvm.amdgcn.log.f32(float [[X:%.*]]) // APPROX-NEXT: ret float [[TMP0]] // extern "C" __device__ float test_log2f(float x) { @@ -2130,17 +2130,17 @@ extern "C" __device__ float test_log2f(float x) { // DEFAULT-LABEL: @test_log2( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_log2_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_log2_f64(double noundef [[X:%.*]]) #[[ATTR15]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_log2( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) double @__ocml_log2_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_log2_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_log2( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_log2_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_log2_f64(double noundef [[X:%.*]]) #[[ATTR15]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_log2(double x) { @@ -2149,17 +2149,17 @@ extern "C" __device__ double test_log2(double x) { // DEFAULT-LABEL: @test_logbf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_logb_f32(float noundef [[X:%.*]]) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_logb_f32(float noundef [[X:%.*]]) #[[ATTR14]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_logbf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) float @__ocml_logb_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_logb_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR14]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_logbf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_logb_f32(float noundef [[X:%.*]]) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_logb_f32(float noundef [[X:%.*]]) #[[ATTR14]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_logbf(float x) { @@ -2168,17 +2168,17 @@ extern "C" __device__ float test_logbf(float x) { // DEFAULT-LABEL: @test_logb( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_logb_f64(double noundef [[X:%.*]]) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_logb_f64(double noundef [[X:%.*]]) #[[ATTR14]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_logb( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) double @__ocml_logb_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_logb_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR14]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_logb( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_logb_f64(double noundef [[X:%.*]]) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_logb_f64(double noundef [[X:%.*]]) #[[ATTR14]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_logb(double x) { @@ -2187,17 +2187,17 @@ extern "C" __device__ double test_logb(double x) { // DEFAULT-LABEL: @test_logf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_log_f32(float noundef [[X:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_log_f32(float noundef [[X:%.*]]) #[[ATTR15]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_logf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) float @__ocml_log_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_log_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_logf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[TMP0:%.*]] = tail call contract float @llvm.log.f32(float [[X:%.*]]) +// APPROX-NEXT: [[TMP0:%.*]] = tail call contract noundef float @llvm.log.f32(float [[X:%.*]]) // APPROX-NEXT: ret float [[TMP0]] // extern "C" __device__ float test_logf(float x) { @@ -2296,7 +2296,7 @@ extern "C" __device__ long int test_lround(double x) { // DEFAULT-NEXT: entry: // DEFAULT-NEXT: [[__TMP_I:%.*]] = alloca float, align 4, addrspace(5) // DEFAULT-NEXT: call void @llvm.lifetime.start.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17:[0-9]+]] -// DEFAULT-NEXT: [[CALL_I:%.*]] = call contract float @__ocml_modf_f32(float noundef [[X:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = call contract noundef float @__ocml_modf_f32(float noundef [[X:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR16]] // DEFAULT-NEXT: [[TMP0:%.*]] = load float, ptr addrspace(5) [[__TMP_I]], align 4, !tbaa [[TBAA16:![0-9]+]] // DEFAULT-NEXT: store float [[TMP0]], ptr [[Y:%.*]], align 4, !tbaa [[TBAA16]] // DEFAULT-NEXT: call void @llvm.lifetime.end.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17]] @@ -2306,7 +2306,7 @@ extern "C" __device__ long int test_lround(double x) { // FINITEONLY-NEXT: entry: // FINITEONLY-NEXT: [[__TMP_I:%.*]] = alloca float, align 4, addrspace(5) // FINITEONLY-NEXT: call void @llvm.lifetime.start.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17:[0-9]+]] -// FINITEONLY-NEXT: [[CALL_I:%.*]] = call nnan ninf contract nofpclass(nan inf) float @__ocml_modf_f32(float noundef nofpclass(nan inf) [[X:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_modf_f32(float noundef nofpclass(nan inf) [[X:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR16]] // FINITEONLY-NEXT: [[TMP0:%.*]] = load float, ptr addrspace(5) [[__TMP_I]], align 4, !tbaa [[TBAA16:![0-9]+]] // FINITEONLY-NEXT: store float [[TMP0]], ptr [[Y:%.*]], align 4, !tbaa [[TBAA16]] // FINITEONLY-NEXT: call void @llvm.lifetime.end.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17]] @@ -2316,7 +2316,7 @@ extern "C" __device__ long int test_lround(double x) { // APPROX-NEXT: entry: // APPROX-NEXT: [[__TMP_I:%.*]] = alloca float, align 4, addrspace(5) // APPROX-NEXT: call void @llvm.lifetime.start.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17:[0-9]+]] -// APPROX-NEXT: [[CALL_I:%.*]] = call contract float @__ocml_modf_f32(float noundef [[X:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I:%.*]] = call contract noundef float @__ocml_modf_f32(float noundef [[X:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR16]] // APPROX-NEXT: [[TMP0:%.*]] = load float, ptr addrspace(5) [[__TMP_I]], align 4, !tbaa [[TBAA16:![0-9]+]] // APPROX-NEXT: store float [[TMP0]], ptr [[Y:%.*]], align 4, !tbaa [[TBAA16]] // APPROX-NEXT: call void @llvm.lifetime.end.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17]] @@ -2330,7 +2330,7 @@ extern "C" __device__ float test_modff(float x, float* y) { // DEFAULT-NEXT: entry: // DEFAULT-NEXT: [[__TMP_I:%.*]] = alloca double, align 8, addrspace(5) // DEFAULT-NEXT: call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17]] -// DEFAULT-NEXT: [[CALL_I:%.*]] = call contract double @__ocml_modf_f64(double noundef [[X:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = call contract noundef double @__ocml_modf_f64(double noundef [[X:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR16]] // DEFAULT-NEXT: [[TMP0:%.*]] = load double, ptr addrspace(5) [[__TMP_I]], align 8, !tbaa [[TBAA18:![0-9]+]] // DEFAULT-NEXT: store double [[TMP0]], ptr [[Y:%.*]], align 8, !tbaa [[TBAA18]] // DEFAULT-NEXT: call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17]] @@ -2340,7 +2340,7 @@ extern "C" __device__ float test_modff(float x, float* y) { // FINITEONLY-NEXT: entry: // FINITEONLY-NEXT: [[__TMP_I:%.*]] = alloca double, align 8, addrspace(5) // FINITEONLY-NEXT: call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17]] -// FINITEONLY-NEXT: [[CALL_I:%.*]] = call nnan ninf contract nofpclass(nan inf) double @__ocml_modf_f64(double noundef nofpclass(nan inf) [[X:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_modf_f64(double noundef nofpclass(nan inf) [[X:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR16]] // FINITEONLY-NEXT: [[TMP0:%.*]] = load double, ptr addrspace(5) [[__TMP_I]], align 8, !tbaa [[TBAA18:![0-9]+]] // FINITEONLY-NEXT: store double [[TMP0]], ptr [[Y:%.*]], align 8, !tbaa [[TBAA18]] // FINITEONLY-NEXT: call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17]] @@ -2350,7 +2350,7 @@ extern "C" __device__ float test_modff(float x, float* y) { // APPROX-NEXT: entry: // APPROX-NEXT: [[__TMP_I:%.*]] = alloca double, align 8, addrspace(5) // APPROX-NEXT: call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17]] -// APPROX-NEXT: [[CALL_I:%.*]] = call contract double @__ocml_modf_f64(double noundef [[X:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I:%.*]] = call contract noundef double @__ocml_modf_f64(double noundef [[X:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR16]] // APPROX-NEXT: [[TMP0:%.*]] = load double, ptr addrspace(5) [[__TMP_I]], align 8, !tbaa [[TBAA18:![0-9]+]] // APPROX-NEXT: store double [[TMP0]], ptr [[Y:%.*]], align 8, !tbaa [[TBAA18]] // APPROX-NEXT: call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17]] @@ -2557,33 +2557,65 @@ extern "C" __device__ double test_nan(const char *tag) { return nan(tag); } -// CHECK-LABEL: @test_nanf_emptystr( -// CHECK-NEXT: entry: -// CHECK-NEXT: ret float 0x7FF8000000000000 +// DEFAULT-LABEL: @test_nanf_emptystr( +// DEFAULT-NEXT: entry: +// DEFAULT-NEXT: ret float 0x7FF8000000000000 +// +// FINITEONLY-LABEL: @test_nanf_emptystr( +// FINITEONLY-NEXT: entry: +// FINITEONLY-NEXT: ret float poison +// +// APPROX-LABEL: @test_nanf_emptystr( +// APPROX-NEXT: entry: +// APPROX-NEXT: ret float 0x7FF8000000000000 // extern "C" __device__ float test_nanf_emptystr() { return nanf(""); } -// CHECK-LABEL: @test_nan_emptystr( -// CHECK-NEXT: entry: -// CHECK-NEXT: ret double 0x7FF8000000000000 +// DEFAULT-LABEL: @test_nan_emptystr( +// DEFAULT-NEXT: entry: +// DEFAULT-NEXT: ret double 0x7FF8000000000000 +// +// FINITEONLY-LABEL: @test_nan_emptystr( +// FINITEONLY-NEXT: entry: +// FINITEONLY-NEXT: ret double poison +// +// APPROX-LABEL: @test_nan_emptystr( +// APPROX-NEXT: entry: +// APPROX-NEXT: ret double 0x7FF8000000000000 // extern "C" __device__ double test_nan_emptystr() { return nan(""); } -// CHECK-LABEL: @test_nanf_fill( -// CHECK-NEXT: entry: -// CHECK-NEXT: ret float 0x7FF8000000000000 +// DEFAULT-LABEL: @test_nanf_fill( +// DEFAULT-NEXT: entry: +// DEFAULT-NEXT: ret float 0x7FF8000000000000 +// +// FINITEONLY-LABEL: @test_nanf_fill( +// FINITEONLY-NEXT: entry: +// FINITEONLY-NEXT: ret float poison +// +// APPROX-LABEL: @test_nanf_fill( +// APPROX-NEXT: entry: +// APPROX-NEXT: ret float 0x7FF8000000000000 // extern "C" __device__ float test_nanf_fill() { return nanf("0x456"); } -// CHECK-LABEL: @test_nan_fill( -// CHECK-NEXT: entry: -// CHECK-NEXT: ret double 0x7FF8000000000000 +// DEFAULT-LABEL: @test_nan_fill( +// DEFAULT-NEXT: entry: +// DEFAULT-NEXT: ret double 0x7FF8000000000000 +// +// FINITEONLY-LABEL: @test_nan_fill( +// FINITEONLY-NEXT: entry: +// FINITEONLY-NEXT: ret double poison +// +// APPROX-LABEL: @test_nan_fill( +// APPROX-NEXT: entry: +// APPROX-NEXT: ret double 0x7FF8000000000000 // extern "C" __device__ double test_nan_fill() { return nan("0x123"); @@ -2591,17 +2623,17 @@ extern "C" __device__ double test_nan_fill() { // DEFAULT-LABEL: @test_nearbyintf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract float @llvm.nearbyint.f32(float [[X:%.*]]) +// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract noundef float @llvm.nearbyint.f32(float [[X:%.*]]) // DEFAULT-NEXT: ret float [[TMP0]] // // FINITEONLY-LABEL: @test_nearbyintf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract float @llvm.nearbyint.f32(float [[X:%.*]]) +// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract noundef float @llvm.nearbyint.f32(float [[X:%.*]]) // FINITEONLY-NEXT: ret float [[TMP0]] // // APPROX-LABEL: @test_nearbyintf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[TMP0:%.*]] = tail call contract float @llvm.nearbyint.f32(float [[X:%.*]]) +// APPROX-NEXT: [[TMP0:%.*]] = tail call contract noundef float @llvm.nearbyint.f32(float [[X:%.*]]) // APPROX-NEXT: ret float [[TMP0]] // extern "C" __device__ float test_nearbyintf(float x) { @@ -2610,17 +2642,17 @@ extern "C" __device__ float test_nearbyintf(float x) { // DEFAULT-LABEL: @test_nearbyint( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract double @llvm.nearbyint.f64(double [[X:%.*]]) +// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract noundef double @llvm.nearbyint.f64(double [[X:%.*]]) // DEFAULT-NEXT: ret double [[TMP0]] // // FINITEONLY-LABEL: @test_nearbyint( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract double @llvm.nearbyint.f64(double [[X:%.*]]) +// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract noundef double @llvm.nearbyint.f64(double [[X:%.*]]) // FINITEONLY-NEXT: ret double [[TMP0]] // // APPROX-LABEL: @test_nearbyint( // APPROX-NEXT: entry: -// APPROX-NEXT: [[TMP0:%.*]] = tail call contract double @llvm.nearbyint.f64(double [[X:%.*]]) +// APPROX-NEXT: [[TMP0:%.*]] = tail call contract noundef double @llvm.nearbyint.f64(double [[X:%.*]]) // APPROX-NEXT: ret double [[TMP0]] // extern "C" __device__ double test_nearbyint(double x) { @@ -2629,17 +2661,17 @@ extern "C" __device__ double test_nearbyint(double x) { // DEFAULT-LABEL: @test_nextafterf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_nextafter_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_nextafter_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR14]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_nextafterf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) float @__ocml_nextafter_f32(float noundef nofpclass(nan inf) [[X:%.*]], float noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_nextafter_f32(float noundef nofpclass(nan inf) [[X:%.*]], float noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR14]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_nextafterf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_nextafter_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_nextafter_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR14]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_nextafterf(float x, float y) { @@ -2648,17 +2680,17 @@ extern "C" __device__ float test_nextafterf(float x, float y) { // DEFAULT-LABEL: @test_nextafter( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_nextafter_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_nextafter_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR14]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_nextafter( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) double @__ocml_nextafter_f64(double noundef nofpclass(nan inf) [[X:%.*]], double noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_nextafter_f64(double noundef nofpclass(nan inf) [[X:%.*]], double noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR14]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_nextafter( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_nextafter_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_nextafter_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR14]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_nextafter(double x, double y) { @@ -2667,17 +2699,17 @@ extern "C" __device__ double test_nextafter(double x, double y) { // DEFAULT-LABEL: @test_norm3df( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_len3_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]], float noundef [[Z:%.*]]) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_len3_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]], float noundef [[Z:%.*]]) #[[ATTR14]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_norm3df( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) float @__ocml_len3_f32(float noundef nofpclass(nan inf) [[X:%.*]], float noundef nofpclass(nan inf) [[Y:%.*]], float noundef nofpclass(nan inf) [[Z:%.*]]) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_len3_f32(float noundef nofpclass(nan inf) [[X:%.*]], float noundef nofpclass(nan inf) [[Y:%.*]], float noundef nofpclass(nan inf) [[Z:%.*]]) #[[ATTR14]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_norm3df( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_len3_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]], float noundef [[Z:%.*]]) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_len3_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]], float noundef [[Z:%.*]]) #[[ATTR14]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_norm3df(float x, float y, float z) { @@ -2686,17 +2718,17 @@ extern "C" __device__ float test_norm3df(float x, float y, float z) { // DEFAULT-LABEL: @test_norm3d( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_len3_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]], double noundef [[Z:%.*]]) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_len3_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]], double noundef [[Z:%.*]]) #[[ATTR14]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_norm3d( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) double @__ocml_len3_f64(double noundef nofpclass(nan inf) [[X:%.*]], double noundef nofpclass(nan inf) [[Y:%.*]], double noundef nofpclass(nan inf) [[Z:%.*]]) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_len3_f64(double noundef nofpclass(nan inf) [[X:%.*]], double noundef nofpclass(nan inf) [[Y:%.*]], double noundef nofpclass(nan inf) [[Z:%.*]]) #[[ATTR14]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_norm3d( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_len3_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]], double noundef [[Z:%.*]]) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_len3_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]], double noundef [[Z:%.*]]) #[[ATTR14]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_norm3d(double x, double y, double z) { @@ -2705,17 +2737,17 @@ extern "C" __device__ double test_norm3d(double x, double y, double z) { // DEFAULT-LABEL: @test_norm4df( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_len4_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]], float noundef [[Z:%.*]], float noundef [[W:%.*]]) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_len4_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]], float noundef [[Z:%.*]], float noundef [[W:%.*]]) #[[ATTR14]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_norm4df( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) float @__ocml_len4_f32(float noundef nofpclass(nan inf) [[X:%.*]], float noundef nofpclass(nan inf) [[Y:%.*]], float noundef nofpclass(nan inf) [[Z:%.*]], float noundef nofpclass(nan inf) [[W:%.*]]) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_len4_f32(float noundef nofpclass(nan inf) [[X:%.*]], float noundef nofpclass(nan inf) [[Y:%.*]], float noundef nofpclass(nan inf) [[Z:%.*]], float noundef nofpclass(nan inf) [[W:%.*]]) #[[ATTR14]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_norm4df( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_len4_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]], float noundef [[Z:%.*]], float noundef [[W:%.*]]) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_len4_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]], float noundef [[Z:%.*]], float noundef [[W:%.*]]) #[[ATTR14]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_norm4df(float x, float y, float z, float w) { @@ -2724,17 +2756,17 @@ extern "C" __device__ float test_norm4df(float x, float y, float z, float w) { // DEFAULT-LABEL: @test_norm4d( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_len4_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]], double noundef [[Z:%.*]], double noundef [[W:%.*]]) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_len4_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]], double noundef [[Z:%.*]], double noundef [[W:%.*]]) #[[ATTR14]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_norm4d( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) double @__ocml_len4_f64(double noundef nofpclass(nan inf) [[X:%.*]], double noundef nofpclass(nan inf) [[Y:%.*]], double noundef nofpclass(nan inf) [[Z:%.*]], double noundef nofpclass(nan inf) [[W:%.*]]) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_len4_f64(double noundef nofpclass(nan inf) [[X:%.*]], double noundef nofpclass(nan inf) [[Y:%.*]], double noundef nofpclass(nan inf) [[Z:%.*]], double noundef nofpclass(nan inf) [[W:%.*]]) #[[ATTR14]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_norm4d( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_len4_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]], double noundef [[Z:%.*]], double noundef [[W:%.*]]) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_len4_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]], double noundef [[Z:%.*]], double noundef [[W:%.*]]) #[[ATTR14]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_norm4d(double x, double y, double z, double w) { @@ -2743,17 +2775,17 @@ extern "C" __device__ double test_norm4d(double x, double y, double z, double w) // DEFAULT-LABEL: @test_normcdff( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_ncdf_f32(float noundef [[X:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_ncdf_f32(float noundef [[X:%.*]]) #[[ATTR15]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_normcdff( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) float @__ocml_ncdf_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_ncdf_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_normcdff( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_ncdf_f32(float noundef [[X:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_ncdf_f32(float noundef [[X:%.*]]) #[[ATTR15]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_normcdff(float x) { @@ -2762,17 +2794,17 @@ extern "C" __device__ float test_normcdff(float x) { // DEFAULT-LABEL: @test_normcdf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_ncdf_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_ncdf_f64(double noundef [[X:%.*]]) #[[ATTR15]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_normcdf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) double @__ocml_ncdf_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_ncdf_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_normcdf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_ncdf_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_ncdf_f64(double noundef [[X:%.*]]) #[[ATTR15]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_normcdf(double x) { @@ -2781,17 +2813,17 @@ extern "C" __device__ double test_normcdf(double x) { // DEFAULT-LABEL: @test_normcdfinvf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_ncdfinv_f32(float noundef [[X:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_ncdfinv_f32(float noundef [[X:%.*]]) #[[ATTR15]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_normcdfinvf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) float @__ocml_ncdfinv_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_ncdfinv_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_normcdfinvf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_ncdfinv_f32(float noundef [[X:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_ncdfinv_f32(float noundef [[X:%.*]]) #[[ATTR15]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_normcdfinvf(float x) { @@ -2800,17 +2832,17 @@ extern "C" __device__ float test_normcdfinvf(float x) { // DEFAULT-LABEL: @test_normcdfinv( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_ncdfinv_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_ncdfinv_f64(double noundef [[X:%.*]]) #[[ATTR15]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_normcdfinv( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) double @__ocml_ncdfinv_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_ncdfinv_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_normcdfinv( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_ncdfinv_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_ncdfinv_f64(double noundef [[X:%.*]]) #[[ATTR15]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_normcdfinv(double x) { @@ -2834,7 +2866,7 @@ extern "C" __device__ double test_normcdfinv(double x) { // DEFAULT-NEXT: br i1 [[TOBOOL_NOT_I]], label [[_ZL5NORMFIPKF_EXIT]], label [[WHILE_BODY_I]], !llvm.loop [[LOOP20:![0-9]+]] // DEFAULT: _ZL5normfiPKf.exit: // DEFAULT-NEXT: [[__R_0_LCSSA_I:%.*]] = phi float [ 0.000000e+00, [[ENTRY]] ], [ [[ADD_I]], [[WHILE_BODY_I]] ] -// DEFAULT-NEXT: [[TMP1:%.*]] = tail call contract float @llvm.sqrt.f32(float [[__R_0_LCSSA_I]]) +// DEFAULT-NEXT: [[TMP1:%.*]] = tail call contract noundef float @llvm.sqrt.f32(float [[__R_0_LCSSA_I]]) // DEFAULT-NEXT: ret float [[TMP1]] // // FINITEONLY-LABEL: @test_normf( @@ -2854,7 +2886,7 @@ extern "C" __device__ double test_normcdfinv(double x) { // FINITEONLY-NEXT: br i1 [[TOBOOL_NOT_I]], label [[_ZL5NORMFIPKF_EXIT]], label [[WHILE_BODY_I]], !llvm.loop [[LOOP20:![0-9]+]] // FINITEONLY: _ZL5normfiPKf.exit: // FINITEONLY-NEXT: [[__R_0_LCSSA_I:%.*]] = phi float [ 0.000000e+00, [[ENTRY]] ], [ [[ADD_I]], [[WHILE_BODY_I]] ] -// FINITEONLY-NEXT: [[TMP1:%.*]] = tail call nnan ninf contract float @llvm.sqrt.f32(float [[__R_0_LCSSA_I]]) +// FINITEONLY-NEXT: [[TMP1:%.*]] = tail call nnan ninf contract noundef float @llvm.sqrt.f32(float [[__R_0_LCSSA_I]]) // FINITEONLY-NEXT: ret float [[TMP1]] // // APPROX-LABEL: @test_normf( @@ -2874,7 +2906,7 @@ extern "C" __device__ double test_normcdfinv(double x) { // APPROX-NEXT: br i1 [[TOBOOL_NOT_I]], label [[_ZL5NORMFIPKF_EXIT]], label [[WHILE_BODY_I]], !llvm.loop [[LOOP20:![0-9]+]] // APPROX: _ZL5normfiPKf.exit: // APPROX-NEXT: [[__R_0_LCSSA_I:%.*]] = phi float [ 0.000000e+00, [[ENTRY]] ], [ [[ADD_I]], [[WHILE_BODY_I]] ] -// APPROX-NEXT: [[TMP1:%.*]] = tail call contract float @llvm.sqrt.f32(float [[__R_0_LCSSA_I]]) +// APPROX-NEXT: [[TMP1:%.*]] = tail call contract noundef float @llvm.sqrt.f32(float [[__R_0_LCSSA_I]]) // APPROX-NEXT: ret float [[TMP1]] // extern "C" __device__ float test_normf(int x, const float *y) { @@ -2898,7 +2930,7 @@ extern "C" __device__ float test_normf(int x, const float *y) { // DEFAULT-NEXT: br i1 [[TOBOOL_NOT_I]], label [[_ZL4NORMIPKD_EXIT]], label [[WHILE_BODY_I]], !llvm.loop [[LOOP21:![0-9]+]] // DEFAULT: _ZL4normiPKd.exit: // DEFAULT-NEXT: [[__R_0_LCSSA_I:%.*]] = phi double [ 0.000000e+00, [[ENTRY]] ], [ [[ADD_I]], [[WHILE_BODY_I]] ] -// DEFAULT-NEXT: [[TMP1:%.*]] = tail call contract double @llvm.sqrt.f64(double [[__R_0_LCSSA_I]]) +// DEFAULT-NEXT: [[TMP1:%.*]] = tail call contract noundef double @llvm.sqrt.f64(double [[__R_0_LCSSA_I]]) // DEFAULT-NEXT: ret double [[TMP1]] // // FINITEONLY-LABEL: @test_norm( @@ -2918,7 +2950,7 @@ extern "C" __device__ float test_normf(int x, const float *y) { // FINITEONLY-NEXT: br i1 [[TOBOOL_NOT_I]], label [[_ZL4NORMIPKD_EXIT]], label [[WHILE_BODY_I]], !llvm.loop [[LOOP21:![0-9]+]] // FINITEONLY: _ZL4normiPKd.exit: // FINITEONLY-NEXT: [[__R_0_LCSSA_I:%.*]] = phi double [ 0.000000e+00, [[ENTRY]] ], [ [[ADD_I]], [[WHILE_BODY_I]] ] -// FINITEONLY-NEXT: [[TMP1:%.*]] = tail call nnan ninf contract double @llvm.sqrt.f64(double [[__R_0_LCSSA_I]]) +// FINITEONLY-NEXT: [[TMP1:%.*]] = tail call nnan ninf contract noundef double @llvm.sqrt.f64(double [[__R_0_LCSSA_I]]) // FINITEONLY-NEXT: ret double [[TMP1]] // // APPROX-LABEL: @test_norm( @@ -2938,7 +2970,7 @@ extern "C" __device__ float test_normf(int x, const float *y) { // APPROX-NEXT: br i1 [[TOBOOL_NOT_I]], label [[_ZL4NORMIPKD_EXIT]], label [[WHILE_BODY_I]], !llvm.loop [[LOOP21:![0-9]+]] // APPROX: _ZL4normiPKd.exit: // APPROX-NEXT: [[__R_0_LCSSA_I:%.*]] = phi double [ 0.000000e+00, [[ENTRY]] ], [ [[ADD_I]], [[WHILE_BODY_I]] ] -// APPROX-NEXT: [[TMP1:%.*]] = tail call contract double @llvm.sqrt.f64(double [[__R_0_LCSSA_I]]) +// APPROX-NEXT: [[TMP1:%.*]] = tail call contract noundef double @llvm.sqrt.f64(double [[__R_0_LCSSA_I]]) // APPROX-NEXT: ret double [[TMP1]] // extern "C" __device__ double test_norm(int x, const double *y) { @@ -2947,17 +2979,17 @@ extern "C" __device__ double test_norm(int x, const double *y) { // DEFAULT-LABEL: @test_powf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_pow_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_pow_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR15]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_powf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) float @__ocml_pow_f32(float noundef nofpclass(nan inf) [[X:%.*]], float noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_pow_f32(float noundef nofpclass(nan inf) [[X:%.*]], float noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR15]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_powf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_pow_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_pow_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR15]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_powf(float x, float y) { @@ -2966,17 +2998,17 @@ extern "C" __device__ float test_powf(float x, float y) { // DEFAULT-LABEL: @test_pow( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_pow_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_pow_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR15]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_pow( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) double @__ocml_pow_f64(double noundef nofpclass(nan inf) [[X:%.*]], double noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_pow_f64(double noundef nofpclass(nan inf) [[X:%.*]], double noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR15]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_pow( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_pow_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_pow_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR15]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_pow(double x, double y) { @@ -2985,17 +3017,17 @@ extern "C" __device__ double test_pow(double x, double y) { // DEFAULT-LABEL: @test_powif( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_pown_f32(float noundef [[X:%.*]], i32 noundef [[Y:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_pown_f32(float noundef [[X:%.*]], i32 noundef [[Y:%.*]]) #[[ATTR15]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_powif( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) float @__ocml_pown_f32(float noundef nofpclass(nan inf) [[X:%.*]], i32 noundef [[Y:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_pown_f32(float noundef nofpclass(nan inf) [[X:%.*]], i32 noundef [[Y:%.*]]) #[[ATTR15]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_powif( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_pown_f32(float noundef [[X:%.*]], i32 noundef [[Y:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_pown_f32(float noundef [[X:%.*]], i32 noundef [[Y:%.*]]) #[[ATTR15]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_powif(float x, int y) { @@ -3004,17 +3036,17 @@ extern "C" __device__ float test_powif(float x, int y) { // DEFAULT-LABEL: @test_powi( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_pown_f64(double noundef [[X:%.*]], i32 noundef [[Y:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_pown_f64(double noundef [[X:%.*]], i32 noundef [[Y:%.*]]) #[[ATTR15]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_powi( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) double @__ocml_pown_f64(double noundef nofpclass(nan inf) [[X:%.*]], i32 noundef [[Y:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_pown_f64(double noundef nofpclass(nan inf) [[X:%.*]], i32 noundef [[Y:%.*]]) #[[ATTR15]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_powi( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_pown_f64(double noundef [[X:%.*]], i32 noundef [[Y:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_pown_f64(double noundef [[X:%.*]], i32 noundef [[Y:%.*]]) #[[ATTR15]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_powi(double x, int y) { @@ -3023,17 +3055,17 @@ extern "C" __device__ double test_powi(double x, int y) { // DEFAULT-LABEL: @test_rcbrtf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_rcbrt_f32(float noundef [[X:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_rcbrt_f32(float noundef [[X:%.*]]) #[[ATTR15]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_rcbrtf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) float @__ocml_rcbrt_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_rcbrt_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_rcbrtf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_rcbrt_f32(float noundef [[X:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_rcbrt_f32(float noundef [[X:%.*]]) #[[ATTR15]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_rcbrtf(float x) { @@ -3042,17 +3074,17 @@ extern "C" __device__ float test_rcbrtf(float x) { // DEFAULT-LABEL: @test_rcbrt( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_rcbrt_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_rcbrt_f64(double noundef [[X:%.*]]) #[[ATTR15]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_rcbrt( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) double @__ocml_rcbrt_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_rcbrt_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_rcbrt( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_rcbrt_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_rcbrt_f64(double noundef [[X:%.*]]) #[[ATTR15]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_rcbrt(double x) { @@ -3061,17 +3093,17 @@ extern "C" __device__ double test_rcbrt(double x) { // DEFAULT-LABEL: @test_remainderf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_remainder_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_remainder_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR14]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_remainderf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) float @__ocml_remainder_f32(float noundef nofpclass(nan inf) [[X:%.*]], float noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_remainder_f32(float noundef nofpclass(nan inf) [[X:%.*]], float noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR14]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_remainderf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_remainder_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_remainder_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR14]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_remainderf(float x, float y) { @@ -3080,17 +3112,17 @@ extern "C" __device__ float test_remainderf(float x, float y) { // DEFAULT-LABEL: @test_remainder( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_remainder_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_remainder_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR14]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_remainder( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) double @__ocml_remainder_f64(double noundef nofpclass(nan inf) [[X:%.*]], double noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_remainder_f64(double noundef nofpclass(nan inf) [[X:%.*]], double noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR14]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_remainder( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_remainder_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_remainder_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR14]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_remainder(double x, double y) { @@ -3101,7 +3133,7 @@ extern "C" __device__ double test_remainder(double x, double y) { // DEFAULT-NEXT: entry: // DEFAULT-NEXT: [[__TMP_I:%.*]] = alloca i32, align 4, addrspace(5) // DEFAULT-NEXT: call void @llvm.lifetime.start.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17]] -// DEFAULT-NEXT: [[CALL_I:%.*]] = call contract float @__ocml_remquo_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = call contract noundef float @__ocml_remquo_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR16]] // DEFAULT-NEXT: [[TMP0:%.*]] = load i32, ptr addrspace(5) [[__TMP_I]], align 4, !tbaa [[TBAA12]] // DEFAULT-NEXT: store i32 [[TMP0]], ptr [[Z:%.*]], align 4, !tbaa [[TBAA12]] // DEFAULT-NEXT: call void @llvm.lifetime.end.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17]] @@ -3111,7 +3143,7 @@ extern "C" __device__ double test_remainder(double x, double y) { // FINITEONLY-NEXT: entry: // FINITEONLY-NEXT: [[__TMP_I:%.*]] = alloca i32, align 4, addrspace(5) // FINITEONLY-NEXT: call void @llvm.lifetime.start.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17]] -// FINITEONLY-NEXT: [[CALL_I:%.*]] = call nnan ninf contract nofpclass(nan inf) float @__ocml_remquo_f32(float noundef nofpclass(nan inf) [[X:%.*]], float noundef nofpclass(nan inf) [[Y:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_remquo_f32(float noundef nofpclass(nan inf) [[X:%.*]], float noundef nofpclass(nan inf) [[Y:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR16]] // FINITEONLY-NEXT: [[TMP0:%.*]] = load i32, ptr addrspace(5) [[__TMP_I]], align 4, !tbaa [[TBAA12]] // FINITEONLY-NEXT: store i32 [[TMP0]], ptr [[Z:%.*]], align 4, !tbaa [[TBAA12]] // FINITEONLY-NEXT: call void @llvm.lifetime.end.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17]] @@ -3121,7 +3153,7 @@ extern "C" __device__ double test_remainder(double x, double y) { // APPROX-NEXT: entry: // APPROX-NEXT: [[__TMP_I:%.*]] = alloca i32, align 4, addrspace(5) // APPROX-NEXT: call void @llvm.lifetime.start.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17]] -// APPROX-NEXT: [[CALL_I:%.*]] = call contract float @__ocml_remquo_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I:%.*]] = call contract noundef float @__ocml_remquo_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR16]] // APPROX-NEXT: [[TMP0:%.*]] = load i32, ptr addrspace(5) [[__TMP_I]], align 4, !tbaa [[TBAA12]] // APPROX-NEXT: store i32 [[TMP0]], ptr [[Z:%.*]], align 4, !tbaa [[TBAA12]] // APPROX-NEXT: call void @llvm.lifetime.end.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17]] @@ -3135,7 +3167,7 @@ extern "C" __device__ float test_remquof(float x, float y, int* z) { // DEFAULT-NEXT: entry: // DEFAULT-NEXT: [[__TMP_I:%.*]] = alloca i32, align 4, addrspace(5) // DEFAULT-NEXT: call void @llvm.lifetime.start.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17]] -// DEFAULT-NEXT: [[CALL_I:%.*]] = call contract double @__ocml_remquo_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = call contract noundef double @__ocml_remquo_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR16]] // DEFAULT-NEXT: [[TMP0:%.*]] = load i32, ptr addrspace(5) [[__TMP_I]], align 4, !tbaa [[TBAA12]] // DEFAULT-NEXT: store i32 [[TMP0]], ptr [[Z:%.*]], align 4, !tbaa [[TBAA12]] // DEFAULT-NEXT: call void @llvm.lifetime.end.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17]] @@ -3145,7 +3177,7 @@ extern "C" __device__ float test_remquof(float x, float y, int* z) { // FINITEONLY-NEXT: entry: // FINITEONLY-NEXT: [[__TMP_I:%.*]] = alloca i32, align 4, addrspace(5) // FINITEONLY-NEXT: call void @llvm.lifetime.start.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17]] -// FINITEONLY-NEXT: [[CALL_I:%.*]] = call nnan ninf contract nofpclass(nan inf) double @__ocml_remquo_f64(double noundef nofpclass(nan inf) [[X:%.*]], double noundef nofpclass(nan inf) [[Y:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_remquo_f64(double noundef nofpclass(nan inf) [[X:%.*]], double noundef nofpclass(nan inf) [[Y:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR16]] // FINITEONLY-NEXT: [[TMP0:%.*]] = load i32, ptr addrspace(5) [[__TMP_I]], align 4, !tbaa [[TBAA12]] // FINITEONLY-NEXT: store i32 [[TMP0]], ptr [[Z:%.*]], align 4, !tbaa [[TBAA12]] // FINITEONLY-NEXT: call void @llvm.lifetime.end.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17]] @@ -3155,7 +3187,7 @@ extern "C" __device__ float test_remquof(float x, float y, int* z) { // APPROX-NEXT: entry: // APPROX-NEXT: [[__TMP_I:%.*]] = alloca i32, align 4, addrspace(5) // APPROX-NEXT: call void @llvm.lifetime.start.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17]] -// APPROX-NEXT: [[CALL_I:%.*]] = call contract double @__ocml_remquo_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I:%.*]] = call contract noundef double @__ocml_remquo_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]], ptr addrspace(5) noundef [[__TMP_I]]) #[[ATTR16]] // APPROX-NEXT: [[TMP0:%.*]] = load i32, ptr addrspace(5) [[__TMP_I]], align 4, !tbaa [[TBAA12]] // APPROX-NEXT: store i32 [[TMP0]], ptr [[Z:%.*]], align 4, !tbaa [[TBAA12]] // APPROX-NEXT: call void @llvm.lifetime.end.p5(i64 4, ptr addrspace(5) [[__TMP_I]]) #[[ATTR17]] @@ -3167,17 +3199,17 @@ extern "C" __device__ double test_remquo(double x, double y, int* z) { // DEFAULT-LABEL: @test_rhypotf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_rhypot_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_rhypot_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR14]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_rhypotf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) float @__ocml_rhypot_f32(float noundef nofpclass(nan inf) [[X:%.*]], float noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_rhypot_f32(float noundef nofpclass(nan inf) [[X:%.*]], float noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR14]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_rhypotf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_rhypot_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_rhypot_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR14]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_rhypotf(float x, float y) { @@ -3186,17 +3218,17 @@ extern "C" __device__ float test_rhypotf(float x, float y) { // DEFAULT-LABEL: @test_rhypot( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_rhypot_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_rhypot_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR14]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_rhypot( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) double @__ocml_rhypot_f64(double noundef nofpclass(nan inf) [[X:%.*]], double noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_rhypot_f64(double noundef nofpclass(nan inf) [[X:%.*]], double noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR14]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_rhypot( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_rhypot_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_rhypot_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR14]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_rhypot(double x, double y) { @@ -3205,17 +3237,17 @@ extern "C" __device__ double test_rhypot(double x, double y) { // DEFAULT-LABEL: @test_rintf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract float @llvm.rint.f32(float [[X:%.*]]) +// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract noundef float @llvm.rint.f32(float [[X:%.*]]) // DEFAULT-NEXT: ret float [[TMP0]] // // FINITEONLY-LABEL: @test_rintf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract float @llvm.rint.f32(float [[X:%.*]]) +// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract noundef float @llvm.rint.f32(float [[X:%.*]]) // FINITEONLY-NEXT: ret float [[TMP0]] // // APPROX-LABEL: @test_rintf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[TMP0:%.*]] = tail call contract float @llvm.rint.f32(float [[X:%.*]]) +// APPROX-NEXT: [[TMP0:%.*]] = tail call contract noundef float @llvm.rint.f32(float [[X:%.*]]) // APPROX-NEXT: ret float [[TMP0]] // extern "C" __device__ float test_rintf(float x) { @@ -3224,17 +3256,17 @@ extern "C" __device__ float test_rintf(float x) { // DEFAULT-LABEL: @test_rint( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract double @llvm.rint.f64(double [[X:%.*]]) +// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract noundef double @llvm.rint.f64(double [[X:%.*]]) // DEFAULT-NEXT: ret double [[TMP0]] // // FINITEONLY-LABEL: @test_rint( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract double @llvm.rint.f64(double [[X:%.*]]) +// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract noundef double @llvm.rint.f64(double [[X:%.*]]) // FINITEONLY-NEXT: ret double [[TMP0]] // // APPROX-LABEL: @test_rint( // APPROX-NEXT: entry: -// APPROX-NEXT: [[TMP0:%.*]] = tail call contract double @llvm.rint.f64(double [[X:%.*]]) +// APPROX-NEXT: [[TMP0:%.*]] = tail call contract noundef double @llvm.rint.f64(double [[X:%.*]]) // APPROX-NEXT: ret double [[TMP0]] // extern "C" __device__ double test_rint(double x) { @@ -3258,7 +3290,7 @@ extern "C" __device__ double test_rint(double x) { // DEFAULT-NEXT: br i1 [[TOBOOL_NOT_I]], label [[_ZL6RNORMFIPKF_EXIT]], label [[WHILE_BODY_I]], !llvm.loop [[LOOP22:![0-9]+]] // DEFAULT: _ZL6rnormfiPKf.exit: // DEFAULT-NEXT: [[__R_0_LCSSA_I:%.*]] = phi float [ 0.000000e+00, [[ENTRY]] ], [ [[ADD_I]], [[WHILE_BODY_I]] ] -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_rsqrt_f32(float noundef [[__R_0_LCSSA_I]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_rsqrt_f32(float noundef [[__R_0_LCSSA_I]]) #[[ATTR15]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_rnormf( @@ -3278,7 +3310,7 @@ extern "C" __device__ double test_rint(double x) { // FINITEONLY-NEXT: br i1 [[TOBOOL_NOT_I]], label [[_ZL6RNORMFIPKF_EXIT]], label [[WHILE_BODY_I]], !llvm.loop [[LOOP22:![0-9]+]] // FINITEONLY: _ZL6rnormfiPKf.exit: // FINITEONLY-NEXT: [[__R_0_LCSSA_I:%.*]] = phi float [ 0.000000e+00, [[ENTRY]] ], [ [[ADD_I]], [[WHILE_BODY_I]] ] -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) float @__ocml_rsqrt_f32(float noundef nofpclass(nan inf) [[__R_0_LCSSA_I]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_rsqrt_f32(float noundef nofpclass(nan inf) [[__R_0_LCSSA_I]]) #[[ATTR15]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_rnormf( @@ -3298,7 +3330,7 @@ extern "C" __device__ double test_rint(double x) { // APPROX-NEXT: br i1 [[TOBOOL_NOT_I]], label [[_ZL6RNORMFIPKF_EXIT]], label [[WHILE_BODY_I]], !llvm.loop [[LOOP22:![0-9]+]] // APPROX: _ZL6rnormfiPKf.exit: // APPROX-NEXT: [[__R_0_LCSSA_I:%.*]] = phi float [ 0.000000e+00, [[ENTRY]] ], [ [[ADD_I]], [[WHILE_BODY_I]] ] -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_rsqrt_f32(float noundef [[__R_0_LCSSA_I]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_rsqrt_f32(float noundef [[__R_0_LCSSA_I]]) #[[ATTR15]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_rnormf(int x, const float* y) { @@ -3322,7 +3354,7 @@ extern "C" __device__ float test_rnormf(int x, const float* y) { // DEFAULT-NEXT: br i1 [[TOBOOL_NOT_I]], label [[_ZL5RNORMIPKD_EXIT]], label [[WHILE_BODY_I]], !llvm.loop [[LOOP23:![0-9]+]] // DEFAULT: _ZL5rnormiPKd.exit: // DEFAULT-NEXT: [[__R_0_LCSSA_I:%.*]] = phi double [ 0.000000e+00, [[ENTRY]] ], [ [[ADD_I]], [[WHILE_BODY_I]] ] -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_rsqrt_f64(double noundef [[__R_0_LCSSA_I]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_rsqrt_f64(double noundef [[__R_0_LCSSA_I]]) #[[ATTR15]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_rnorm( @@ -3342,7 +3374,7 @@ extern "C" __device__ float test_rnormf(int x, const float* y) { // FINITEONLY-NEXT: br i1 [[TOBOOL_NOT_I]], label [[_ZL5RNORMIPKD_EXIT]], label [[WHILE_BODY_I]], !llvm.loop [[LOOP23:![0-9]+]] // FINITEONLY: _ZL5rnormiPKd.exit: // FINITEONLY-NEXT: [[__R_0_LCSSA_I:%.*]] = phi double [ 0.000000e+00, [[ENTRY]] ], [ [[ADD_I]], [[WHILE_BODY_I]] ] -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) double @__ocml_rsqrt_f64(double noundef nofpclass(nan inf) [[__R_0_LCSSA_I]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_rsqrt_f64(double noundef nofpclass(nan inf) [[__R_0_LCSSA_I]]) #[[ATTR15]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_rnorm( @@ -3362,7 +3394,7 @@ extern "C" __device__ float test_rnormf(int x, const float* y) { // APPROX-NEXT: br i1 [[TOBOOL_NOT_I]], label [[_ZL5RNORMIPKD_EXIT]], label [[WHILE_BODY_I]], !llvm.loop [[LOOP23:![0-9]+]] // APPROX: _ZL5rnormiPKd.exit: // APPROX-NEXT: [[__R_0_LCSSA_I:%.*]] = phi double [ 0.000000e+00, [[ENTRY]] ], [ [[ADD_I]], [[WHILE_BODY_I]] ] -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_rsqrt_f64(double noundef [[__R_0_LCSSA_I]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_rsqrt_f64(double noundef [[__R_0_LCSSA_I]]) #[[ATTR15]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_rnorm(int x, const double* y) { @@ -3371,17 +3403,17 @@ extern "C" __device__ double test_rnorm(int x, const double* y) { // DEFAULT-LABEL: @test_rnorm3df( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_rlen3_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]], float noundef [[Z:%.*]]) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_rlen3_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]], float noundef [[Z:%.*]]) #[[ATTR14]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_rnorm3df( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) float @__ocml_rlen3_f32(float noundef nofpclass(nan inf) [[X:%.*]], float noundef nofpclass(nan inf) [[Y:%.*]], float noundef nofpclass(nan inf) [[Z:%.*]]) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_rlen3_f32(float noundef nofpclass(nan inf) [[X:%.*]], float noundef nofpclass(nan inf) [[Y:%.*]], float noundef nofpclass(nan inf) [[Z:%.*]]) #[[ATTR14]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_rnorm3df( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_rlen3_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]], float noundef [[Z:%.*]]) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_rlen3_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]], float noundef [[Z:%.*]]) #[[ATTR14]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_rnorm3df(float x, float y, float z) { @@ -3390,17 +3422,17 @@ extern "C" __device__ float test_rnorm3df(float x, float y, float z) { // DEFAULT-LABEL: @test_rnorm3d( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_rlen3_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]], double noundef [[Z:%.*]]) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_rlen3_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]], double noundef [[Z:%.*]]) #[[ATTR14]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_rnorm3d( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) double @__ocml_rlen3_f64(double noundef nofpclass(nan inf) [[X:%.*]], double noundef nofpclass(nan inf) [[Y:%.*]], double noundef nofpclass(nan inf) [[Z:%.*]]) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_rlen3_f64(double noundef nofpclass(nan inf) [[X:%.*]], double noundef nofpclass(nan inf) [[Y:%.*]], double noundef nofpclass(nan inf) [[Z:%.*]]) #[[ATTR14]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_rnorm3d( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_rlen3_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]], double noundef [[Z:%.*]]) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_rlen3_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]], double noundef [[Z:%.*]]) #[[ATTR14]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_rnorm3d(double x, double y, double z) { @@ -3409,17 +3441,17 @@ extern "C" __device__ double test_rnorm3d(double x, double y, double z) { // DEFAULT-LABEL: @test_rnorm4df( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_rlen4_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]], float noundef [[Z:%.*]], float noundef [[W:%.*]]) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_rlen4_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]], float noundef [[Z:%.*]], float noundef [[W:%.*]]) #[[ATTR14]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_rnorm4df( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) float @__ocml_rlen4_f32(float noundef nofpclass(nan inf) [[X:%.*]], float noundef nofpclass(nan inf) [[Y:%.*]], float noundef nofpclass(nan inf) [[Z:%.*]], float noundef nofpclass(nan inf) [[W:%.*]]) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_rlen4_f32(float noundef nofpclass(nan inf) [[X:%.*]], float noundef nofpclass(nan inf) [[Y:%.*]], float noundef nofpclass(nan inf) [[Z:%.*]], float noundef nofpclass(nan inf) [[W:%.*]]) #[[ATTR14]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_rnorm4df( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_rlen4_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]], float noundef [[Z:%.*]], float noundef [[W:%.*]]) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_rlen4_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]], float noundef [[Z:%.*]], float noundef [[W:%.*]]) #[[ATTR14]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_rnorm4df(float x, float y, float z, float w) { @@ -3428,17 +3460,17 @@ extern "C" __device__ float test_rnorm4df(float x, float y, float z, float w) { // DEFAULT-LABEL: @test_rnorm4d( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_rlen4_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]], double noundef [[Z:%.*]], double noundef [[W:%.*]]) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_rlen4_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]], double noundef [[Z:%.*]], double noundef [[W:%.*]]) #[[ATTR14]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_rnorm4d( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) double @__ocml_rlen4_f64(double noundef nofpclass(nan inf) [[X:%.*]], double noundef nofpclass(nan inf) [[Y:%.*]], double noundef nofpclass(nan inf) [[Z:%.*]], double noundef nofpclass(nan inf) [[W:%.*]]) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_rlen4_f64(double noundef nofpclass(nan inf) [[X:%.*]], double noundef nofpclass(nan inf) [[Y:%.*]], double noundef nofpclass(nan inf) [[Z:%.*]], double noundef nofpclass(nan inf) [[W:%.*]]) #[[ATTR14]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_rnorm4d( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_rlen4_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]], double noundef [[Z:%.*]], double noundef [[W:%.*]]) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_rlen4_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]], double noundef [[Z:%.*]], double noundef [[W:%.*]]) #[[ATTR14]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_rnorm4d(double x, double y, double z, double w) { @@ -3447,17 +3479,17 @@ extern "C" __device__ double test_rnorm4d(double x, double y, double z, double w // DEFAULT-LABEL: @test_roundf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract float @llvm.round.f32(float [[X:%.*]]) +// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract noundef float @llvm.round.f32(float [[X:%.*]]) // DEFAULT-NEXT: ret float [[TMP0]] // // FINITEONLY-LABEL: @test_roundf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract float @llvm.round.f32(float [[X:%.*]]) +// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract noundef float @llvm.round.f32(float [[X:%.*]]) // FINITEONLY-NEXT: ret float [[TMP0]] // // APPROX-LABEL: @test_roundf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[TMP0:%.*]] = tail call contract float @llvm.round.f32(float [[X:%.*]]) +// APPROX-NEXT: [[TMP0:%.*]] = tail call contract noundef float @llvm.round.f32(float [[X:%.*]]) // APPROX-NEXT: ret float [[TMP0]] // extern "C" __device__ float test_roundf(float x) { @@ -3466,17 +3498,17 @@ extern "C" __device__ float test_roundf(float x) { // DEFAULT-LABEL: @test_round( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract double @llvm.round.f64(double [[X:%.*]]) +// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract noundef double @llvm.round.f64(double [[X:%.*]]) // DEFAULT-NEXT: ret double [[TMP0]] // // FINITEONLY-LABEL: @test_round( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract double @llvm.round.f64(double [[X:%.*]]) +// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract noundef double @llvm.round.f64(double [[X:%.*]]) // FINITEONLY-NEXT: ret double [[TMP0]] // // APPROX-LABEL: @test_round( // APPROX-NEXT: entry: -// APPROX-NEXT: [[TMP0:%.*]] = tail call contract double @llvm.round.f64(double [[X:%.*]]) +// APPROX-NEXT: [[TMP0:%.*]] = tail call contract noundef double @llvm.round.f64(double [[X:%.*]]) // APPROX-NEXT: ret double [[TMP0]] // extern "C" __device__ double test_round(double x) { @@ -3485,17 +3517,17 @@ extern "C" __device__ double test_round(double x) { // DEFAULT-LABEL: @test_rsqrtf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_rsqrt_f32(float noundef [[X:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_rsqrt_f32(float noundef [[X:%.*]]) #[[ATTR15]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_rsqrtf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) float @__ocml_rsqrt_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_rsqrt_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_rsqrtf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_rsqrt_f32(float noundef [[X:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_rsqrt_f32(float noundef [[X:%.*]]) #[[ATTR15]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_rsqrtf(float x) { @@ -3504,17 +3536,17 @@ extern "C" __device__ float test_rsqrtf(float x) { // DEFAULT-LABEL: @test_rsqrt( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_rsqrt_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_rsqrt_f64(double noundef [[X:%.*]]) #[[ATTR15]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_rsqrt( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) double @__ocml_rsqrt_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_rsqrt_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_rsqrt( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_rsqrt_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_rsqrt_f64(double noundef [[X:%.*]]) #[[ATTR15]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_rsqrt(double x) { @@ -3621,17 +3653,17 @@ extern "C" __device__ double test_scalbln(double x, long int y) { // DEFAULT-LABEL: @test_scalbnf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract float @llvm.ldexp.f32.i32(float [[X:%.*]], i32 [[Y:%.*]]) +// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract noundef float @llvm.ldexp.f32.i32(float [[X:%.*]], i32 [[Y:%.*]]) // DEFAULT-NEXT: ret float [[TMP0]] // // FINITEONLY-LABEL: @test_scalbnf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract float @llvm.ldexp.f32.i32(float [[X:%.*]], i32 [[Y:%.*]]) +// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract noundef float @llvm.ldexp.f32.i32(float [[X:%.*]], i32 [[Y:%.*]]) // FINITEONLY-NEXT: ret float [[TMP0]] // // APPROX-LABEL: @test_scalbnf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[TMP0:%.*]] = tail call contract float @llvm.ldexp.f32.i32(float [[X:%.*]], i32 [[Y:%.*]]) +// APPROX-NEXT: [[TMP0:%.*]] = tail call contract noundef float @llvm.ldexp.f32.i32(float [[X:%.*]], i32 [[Y:%.*]]) // APPROX-NEXT: ret float [[TMP0]] // extern "C" __device__ float test_scalbnf(float x, int y) { @@ -3640,17 +3672,17 @@ extern "C" __device__ float test_scalbnf(float x, int y) { // DEFAULT-LABEL: @test_scalbn( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract double @llvm.ldexp.f64.i32(double [[X:%.*]], i32 [[Y:%.*]]) +// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract noundef double @llvm.ldexp.f64.i32(double [[X:%.*]], i32 [[Y:%.*]]) // DEFAULT-NEXT: ret double [[TMP0]] // // FINITEONLY-LABEL: @test_scalbn( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract double @llvm.ldexp.f64.i32(double [[X:%.*]], i32 [[Y:%.*]]) +// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract noundef double @llvm.ldexp.f64.i32(double [[X:%.*]], i32 [[Y:%.*]]) // FINITEONLY-NEXT: ret double [[TMP0]] // // APPROX-LABEL: @test_scalbn( // APPROX-NEXT: entry: -// APPROX-NEXT: [[TMP0:%.*]] = tail call contract double @llvm.ldexp.f64.i32(double [[X:%.*]], i32 [[Y:%.*]]) +// APPROX-NEXT: [[TMP0:%.*]] = tail call contract noundef double @llvm.ldexp.f64.i32(double [[X:%.*]], i32 [[Y:%.*]]) // APPROX-NEXT: ret double [[TMP0]] // extern "C" __device__ double test_scalbn(double x, int y) { @@ -3828,17 +3860,17 @@ extern "C" __device__ void test_sincospi(double x, double *y, double *z) { // DEFAULT-LABEL: @test_sinf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_sin_f32(float noundef [[X:%.*]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_sin_f32(float noundef [[X:%.*]]) #[[ATTR16]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_sinf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) float @__ocml_sin_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_sin_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_sinf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I_I:%.*]] = tail call contract float @__ocml_native_sin_f32(float noundef [[X:%.*]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I_I:%.*]] = tail call contract noundef float @__ocml_native_sin_f32(float noundef [[X:%.*]]) #[[ATTR16]] // APPROX-NEXT: ret float [[CALL_I_I]] // extern "C" __device__ float test_sinf(float x) { @@ -3847,17 +3879,17 @@ extern "C" __device__ float test_sinf(float x) { // DEFAULT-LABEL: @test_sin( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_sin_f64(double noundef [[X:%.*]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_sin_f64(double noundef [[X:%.*]]) #[[ATTR16]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_sin( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) double @__ocml_sin_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_sin_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_sin( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_sin_f64(double noundef [[X:%.*]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_sin_f64(double noundef [[X:%.*]]) #[[ATTR16]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_sin(double x) { @@ -3866,17 +3898,17 @@ extern "C" __device__ double test_sin(double x) { // DEFAULT-LABEL: @test_sinpif( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_sinpi_f32(float noundef [[X:%.*]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_sinpi_f32(float noundef [[X:%.*]]) #[[ATTR16]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_sinpif( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) float @__ocml_sinpi_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_sinpi_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_sinpif( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_sinpi_f32(float noundef [[X:%.*]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_sinpi_f32(float noundef [[X:%.*]]) #[[ATTR16]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_sinpif(float x) { @@ -3885,17 +3917,17 @@ extern "C" __device__ float test_sinpif(float x) { // DEFAULT-LABEL: @test_sinpi( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_sinpi_f64(double noundef [[X:%.*]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_sinpi_f64(double noundef [[X:%.*]]) #[[ATTR16]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_sinpi( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) double @__ocml_sinpi_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_sinpi_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_sinpi( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_sinpi_f64(double noundef [[X:%.*]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_sinpi_f64(double noundef [[X:%.*]]) #[[ATTR16]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_sinpi(double x) { @@ -3904,17 +3936,17 @@ extern "C" __device__ double test_sinpi(double x) { // DEFAULT-LABEL: @test_sqrtf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract float @llvm.sqrt.f32(float [[X:%.*]]) +// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract noundef float @llvm.sqrt.f32(float [[X:%.*]]) // DEFAULT-NEXT: ret float [[TMP0]] // // FINITEONLY-LABEL: @test_sqrtf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract float @llvm.sqrt.f32(float [[X:%.*]]) +// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract noundef float @llvm.sqrt.f32(float [[X:%.*]]) // FINITEONLY-NEXT: ret float [[TMP0]] // // APPROX-LABEL: @test_sqrtf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[TMP0:%.*]] = tail call contract float @llvm.sqrt.f32(float [[X:%.*]]) +// APPROX-NEXT: [[TMP0:%.*]] = tail call contract noundef float @llvm.sqrt.f32(float [[X:%.*]]) // APPROX-NEXT: ret float [[TMP0]] // extern "C" __device__ float test_sqrtf(float x) { @@ -3923,17 +3955,17 @@ extern "C" __device__ float test_sqrtf(float x) { // DEFAULT-LABEL: @test_sqrt( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract double @llvm.sqrt.f64(double [[X:%.*]]) +// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract noundef double @llvm.sqrt.f64(double [[X:%.*]]) // DEFAULT-NEXT: ret double [[TMP0]] // // FINITEONLY-LABEL: @test_sqrt( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract double @llvm.sqrt.f64(double [[X:%.*]]) +// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract noundef double @llvm.sqrt.f64(double [[X:%.*]]) // FINITEONLY-NEXT: ret double [[TMP0]] // // APPROX-LABEL: @test_sqrt( // APPROX-NEXT: entry: -// APPROX-NEXT: [[TMP0:%.*]] = tail call contract double @llvm.sqrt.f64(double [[X:%.*]]) +// APPROX-NEXT: [[TMP0:%.*]] = tail call contract noundef double @llvm.sqrt.f64(double [[X:%.*]]) // APPROX-NEXT: ret double [[TMP0]] // extern "C" __device__ double test_sqrt(double x) { @@ -3942,17 +3974,17 @@ extern "C" __device__ double test_sqrt(double x) { // DEFAULT-LABEL: @test_tanf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_tan_f32(float noundef [[X:%.*]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_tan_f32(float noundef [[X:%.*]]) #[[ATTR16]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_tanf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) float @__ocml_tan_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_tan_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_tanf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_tan_f32(float noundef [[X:%.*]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_tan_f32(float noundef [[X:%.*]]) #[[ATTR16]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_tanf(float x) { @@ -3961,17 +3993,17 @@ extern "C" __device__ float test_tanf(float x) { // DEFAULT-LABEL: @test_tan( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_tan_f64(double noundef [[X:%.*]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_tan_f64(double noundef [[X:%.*]]) #[[ATTR16]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_tan( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) double @__ocml_tan_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_tan_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_tan( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_tan_f64(double noundef [[X:%.*]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_tan_f64(double noundef [[X:%.*]]) #[[ATTR16]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_tan(double x) { @@ -3980,17 +4012,17 @@ extern "C" __device__ double test_tan(double x) { // DEFAULT-LABEL: @test_tanhf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_tanh_f32(float noundef [[X:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_tanh_f32(float noundef [[X:%.*]]) #[[ATTR15]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_tanhf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) float @__ocml_tanh_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_tanh_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_tanhf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_tanh_f32(float noundef [[X:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_tanh_f32(float noundef [[X:%.*]]) #[[ATTR15]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_tanhf(float x) { @@ -3999,17 +4031,17 @@ extern "C" __device__ float test_tanhf(float x) { // DEFAULT-LABEL: @test_tanh( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_tanh_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_tanh_f64(double noundef [[X:%.*]]) #[[ATTR15]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_tanh( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) double @__ocml_tanh_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_tanh_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR15]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_tanh( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_tanh_f64(double noundef [[X:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_tanh_f64(double noundef [[X:%.*]]) #[[ATTR15]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_tanh(double x) { @@ -4018,17 +4050,17 @@ extern "C" __device__ double test_tanh(double x) { // DEFAULT-LABEL: @test_tgammaf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_tgamma_f32(float noundef [[X:%.*]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_tgamma_f32(float noundef [[X:%.*]]) #[[ATTR16]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_tgammaf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) float @__ocml_tgamma_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_tgamma_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_tgammaf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_tgamma_f32(float noundef [[X:%.*]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_tgamma_f32(float noundef [[X:%.*]]) #[[ATTR16]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_tgammaf(float x) { @@ -4037,17 +4069,17 @@ extern "C" __device__ float test_tgammaf(float x) { // DEFAULT-LABEL: @test_tgamma( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_tgamma_f64(double noundef [[X:%.*]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_tgamma_f64(double noundef [[X:%.*]]) #[[ATTR16]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_tgamma( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) double @__ocml_tgamma_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_tgamma_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_tgamma( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_tgamma_f64(double noundef [[X:%.*]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_tgamma_f64(double noundef [[X:%.*]]) #[[ATTR16]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_tgamma(double x) { @@ -4056,17 +4088,17 @@ extern "C" __device__ double test_tgamma(double x) { // DEFAULT-LABEL: @test_truncf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract float @llvm.trunc.f32(float [[X:%.*]]) +// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract noundef float @llvm.trunc.f32(float [[X:%.*]]) // DEFAULT-NEXT: ret float [[TMP0]] // // FINITEONLY-LABEL: @test_truncf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract float @llvm.trunc.f32(float [[X:%.*]]) +// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract noundef float @llvm.trunc.f32(float [[X:%.*]]) // FINITEONLY-NEXT: ret float [[TMP0]] // // APPROX-LABEL: @test_truncf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[TMP0:%.*]] = tail call contract float @llvm.trunc.f32(float [[X:%.*]]) +// APPROX-NEXT: [[TMP0:%.*]] = tail call contract noundef float @llvm.trunc.f32(float [[X:%.*]]) // APPROX-NEXT: ret float [[TMP0]] // extern "C" __device__ float test_truncf(float x) { @@ -4075,17 +4107,17 @@ extern "C" __device__ float test_truncf(float x) { // DEFAULT-LABEL: @test_trunc( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract double @llvm.trunc.f64(double [[X:%.*]]) +// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract noundef double @llvm.trunc.f64(double [[X:%.*]]) // DEFAULT-NEXT: ret double [[TMP0]] // // FINITEONLY-LABEL: @test_trunc( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract double @llvm.trunc.f64(double [[X:%.*]]) +// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract noundef double @llvm.trunc.f64(double [[X:%.*]]) // FINITEONLY-NEXT: ret double [[TMP0]] // // APPROX-LABEL: @test_trunc( // APPROX-NEXT: entry: -// APPROX-NEXT: [[TMP0:%.*]] = tail call contract double @llvm.trunc.f64(double [[X:%.*]]) +// APPROX-NEXT: [[TMP0:%.*]] = tail call contract noundef double @llvm.trunc.f64(double [[X:%.*]]) // APPROX-NEXT: ret double [[TMP0]] // extern "C" __device__ double test_trunc(double x) { @@ -4094,17 +4126,17 @@ extern "C" __device__ double test_trunc(double x) { // DEFAULT-LABEL: @test_y0f( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_y0_f32(float noundef [[X:%.*]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_y0_f32(float noundef [[X:%.*]]) #[[ATTR16]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_y0f( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) float @__ocml_y0_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_y0_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_y0f( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_y0_f32(float noundef [[X:%.*]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_y0_f32(float noundef [[X:%.*]]) #[[ATTR16]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_y0f(float x) { @@ -4113,17 +4145,17 @@ extern "C" __device__ float test_y0f(float x) { // DEFAULT-LABEL: @test_y0( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_y0_f64(double noundef [[X:%.*]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_y0_f64(double noundef [[X:%.*]]) #[[ATTR16]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_y0( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) double @__ocml_y0_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_y0_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_y0( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_y0_f64(double noundef [[X:%.*]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_y0_f64(double noundef [[X:%.*]]) #[[ATTR16]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_y0(double x) { @@ -4132,17 +4164,17 @@ extern "C" __device__ double test_y0(double x) { // DEFAULT-LABEL: @test_y1f( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_y1_f32(float noundef [[X:%.*]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_y1_f32(float noundef [[X:%.*]]) #[[ATTR16]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test_y1f( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) float @__ocml_y1_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_y1_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test_y1f( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_y1_f32(float noundef [[X:%.*]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_y1_f32(float noundef [[X:%.*]]) #[[ATTR16]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test_y1f(float x) { @@ -4151,17 +4183,17 @@ extern "C" __device__ float test_y1f(float x) { // DEFAULT-LABEL: @test_y1( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_y1_f64(double noundef [[X:%.*]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_y1_f64(double noundef [[X:%.*]]) #[[ATTR16]] // DEFAULT-NEXT: ret double [[CALL_I]] // // FINITEONLY-LABEL: @test_y1( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) double @__ocml_y1_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_y1_f64(double noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] // FINITEONLY-NEXT: ret double [[CALL_I]] // // APPROX-LABEL: @test_y1( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_y1_f64(double noundef [[X:%.*]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_y1_f64(double noundef [[X:%.*]]) #[[ATTR16]] // APPROX-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test_y1(double x) { @@ -4175,14 +4207,14 @@ extern "C" __device__ double test_y1(double x) { // DEFAULT-NEXT: i32 1, label [[IF_THEN2_I:%.*]] // DEFAULT-NEXT: ] // DEFAULT: if.then.i: -// DEFAULT-NEXT: [[CALL_I_I:%.*]] = tail call contract float @__ocml_y0_f32(float noundef [[Y:%.*]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I_I:%.*]] = tail call contract noundef float @__ocml_y0_f32(float noundef [[Y:%.*]]) #[[ATTR16]] // DEFAULT-NEXT: br label [[_ZL3YNFIF_EXIT:%.*]] // DEFAULT: if.then2.i: -// DEFAULT-NEXT: [[CALL_I20_I:%.*]] = tail call contract float @__ocml_y1_f32(float noundef [[Y]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I20_I:%.*]] = tail call contract noundef float @__ocml_y1_f32(float noundef [[Y]]) #[[ATTR16]] // DEFAULT-NEXT: br label [[_ZL3YNFIF_EXIT]] // DEFAULT: if.end4.i: -// DEFAULT-NEXT: [[CALL_I21_I:%.*]] = tail call contract float @__ocml_y0_f32(float noundef [[Y]]) #[[ATTR16]] -// DEFAULT-NEXT: [[CALL_I22_I:%.*]] = tail call contract float @__ocml_y1_f32(float noundef [[Y]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I21_I:%.*]] = tail call contract noundef float @__ocml_y0_f32(float noundef [[Y]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I22_I:%.*]] = tail call contract noundef float @__ocml_y1_f32(float noundef [[Y]]) #[[ATTR16]] // DEFAULT-NEXT: [[CMP723_I:%.*]] = icmp sgt i32 [[X]], 1 // DEFAULT-NEXT: br i1 [[CMP723_I]], label [[FOR_BODY_I:%.*]], label [[_ZL3YNFIF_EXIT]] // DEFAULT: for.body.i: @@ -4208,14 +4240,14 @@ extern "C" __device__ double test_y1(double x) { // FINITEONLY-NEXT: i32 1, label [[IF_THEN2_I:%.*]] // FINITEONLY-NEXT: ] // FINITEONLY: if.then.i: -// FINITEONLY-NEXT: [[CALL_I_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) float @__ocml_y0_f32(float noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_y0_f32(float noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR16]] // FINITEONLY-NEXT: br label [[_ZL3YNFIF_EXIT:%.*]] // FINITEONLY: if.then2.i: -// FINITEONLY-NEXT: [[CALL_I20_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) float @__ocml_y1_f32(float noundef nofpclass(nan inf) [[Y]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I20_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_y1_f32(float noundef nofpclass(nan inf) [[Y]]) #[[ATTR16]] // FINITEONLY-NEXT: br label [[_ZL3YNFIF_EXIT]] // FINITEONLY: if.end4.i: -// FINITEONLY-NEXT: [[CALL_I21_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) float @__ocml_y0_f32(float noundef nofpclass(nan inf) [[Y]]) #[[ATTR16]] -// FINITEONLY-NEXT: [[CALL_I22_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) float @__ocml_y1_f32(float noundef nofpclass(nan inf) [[Y]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I21_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_y0_f32(float noundef nofpclass(nan inf) [[Y]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I22_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_y1_f32(float noundef nofpclass(nan inf) [[Y]]) #[[ATTR16]] // FINITEONLY-NEXT: [[CMP723_I:%.*]] = icmp sgt i32 [[X]], 1 // FINITEONLY-NEXT: br i1 [[CMP723_I]], label [[FOR_BODY_I:%.*]], label [[_ZL3YNFIF_EXIT]] // FINITEONLY: for.body.i: @@ -4241,14 +4273,14 @@ extern "C" __device__ double test_y1(double x) { // APPROX-NEXT: i32 1, label [[IF_THEN2_I:%.*]] // APPROX-NEXT: ] // APPROX: if.then.i: -// APPROX-NEXT: [[CALL_I_I:%.*]] = tail call contract float @__ocml_y0_f32(float noundef [[Y:%.*]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I_I:%.*]] = tail call contract noundef float @__ocml_y0_f32(float noundef [[Y:%.*]]) #[[ATTR16]] // APPROX-NEXT: br label [[_ZL3YNFIF_EXIT:%.*]] // APPROX: if.then2.i: -// APPROX-NEXT: [[CALL_I20_I:%.*]] = tail call contract float @__ocml_y1_f32(float noundef [[Y]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I20_I:%.*]] = tail call contract noundef float @__ocml_y1_f32(float noundef [[Y]]) #[[ATTR16]] // APPROX-NEXT: br label [[_ZL3YNFIF_EXIT]] // APPROX: if.end4.i: -// APPROX-NEXT: [[CALL_I21_I:%.*]] = tail call contract float @__ocml_y0_f32(float noundef [[Y]]) #[[ATTR16]] -// APPROX-NEXT: [[CALL_I22_I:%.*]] = tail call contract float @__ocml_y1_f32(float noundef [[Y]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I21_I:%.*]] = tail call contract noundef float @__ocml_y0_f32(float noundef [[Y]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I22_I:%.*]] = tail call contract noundef float @__ocml_y1_f32(float noundef [[Y]]) #[[ATTR16]] // APPROX-NEXT: [[CMP723_I:%.*]] = icmp sgt i32 [[X]], 1 // APPROX-NEXT: br i1 [[CMP723_I]], label [[FOR_BODY_I:%.*]], label [[_ZL3YNFIF_EXIT]] // APPROX: for.body.i: @@ -4278,14 +4310,14 @@ extern "C" __device__ float test_ynf(int x, float y) { // DEFAULT-NEXT: i32 1, label [[IF_THEN2_I:%.*]] // DEFAULT-NEXT: ] // DEFAULT: if.then.i: -// DEFAULT-NEXT: [[CALL_I_I:%.*]] = tail call contract double @__ocml_y0_f64(double noundef [[Y:%.*]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I_I:%.*]] = tail call contract noundef double @__ocml_y0_f64(double noundef [[Y:%.*]]) #[[ATTR16]] // DEFAULT-NEXT: br label [[_ZL2YNID_EXIT:%.*]] // DEFAULT: if.then2.i: -// DEFAULT-NEXT: [[CALL_I20_I:%.*]] = tail call contract double @__ocml_y1_f64(double noundef [[Y]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I20_I:%.*]] = tail call contract noundef double @__ocml_y1_f64(double noundef [[Y]]) #[[ATTR16]] // DEFAULT-NEXT: br label [[_ZL2YNID_EXIT]] // DEFAULT: if.end4.i: -// DEFAULT-NEXT: [[CALL_I21_I:%.*]] = tail call contract double @__ocml_y0_f64(double noundef [[Y]]) #[[ATTR16]] -// DEFAULT-NEXT: [[CALL_I22_I:%.*]] = tail call contract double @__ocml_y1_f64(double noundef [[Y]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I21_I:%.*]] = tail call contract noundef double @__ocml_y0_f64(double noundef [[Y]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I22_I:%.*]] = tail call contract noundef double @__ocml_y1_f64(double noundef [[Y]]) #[[ATTR16]] // DEFAULT-NEXT: [[CMP723_I:%.*]] = icmp sgt i32 [[X]], 1 // DEFAULT-NEXT: br i1 [[CMP723_I]], label [[FOR_BODY_I:%.*]], label [[_ZL2YNID_EXIT]] // DEFAULT: for.body.i: @@ -4311,14 +4343,14 @@ extern "C" __device__ float test_ynf(int x, float y) { // FINITEONLY-NEXT: i32 1, label [[IF_THEN2_I:%.*]] // FINITEONLY-NEXT: ] // FINITEONLY: if.then.i: -// FINITEONLY-NEXT: [[CALL_I_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) double @__ocml_y0_f64(double noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_y0_f64(double noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR16]] // FINITEONLY-NEXT: br label [[_ZL2YNID_EXIT:%.*]] // FINITEONLY: if.then2.i: -// FINITEONLY-NEXT: [[CALL_I20_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) double @__ocml_y1_f64(double noundef nofpclass(nan inf) [[Y]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I20_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_y1_f64(double noundef nofpclass(nan inf) [[Y]]) #[[ATTR16]] // FINITEONLY-NEXT: br label [[_ZL2YNID_EXIT]] // FINITEONLY: if.end4.i: -// FINITEONLY-NEXT: [[CALL_I21_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) double @__ocml_y0_f64(double noundef nofpclass(nan inf) [[Y]]) #[[ATTR16]] -// FINITEONLY-NEXT: [[CALL_I22_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) double @__ocml_y1_f64(double noundef nofpclass(nan inf) [[Y]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I21_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_y0_f64(double noundef nofpclass(nan inf) [[Y]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I22_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) double @__ocml_y1_f64(double noundef nofpclass(nan inf) [[Y]]) #[[ATTR16]] // FINITEONLY-NEXT: [[CMP723_I:%.*]] = icmp sgt i32 [[X]], 1 // FINITEONLY-NEXT: br i1 [[CMP723_I]], label [[FOR_BODY_I:%.*]], label [[_ZL2YNID_EXIT]] // FINITEONLY: for.body.i: @@ -4344,14 +4376,14 @@ extern "C" __device__ float test_ynf(int x, float y) { // APPROX-NEXT: i32 1, label [[IF_THEN2_I:%.*]] // APPROX-NEXT: ] // APPROX: if.then.i: -// APPROX-NEXT: [[CALL_I_I:%.*]] = tail call contract double @__ocml_y0_f64(double noundef [[Y:%.*]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I_I:%.*]] = tail call contract noundef double @__ocml_y0_f64(double noundef [[Y:%.*]]) #[[ATTR16]] // APPROX-NEXT: br label [[_ZL2YNID_EXIT:%.*]] // APPROX: if.then2.i: -// APPROX-NEXT: [[CALL_I20_I:%.*]] = tail call contract double @__ocml_y1_f64(double noundef [[Y]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I20_I:%.*]] = tail call contract noundef double @__ocml_y1_f64(double noundef [[Y]]) #[[ATTR16]] // APPROX-NEXT: br label [[_ZL2YNID_EXIT]] // APPROX: if.end4.i: -// APPROX-NEXT: [[CALL_I21_I:%.*]] = tail call contract double @__ocml_y0_f64(double noundef [[Y]]) #[[ATTR16]] -// APPROX-NEXT: [[CALL_I22_I:%.*]] = tail call contract double @__ocml_y1_f64(double noundef [[Y]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I21_I:%.*]] = tail call contract noundef double @__ocml_y0_f64(double noundef [[Y]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I22_I:%.*]] = tail call contract noundef double @__ocml_y1_f64(double noundef [[Y]]) #[[ATTR16]] // APPROX-NEXT: [[CMP723_I:%.*]] = icmp sgt i32 [[X]], 1 // APPROX-NEXT: br i1 [[CMP723_I]], label [[FOR_BODY_I:%.*]], label [[_ZL2YNID_EXIT]] // APPROX: for.body.i: @@ -4376,17 +4408,17 @@ extern "C" __device__ double test_yn(int x, double y) { // DEFAULT-LABEL: @test___cosf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_native_cos_f32(float noundef [[X:%.*]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_native_cos_f32(float noundef [[X:%.*]]) #[[ATTR16]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test___cosf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) float @__ocml_native_cos_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_native_cos_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test___cosf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_native_cos_f32(float noundef [[X:%.*]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_native_cos_f32(float noundef [[X:%.*]]) #[[ATTR16]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test___cosf(float x) { @@ -4396,19 +4428,19 @@ extern "C" __device__ float test___cosf(float x) { // DEFAULT-LABEL: @test___exp10f( // DEFAULT-NEXT: entry: // DEFAULT-NEXT: [[MUL_I:%.*]] = fmul contract float [[X:%.*]], 0x400A934F00000000 -// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract float @llvm.amdgcn.exp2.f32(float [[MUL_I]]) +// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract noundef float @llvm.amdgcn.exp2.f32(float [[MUL_I]]) // DEFAULT-NEXT: ret float [[TMP0]] // // FINITEONLY-LABEL: @test___exp10f( // FINITEONLY-NEXT: entry: // FINITEONLY-NEXT: [[MUL_I:%.*]] = fmul nnan ninf contract float [[X:%.*]], 0x400A934F00000000 -// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract float @llvm.amdgcn.exp2.f32(float [[MUL_I]]) +// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract noundef float @llvm.amdgcn.exp2.f32(float [[MUL_I]]) // FINITEONLY-NEXT: ret float [[TMP0]] // // APPROX-LABEL: @test___exp10f( // APPROX-NEXT: entry: // APPROX-NEXT: [[MUL_I:%.*]] = fmul contract float [[X:%.*]], 0x400A934F00000000 -// APPROX-NEXT: [[TMP0:%.*]] = tail call contract float @llvm.amdgcn.exp2.f32(float [[MUL_I]]) +// APPROX-NEXT: [[TMP0:%.*]] = tail call contract noundef float @llvm.amdgcn.exp2.f32(float [[MUL_I]]) // APPROX-NEXT: ret float [[TMP0]] // extern "C" __device__ float test___exp10f(float x) { @@ -4418,19 +4450,19 @@ extern "C" __device__ float test___exp10f(float x) { // DEFAULT-LABEL: @test___expf( // DEFAULT-NEXT: entry: // DEFAULT-NEXT: [[MUL_I:%.*]] = fmul contract float [[X:%.*]], 0x3FF7154760000000 -// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract float @llvm.amdgcn.exp2.f32(float [[MUL_I]]) +// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract noundef float @llvm.amdgcn.exp2.f32(float [[MUL_I]]) // DEFAULT-NEXT: ret float [[TMP0]] // // FINITEONLY-LABEL: @test___expf( // FINITEONLY-NEXT: entry: // FINITEONLY-NEXT: [[MUL_I:%.*]] = fmul nnan ninf contract float [[X:%.*]], 0x3FF7154760000000 -// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract float @llvm.amdgcn.exp2.f32(float [[MUL_I]]) +// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract noundef float @llvm.amdgcn.exp2.f32(float [[MUL_I]]) // FINITEONLY-NEXT: ret float [[TMP0]] // // APPROX-LABEL: @test___expf( // APPROX-NEXT: entry: // APPROX-NEXT: [[MUL_I:%.*]] = fmul contract float [[X:%.*]], 0x3FF7154760000000 -// APPROX-NEXT: [[TMP0:%.*]] = tail call contract float @llvm.amdgcn.exp2.f32(float [[MUL_I]]) +// APPROX-NEXT: [[TMP0:%.*]] = tail call contract noundef float @llvm.amdgcn.exp2.f32(float [[MUL_I]]) // APPROX-NEXT: ret float [[TMP0]] // extern "C" __device__ float test___expf(float x) { @@ -4477,17 +4509,17 @@ extern "C" __device__ float test___fdividef(float x, float y) { // DEFAULT-LABEL: @test__fmaf_rn( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract float @llvm.fma.f32(float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]]) +// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract noundef float @llvm.fma.f32(float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]]) // DEFAULT-NEXT: ret float [[TMP0]] // // FINITEONLY-LABEL: @test__fmaf_rn( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract float @llvm.fma.f32(float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]]) +// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract noundef float @llvm.fma.f32(float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]]) // FINITEONLY-NEXT: ret float [[TMP0]] // // APPROX-LABEL: @test__fmaf_rn( // APPROX-NEXT: entry: -// APPROX-NEXT: [[TMP0:%.*]] = tail call contract float @llvm.fma.f32(float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]]) +// APPROX-NEXT: [[TMP0:%.*]] = tail call contract noundef float @llvm.fma.f32(float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]]) // APPROX-NEXT: ret float [[TMP0]] // extern "C" __device__ float test__fmaf_rn(float x, float y, float z) { @@ -4534,17 +4566,17 @@ extern "C" __device__ float test___frcp_rn(float x) { // DEFAULT-LABEL: @test___frsqrt_rn( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract float @llvm.amdgcn.rsq.f32(float [[X:%.*]]) +// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract noundef float @llvm.amdgcn.rsq.f32(float [[X:%.*]]) // DEFAULT-NEXT: ret float [[TMP0]] // // FINITEONLY-LABEL: @test___frsqrt_rn( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract float @llvm.amdgcn.rsq.f32(float [[X:%.*]]) +// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract noundef float @llvm.amdgcn.rsq.f32(float [[X:%.*]]) // FINITEONLY-NEXT: ret float [[TMP0]] // // APPROX-LABEL: @test___frsqrt_rn( // APPROX-NEXT: entry: -// APPROX-NEXT: [[TMP0:%.*]] = tail call contract float @llvm.amdgcn.rsq.f32(float [[X:%.*]]) +// APPROX-NEXT: [[TMP0:%.*]] = tail call contract noundef float @llvm.amdgcn.rsq.f32(float [[X:%.*]]) // APPROX-NEXT: ret float [[TMP0]] // extern "C" __device__ float test___frsqrt_rn(float x) { @@ -4553,17 +4585,17 @@ extern "C" __device__ float test___frsqrt_rn(float x) { // DEFAULT-LABEL: @test___fsqrt_rn( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_native_sqrt_f32(float noundef [[X:%.*]]) #[[ATTR14]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_native_sqrt_f32(float noundef [[X:%.*]]) #[[ATTR14]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test___fsqrt_rn( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) float @__ocml_native_sqrt_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR14]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_native_sqrt_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR14]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test___fsqrt_rn( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_native_sqrt_f32(float noundef [[X:%.*]]) #[[ATTR14]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_native_sqrt_f32(float noundef [[X:%.*]]) #[[ATTR14]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test___fsqrt_rn(float x) { @@ -4591,17 +4623,17 @@ extern "C" __device__ float test___fsub_rn(float x, float y) { // DEFAULT-LABEL: @test___log10f( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract float @llvm.log10.f32(float [[X:%.*]]) +// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract noundef float @llvm.log10.f32(float [[X:%.*]]) // DEFAULT-NEXT: ret float [[TMP0]] // // FINITEONLY-LABEL: @test___log10f( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract float @llvm.log10.f32(float [[X:%.*]]) +// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract noundef float @llvm.log10.f32(float [[X:%.*]]) // FINITEONLY-NEXT: ret float [[TMP0]] // // APPROX-LABEL: @test___log10f( // APPROX-NEXT: entry: -// APPROX-NEXT: [[TMP0:%.*]] = tail call contract float @llvm.log10.f32(float [[X:%.*]]) +// APPROX-NEXT: [[TMP0:%.*]] = tail call contract noundef float @llvm.log10.f32(float [[X:%.*]]) // APPROX-NEXT: ret float [[TMP0]] // extern "C" __device__ float test___log10f(float x) { @@ -4610,17 +4642,17 @@ extern "C" __device__ float test___log10f(float x) { // DEFAULT-LABEL: @test___log2f( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract float @llvm.amdgcn.log.f32(float [[X:%.*]]) +// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract noundef float @llvm.amdgcn.log.f32(float [[X:%.*]]) // DEFAULT-NEXT: ret float [[TMP0]] // // FINITEONLY-LABEL: @test___log2f( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract float @llvm.amdgcn.log.f32(float [[X:%.*]]) +// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract noundef float @llvm.amdgcn.log.f32(float [[X:%.*]]) // FINITEONLY-NEXT: ret float [[TMP0]] // // APPROX-LABEL: @test___log2f( // APPROX-NEXT: entry: -// APPROX-NEXT: [[TMP0:%.*]] = tail call contract float @llvm.amdgcn.log.f32(float [[X:%.*]]) +// APPROX-NEXT: [[TMP0:%.*]] = tail call contract noundef float @llvm.amdgcn.log.f32(float [[X:%.*]]) // APPROX-NEXT: ret float [[TMP0]] // extern "C" __device__ float test___log2f(float x) { @@ -4629,17 +4661,17 @@ extern "C" __device__ float test___log2f(float x) { // DEFAULT-LABEL: @test___logf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract float @llvm.log.f32(float [[X:%.*]]) +// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract noundef float @llvm.log.f32(float [[X:%.*]]) // DEFAULT-NEXT: ret float [[TMP0]] // // FINITEONLY-LABEL: @test___logf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract float @llvm.log.f32(float [[X:%.*]]) +// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract noundef float @llvm.log.f32(float [[X:%.*]]) // FINITEONLY-NEXT: ret float [[TMP0]] // // APPROX-LABEL: @test___logf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[TMP0:%.*]] = tail call contract float @llvm.log.f32(float [[X:%.*]]) +// APPROX-NEXT: [[TMP0:%.*]] = tail call contract noundef float @llvm.log.f32(float [[X:%.*]]) // APPROX-NEXT: ret float [[TMP0]] // extern "C" __device__ float test___logf(float x) { @@ -4648,17 +4680,17 @@ extern "C" __device__ float test___logf(float x) { // DEFAULT-LABEL: @test___powf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_pow_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR15]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_pow_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR15]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test___powf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) float @__ocml_pow_f32(float noundef nofpclass(nan inf) [[X:%.*]], float noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR15]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_pow_f32(float noundef nofpclass(nan inf) [[X:%.*]], float noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR15]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test___powf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_pow_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR15]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_pow_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR15]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test___powf(float x, float y) { @@ -4723,17 +4755,17 @@ extern "C" __device__ void test___sincosf(float x, float *y, float *z) { // DEFAULT-LABEL: @test___sinf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_native_sin_f32(float noundef [[X:%.*]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_native_sin_f32(float noundef [[X:%.*]]) #[[ATTR16]] // DEFAULT-NEXT: ret float [[CALL_I]] // // FINITEONLY-LABEL: @test___sinf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) float @__ocml_native_sin_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_native_sin_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] // FINITEONLY-NEXT: ret float [[CALL_I]] // // APPROX-LABEL: @test___sinf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_native_sin_f32(float noundef [[X:%.*]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_native_sin_f32(float noundef [[X:%.*]]) #[[ATTR16]] // APPROX-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test___sinf(float x) { @@ -4742,24 +4774,24 @@ extern "C" __device__ float test___sinf(float x) { // DEFAULT-LABEL: @test___tanf( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[CALL_I_I:%.*]] = tail call contract float @__ocml_native_sin_f32(float noundef [[X:%.*]]) #[[ATTR16]] -// DEFAULT-NEXT: [[CALL_I3_I:%.*]] = tail call contract float @__ocml_native_cos_f32(float noundef [[X]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I_I:%.*]] = tail call contract noundef float @__ocml_native_sin_f32(float noundef [[X:%.*]]) #[[ATTR16]] +// DEFAULT-NEXT: [[CALL_I3_I:%.*]] = tail call contract noundef float @__ocml_native_cos_f32(float noundef [[X]]) #[[ATTR16]] // DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract float @llvm.amdgcn.rcp.f32(float [[CALL_I3_I]]) // DEFAULT-NEXT: [[MUL_I:%.*]] = fmul contract float [[CALL_I_I]], [[TMP0]] // DEFAULT-NEXT: ret float [[MUL_I]] // // FINITEONLY-LABEL: @test___tanf( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[CALL_I_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) float @__ocml_native_sin_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] -// FINITEONLY-NEXT: [[CALL_I3_I:%.*]] = tail call nnan ninf contract nofpclass(nan inf) float @__ocml_native_cos_f32(float noundef nofpclass(nan inf) [[X]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_native_sin_f32(float noundef nofpclass(nan inf) [[X:%.*]]) #[[ATTR16]] +// FINITEONLY-NEXT: [[CALL_I3_I:%.*]] = tail call nnan ninf contract noundef nofpclass(nan inf) float @__ocml_native_cos_f32(float noundef nofpclass(nan inf) [[X]]) #[[ATTR16]] // FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract float @llvm.amdgcn.rcp.f32(float [[CALL_I3_I]]) // FINITEONLY-NEXT: [[MUL_I:%.*]] = fmul nnan ninf contract float [[CALL_I_I]], [[TMP0]] // FINITEONLY-NEXT: ret float [[MUL_I]] // // APPROX-LABEL: @test___tanf( // APPROX-NEXT: entry: -// APPROX-NEXT: [[CALL_I_I:%.*]] = tail call contract float @__ocml_native_sin_f32(float noundef [[X:%.*]]) #[[ATTR16]] -// APPROX-NEXT: [[CALL_I3_I:%.*]] = tail call contract float @__ocml_native_cos_f32(float noundef [[X]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I_I:%.*]] = tail call contract noundef float @__ocml_native_sin_f32(float noundef [[X:%.*]]) #[[ATTR16]] +// APPROX-NEXT: [[CALL_I3_I:%.*]] = tail call contract noundef float @__ocml_native_cos_f32(float noundef [[X]]) #[[ATTR16]] // APPROX-NEXT: [[TMP0:%.*]] = tail call contract float @llvm.amdgcn.rcp.f32(float [[CALL_I3_I]]) // APPROX-NEXT: [[MUL_I:%.*]] = fmul contract float [[CALL_I_I]], [[TMP0]] // APPROX-NEXT: ret float [[MUL_I]] @@ -4846,17 +4878,17 @@ extern "C" __device__ double test___drcp_rn(double x) { // DEFAULT-LABEL: @test___dsqrt_rn( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract double @llvm.sqrt.f64(double [[X:%.*]]) +// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract noundef double @llvm.sqrt.f64(double [[X:%.*]]) // DEFAULT-NEXT: ret double [[TMP0]] // // FINITEONLY-LABEL: @test___dsqrt_rn( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract double @llvm.sqrt.f64(double [[X:%.*]]) +// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract noundef double @llvm.sqrt.f64(double [[X:%.*]]) // FINITEONLY-NEXT: ret double [[TMP0]] // // APPROX-LABEL: @test___dsqrt_rn( // APPROX-NEXT: entry: -// APPROX-NEXT: [[TMP0:%.*]] = tail call contract double @llvm.sqrt.f64(double [[X:%.*]]) +// APPROX-NEXT: [[TMP0:%.*]] = tail call contract noundef double @llvm.sqrt.f64(double [[X:%.*]]) // APPROX-NEXT: ret double [[TMP0]] // extern "C" __device__ double test___dsqrt_rn(double x) { @@ -4865,17 +4897,17 @@ extern "C" __device__ double test___dsqrt_rn(double x) { // DEFAULT-LABEL: @test__fma_rn( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract double @llvm.fma.f64(double [[X:%.*]], double [[Y:%.*]], double [[Z:%.*]]) +// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract noundef double @llvm.fma.f64(double [[X:%.*]], double [[Y:%.*]], double [[Z:%.*]]) // DEFAULT-NEXT: ret double [[TMP0]] // // FINITEONLY-LABEL: @test__fma_rn( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract double @llvm.fma.f64(double [[X:%.*]], double [[Y:%.*]], double [[Z:%.*]]) +// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract noundef double @llvm.fma.f64(double [[X:%.*]], double [[Y:%.*]], double [[Z:%.*]]) // FINITEONLY-NEXT: ret double [[TMP0]] // // APPROX-LABEL: @test__fma_rn( // APPROX-NEXT: entry: -// APPROX-NEXT: [[TMP0:%.*]] = tail call contract double @llvm.fma.f64(double [[X:%.*]], double [[Y:%.*]], double [[Z:%.*]]) +// APPROX-NEXT: [[TMP0:%.*]] = tail call contract noundef double @llvm.fma.f64(double [[X:%.*]], double [[Y:%.*]], double [[Z:%.*]]) // APPROX-NEXT: ret double [[TMP0]] // extern "C" __device__ double test__fma_rn(double x, double y, double z) { @@ -4884,17 +4916,17 @@ extern "C" __device__ double test__fma_rn(double x, double y, double z) { // DEFAULT-LABEL: @test_float_min( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]]) +// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract noundef float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]]) // DEFAULT-NEXT: ret float [[TMP0]] // // FINITEONLY-LABEL: @test_float_min( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]]) +// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract noundef float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]]) // FINITEONLY-NEXT: ret float [[TMP0]] // // APPROX-LABEL: @test_float_min( // APPROX-NEXT: entry: -// APPROX-NEXT: [[TMP0:%.*]] = tail call contract float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]]) +// APPROX-NEXT: [[TMP0:%.*]] = tail call contract noundef float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]]) // APPROX-NEXT: ret float [[TMP0]] // extern "C" __device__ float test_float_min(float x, float y) { @@ -4903,17 +4935,17 @@ extern "C" __device__ float test_float_min(float x, float y) { // DEFAULT-LABEL: @test_float_max( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]]) +// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract noundef float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]]) // DEFAULT-NEXT: ret float [[TMP0]] // // FINITEONLY-LABEL: @test_float_max( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]]) +// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract noundef float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]]) // FINITEONLY-NEXT: ret float [[TMP0]] // // APPROX-LABEL: @test_float_max( // APPROX-NEXT: entry: -// APPROX-NEXT: [[TMP0:%.*]] = tail call contract float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]]) +// APPROX-NEXT: [[TMP0:%.*]] = tail call contract noundef float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]]) // APPROX-NEXT: ret float [[TMP0]] // extern "C" __device__ float test_float_max(float x, float y) { @@ -4922,17 +4954,17 @@ extern "C" __device__ float test_float_max(float x, float y) { // DEFAULT-LABEL: @test_double_min( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract double @llvm.minnum.f64(double [[X:%.*]], double [[Y:%.*]]) +// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract noundef double @llvm.minnum.f64(double [[X:%.*]], double [[Y:%.*]]) // DEFAULT-NEXT: ret double [[TMP0]] // // FINITEONLY-LABEL: @test_double_min( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract double @llvm.minnum.f64(double [[X:%.*]], double [[Y:%.*]]) +// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract noundef double @llvm.minnum.f64(double [[X:%.*]], double [[Y:%.*]]) // FINITEONLY-NEXT: ret double [[TMP0]] // // APPROX-LABEL: @test_double_min( // APPROX-NEXT: entry: -// APPROX-NEXT: [[TMP0:%.*]] = tail call contract double @llvm.minnum.f64(double [[X:%.*]], double [[Y:%.*]]) +// APPROX-NEXT: [[TMP0:%.*]] = tail call contract noundef double @llvm.minnum.f64(double [[X:%.*]], double [[Y:%.*]]) // APPROX-NEXT: ret double [[TMP0]] // extern "C" __device__ double test_double_min(double x, double y) { @@ -4941,17 +4973,17 @@ extern "C" __device__ double test_double_min(double x, double y) { // DEFAULT-LABEL: @test_double_max( // DEFAULT-NEXT: entry: -// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract double @llvm.maxnum.f64(double [[X:%.*]], double [[Y:%.*]]) +// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract noundef double @llvm.maxnum.f64(double [[X:%.*]], double [[Y:%.*]]) // DEFAULT-NEXT: ret double [[TMP0]] // // FINITEONLY-LABEL: @test_double_max( // FINITEONLY-NEXT: entry: -// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract double @llvm.maxnum.f64(double [[X:%.*]], double [[Y:%.*]]) +// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract noundef double @llvm.maxnum.f64(double [[X:%.*]], double [[Y:%.*]]) // FINITEONLY-NEXT: ret double [[TMP0]] // // APPROX-LABEL: @test_double_max( // APPROX-NEXT: entry: -// APPROX-NEXT: [[TMP0:%.*]] = tail call contract double @llvm.maxnum.f64(double [[X:%.*]], double [[Y:%.*]]) +// APPROX-NEXT: [[TMP0:%.*]] = tail call contract noundef double @llvm.maxnum.f64(double [[X:%.*]], double [[Y:%.*]]) // APPROX-NEXT: ret double [[TMP0]] // extern "C" __device__ double test_double_max(double x, double y) { @@ -4959,7 +4991,7 @@ extern "C" __device__ double test_double_max(double x, double y) { } // CHECK-LABEL: @test_int_min( // CHECK-NEXT: entry: -// CHECK-NEXT: [[COND_I:%.*]] = tail call i32 @llvm.smin.i32(i32 [[X:%.*]], i32 [[Y:%.*]]) +// CHECK-NEXT: [[COND_I:%.*]] = tail call noundef i32 @llvm.smin.i32(i32 [[X:%.*]], i32 [[Y:%.*]]) // CHECK-NEXT: ret i32 [[COND_I]] // extern "C" __device__ int test_int_min(int x, int y) { @@ -4968,7 +5000,7 @@ extern "C" __device__ int test_int_min(int x, int y) { // CHECK-LABEL: @test_int_max( // CHECK-NEXT: entry: -// CHECK-NEXT: [[COND_I:%.*]] = tail call i32 @llvm.smax.i32(i32 [[X:%.*]], i32 [[Y:%.*]]) +// CHECK-NEXT: [[COND_I:%.*]] = tail call noundef i32 @llvm.smax.i32(i32 [[X:%.*]], i32 [[Y:%.*]]) // CHECK-NEXT: ret i32 [[COND_I]] // extern "C" __device__ int test_int_max(int x, int y) { diff --git a/clang/test/Headers/__clang_hip_math_ocml_rounded_ops.hip b/clang/test/Headers/__clang_hip_math_ocml_rounded_ops.hip index 422b5fb56c4d40..9e30c2c9c2ccbb 100644 --- a/clang/test/Headers/__clang_hip_math_ocml_rounded_ops.hip +++ b/clang/test/Headers/__clang_hip_math_ocml_rounded_ops.hip @@ -9,7 +9,7 @@ // CHECK-LABEL: @test___fadd_rd( // CHECK-NEXT: entry: -// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_add_rtn_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR3:[0-9]+]] +// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_add_rtn_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR3:[0-9]+]] // CHECK-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test___fadd_rd(float x, float y) { @@ -18,7 +18,7 @@ extern "C" __device__ float test___fadd_rd(float x, float y) { // CHECK-LABEL: @test___fadd_rn( // CHECK-NEXT: entry: -// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_add_rte_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR3]] +// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_add_rte_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR3]] // CHECK-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test___fadd_rn(float x, float y) { @@ -27,7 +27,7 @@ extern "C" __device__ float test___fadd_rn(float x, float y) { // CHECK-LABEL: @test___fadd_ru( // CHECK-NEXT: entry: -// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_add_rtp_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR3]] +// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_add_rtp_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR3]] // CHECK-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test___fadd_ru(float x, float y) { @@ -36,7 +36,7 @@ extern "C" __device__ float test___fadd_ru(float x, float y) { // CHECK-LABEL: @test___fadd_rz( // CHECK-NEXT: entry: -// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_add_rtz_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR3]] +// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_add_rtz_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR3]] // CHECK-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test___fadd_rz(float x, float y) { @@ -45,7 +45,7 @@ extern "C" __device__ float test___fadd_rz(float x, float y) { // CHECK-LABEL: @test__fmaf_rd( // CHECK-NEXT: entry: -// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_fma_rtn_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]], float noundef [[Z:%.*]]) #[[ATTR3]] +// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_fma_rtn_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]], float noundef [[Z:%.*]]) #[[ATTR3]] // CHECK-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test__fmaf_rd(float x, float y, float z) { @@ -54,7 +54,7 @@ extern "C" __device__ float test__fmaf_rd(float x, float y, float z) { // CHECK-LABEL: @test__fmaf_rn( // CHECK-NEXT: entry: -// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_fma_rte_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]], float noundef [[Z:%.*]]) #[[ATTR3]] +// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_fma_rte_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]], float noundef [[Z:%.*]]) #[[ATTR3]] // CHECK-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test__fmaf_rn(float x, float y, float z) { @@ -63,7 +63,7 @@ extern "C" __device__ float test__fmaf_rn(float x, float y, float z) { // CHECK-LABEL: @test__fmaf_ru( // CHECK-NEXT: entry: -// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_fma_rtp_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]], float noundef [[Z:%.*]]) #[[ATTR3]] +// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_fma_rtp_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]], float noundef [[Z:%.*]]) #[[ATTR3]] // CHECK-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test__fmaf_ru(float x, float y, float z) { @@ -72,7 +72,7 @@ extern "C" __device__ float test__fmaf_ru(float x, float y, float z) { // CHECK-LABEL: @test__fmaf_rz( // CHECK-NEXT: entry: -// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_fma_rtz_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]], float noundef [[Z:%.*]]) #[[ATTR3]] +// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_fma_rtz_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]], float noundef [[Z:%.*]]) #[[ATTR3]] // CHECK-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test__fmaf_rz(float x, float y, float z) { @@ -81,7 +81,7 @@ extern "C" __device__ float test__fmaf_rz(float x, float y, float z) { // CHECK-LABEL: @test___fmul_rd( // CHECK-NEXT: entry: -// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_mul_rtn_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR3]] +// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_mul_rtn_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR3]] // CHECK-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test___fmul_rd(float x, float y) { @@ -90,7 +90,7 @@ extern "C" __device__ float test___fmul_rd(float x, float y) { // CHECK-LABEL: @test___fmul_rn( // CHECK-NEXT: entry: -// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_mul_rte_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR3]] +// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_mul_rte_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR3]] // CHECK-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test___fmul_rn(float x, float y) { @@ -99,7 +99,7 @@ extern "C" __device__ float test___fmul_rn(float x, float y) { // CHECK-LABEL: @test___fmul_ru( // CHECK-NEXT: entry: -// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_mul_rtp_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR3]] +// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_mul_rtp_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR3]] // CHECK-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test___fmul_ru(float x, float y) { @@ -108,7 +108,7 @@ extern "C" __device__ float test___fmul_ru(float x, float y) { // CHECK-LABEL: @test___fmul_rz( // CHECK-NEXT: entry: -// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_mul_rtz_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR3]] +// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_mul_rtz_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR3]] // CHECK-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test___fmul_rz(float x, float y) { @@ -117,7 +117,7 @@ extern "C" __device__ float test___fmul_rz(float x, float y) { // CHECK-LABEL: @test___frcp_rd( // CHECK-NEXT: entry: -// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_div_rtn_f32(float noundef 1.000000e+00, float noundef [[X:%.*]]) #[[ATTR3]] +// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_div_rtn_f32(float noundef 1.000000e+00, float noundef [[X:%.*]]) #[[ATTR3]] // CHECK-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test___frcp_rd(float x) { @@ -126,7 +126,7 @@ extern "C" __device__ float test___frcp_rd(float x) { // CHECK-LABEL: @test___frcp_rn( // CHECK-NEXT: entry: -// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_div_rte_f32(float noundef 1.000000e+00, float noundef [[X:%.*]]) #[[ATTR3]] +// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_div_rte_f32(float noundef 1.000000e+00, float noundef [[X:%.*]]) #[[ATTR3]] // CHECK-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test___frcp_rn(float x) { @@ -135,7 +135,7 @@ extern "C" __device__ float test___frcp_rn(float x) { // CHECK-LABEL: @test___frcp_ru( // CHECK-NEXT: entry: -// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_div_rtp_f32(float noundef 1.000000e+00, float noundef [[X:%.*]]) #[[ATTR3]] +// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_div_rtp_f32(float noundef 1.000000e+00, float noundef [[X:%.*]]) #[[ATTR3]] // CHECK-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test___frcp_ru(float x) { @@ -144,7 +144,7 @@ extern "C" __device__ float test___frcp_ru(float x) { // CHECK-LABEL: @test___frcp_rz( // CHECK-NEXT: entry: -// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_div_rtz_f32(float noundef 1.000000e+00, float noundef [[X:%.*]]) #[[ATTR3]] +// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_div_rtz_f32(float noundef 1.000000e+00, float noundef [[X:%.*]]) #[[ATTR3]] // CHECK-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test___frcp_rz(float x) { @@ -153,7 +153,7 @@ extern "C" __device__ float test___frcp_rz(float x) { // CHECK-LABEL: @test___fsqrt_rd( // CHECK-NEXT: entry: -// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_sqrt_rtn_f32(float noundef [[X:%.*]]) #[[ATTR3]] +// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_sqrt_rtn_f32(float noundef [[X:%.*]]) #[[ATTR3]] // CHECK-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test___fsqrt_rd(float x) { @@ -162,7 +162,7 @@ extern "C" __device__ float test___fsqrt_rd(float x) { // CHECK-LABEL: @test___fsqrt_rn( // CHECK-NEXT: entry: -// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_sqrt_rte_f32(float noundef [[X:%.*]]) #[[ATTR3]] +// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_sqrt_rte_f32(float noundef [[X:%.*]]) #[[ATTR3]] // CHECK-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test___fsqrt_rn(float x) { @@ -171,7 +171,7 @@ extern "C" __device__ float test___fsqrt_rn(float x) { // CHECK-LABEL: @test___fsqrt_ru( // CHECK-NEXT: entry: -// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_sqrt_rtp_f32(float noundef [[X:%.*]]) #[[ATTR3]] +// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_sqrt_rtp_f32(float noundef [[X:%.*]]) #[[ATTR3]] // CHECK-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test___fsqrt_ru(float x) { @@ -180,7 +180,7 @@ extern "C" __device__ float test___fsqrt_ru(float x) { // CHECK-LABEL: @test___fsqrt_rz( // CHECK-NEXT: entry: -// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_sqrt_rtz_f32(float noundef [[X:%.*]]) #[[ATTR3]] +// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_sqrt_rtz_f32(float noundef [[X:%.*]]) #[[ATTR3]] // CHECK-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test___fsqrt_rz(float x) { @@ -189,7 +189,7 @@ extern "C" __device__ float test___fsqrt_rz(float x) { // CHECK-LABEL: @test___fsub_rd( // CHECK-NEXT: entry: -// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_sub_rtn_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR3]] +// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_sub_rtn_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR3]] // CHECK-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test___fsub_rd(float x, float y) { @@ -198,7 +198,7 @@ extern "C" __device__ float test___fsub_rd(float x, float y) { // CHECK-LABEL: @test___fsub_rn( // CHECK-NEXT: entry: -// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_sub_rte_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR3]] +// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_sub_rte_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR3]] // CHECK-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test___fsub_rn(float x, float y) { @@ -207,7 +207,7 @@ extern "C" __device__ float test___fsub_rn(float x, float y) { // CHECK-LABEL: @test___fsub_ru( // CHECK-NEXT: entry: -// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_sub_rtp_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR3]] +// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_sub_rtp_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR3]] // CHECK-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test___fsub_ru(float x, float y) { @@ -216,7 +216,7 @@ extern "C" __device__ float test___fsub_ru(float x, float y) { // CHECK-LABEL: @test___fsub_rz( // CHECK-NEXT: entry: -// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract float @__ocml_sub_rtz_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR3]] +// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_sub_rtz_f32(float noundef [[X:%.*]], float noundef [[Y:%.*]]) #[[ATTR3]] // CHECK-NEXT: ret float [[CALL_I]] // extern "C" __device__ float test___fsub_rz(float x, float y) { @@ -225,7 +225,7 @@ extern "C" __device__ float test___fsub_rz(float x, float y) { // CHECK-LABEL: @test___dadd_rd( // CHECK-NEXT: entry: -// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_add_rtn_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR3]] +// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_add_rtn_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR3]] // CHECK-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test___dadd_rd(double x, double y) { @@ -234,7 +234,7 @@ extern "C" __device__ double test___dadd_rd(double x, double y) { // CHECK-LABEL: @test___dadd_rn( // CHECK-NEXT: entry: -// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_add_rte_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR3]] +// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_add_rte_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR3]] // CHECK-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test___dadd_rn(double x, double y) { @@ -243,7 +243,7 @@ extern "C" __device__ double test___dadd_rn(double x, double y) { // CHECK-LABEL: @test___dadd_ru( // CHECK-NEXT: entry: -// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_add_rtp_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR3]] +// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_add_rtp_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR3]] // CHECK-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test___dadd_ru(double x, double y) { @@ -252,7 +252,7 @@ extern "C" __device__ double test___dadd_ru(double x, double y) { // CHECK-LABEL: @test___dadd_rz( // CHECK-NEXT: entry: -// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_add_rtz_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR3]] +// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_add_rtz_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR3]] // CHECK-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test___dadd_rz(double x, double y) { @@ -261,7 +261,7 @@ extern "C" __device__ double test___dadd_rz(double x, double y) { // CHECK-LABEL: @test___dmul_rd( // CHECK-NEXT: entry: -// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_mul_rtn_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR3]] +// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_mul_rtn_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR3]] // CHECK-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test___dmul_rd(double x, double y) { @@ -270,7 +270,7 @@ extern "C" __device__ double test___dmul_rd(double x, double y) { // CHECK-LABEL: @test___dmul_rn( // CHECK-NEXT: entry: -// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_mul_rte_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR3]] +// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_mul_rte_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR3]] // CHECK-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test___dmul_rn(double x, double y) { @@ -279,7 +279,7 @@ extern "C" __device__ double test___dmul_rn(double x, double y) { // CHECK-LABEL: @test___dmul_ru( // CHECK-NEXT: entry: -// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_mul_rtp_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR3]] +// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_mul_rtp_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR3]] // CHECK-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test___dmul_ru(double x, double y) { @@ -288,7 +288,7 @@ extern "C" __device__ double test___dmul_ru(double x, double y) { // CHECK-LABEL: @test___dmul_rz( // CHECK-NEXT: entry: -// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_mul_rtz_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR3]] +// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_mul_rtz_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]]) #[[ATTR3]] // CHECK-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test___dmul_rz(double x, double y) { @@ -298,7 +298,7 @@ extern "C" __device__ double test___dmul_rz(double x, double y) { // CHECK-LABEL: @test___drcp_rd( // CHECK-NEXT: entry: // CHECK-NEXT: [[CONV:%.*]] = fpext float [[X:%.*]] to double -// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_div_rtn_f64(double noundef 1.000000e+00, double noundef [[CONV]]) #[[ATTR3]] +// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_div_rtn_f64(double noundef 1.000000e+00, double noundef [[CONV]]) #[[ATTR3]] // CHECK-NEXT: [[CONV1:%.*]] = fptrunc double [[CALL_I]] to float // CHECK-NEXT: ret float [[CONV1]] // @@ -309,7 +309,7 @@ extern "C" __device__ float test___drcp_rd(float x) { // CHECK-LABEL: @test___drcp_rn( // CHECK-NEXT: entry: // CHECK-NEXT: [[CONV:%.*]] = fpext float [[X:%.*]] to double -// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_div_rte_f64(double noundef 1.000000e+00, double noundef [[CONV]]) #[[ATTR3]] +// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_div_rte_f64(double noundef 1.000000e+00, double noundef [[CONV]]) #[[ATTR3]] // CHECK-NEXT: [[CONV1:%.*]] = fptrunc double [[CALL_I]] to float // CHECK-NEXT: ret float [[CONV1]] // @@ -320,7 +320,7 @@ extern "C" __device__ float test___drcp_rn(float x) { // CHECK-LABEL: @test___drcp_ru( // CHECK-NEXT: entry: // CHECK-NEXT: [[CONV:%.*]] = fpext float [[X:%.*]] to double -// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_div_rtp_f64(double noundef 1.000000e+00, double noundef [[CONV]]) #[[ATTR3]] +// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_div_rtp_f64(double noundef 1.000000e+00, double noundef [[CONV]]) #[[ATTR3]] // CHECK-NEXT: [[CONV1:%.*]] = fptrunc double [[CALL_I]] to float // CHECK-NEXT: ret float [[CONV1]] // @@ -331,7 +331,7 @@ extern "C" __device__ float test___drcp_ru(float x) { // CHECK-LABEL: @test___drcp_rz( // CHECK-NEXT: entry: // CHECK-NEXT: [[CONV:%.*]] = fpext float [[X:%.*]] to double -// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_div_rtz_f64(double noundef 1.000000e+00, double noundef [[CONV]]) #[[ATTR3]] +// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_div_rtz_f64(double noundef 1.000000e+00, double noundef [[CONV]]) #[[ATTR3]] // CHECK-NEXT: [[CONV1:%.*]] = fptrunc double [[CALL_I]] to float // CHECK-NEXT: ret float [[CONV1]] // @@ -342,7 +342,7 @@ extern "C" __device__ float test___drcp_rz(float x) { // CHECK-LABEL: @test___dsqrt_rd( // CHECK-NEXT: entry: // CHECK-NEXT: [[CONV:%.*]] = fpext float [[X:%.*]] to double -// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_sqrt_rtn_f64(double noundef [[CONV]]) #[[ATTR3]] +// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_sqrt_rtn_f64(double noundef [[CONV]]) #[[ATTR3]] // CHECK-NEXT: [[CONV1:%.*]] = fptrunc double [[CALL_I]] to float // CHECK-NEXT: ret float [[CONV1]] // @@ -353,7 +353,7 @@ extern "C" __device__ float test___dsqrt_rd(float x) { // CHECK-LABEL: @test___dsqrt_rn( // CHECK-NEXT: entry: // CHECK-NEXT: [[CONV:%.*]] = fpext float [[X:%.*]] to double -// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_sqrt_rte_f64(double noundef [[CONV]]) #[[ATTR3]] +// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_sqrt_rte_f64(double noundef [[CONV]]) #[[ATTR3]] // CHECK-NEXT: [[CONV1:%.*]] = fptrunc double [[CALL_I]] to float // CHECK-NEXT: ret float [[CONV1]] // @@ -364,7 +364,7 @@ extern "C" __device__ float test___dsqrt_rn(float x) { // CHECK-LABEL: @test___dsqrt_ru( // CHECK-NEXT: entry: // CHECK-NEXT: [[CONV:%.*]] = fpext float [[X:%.*]] to double -// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_sqrt_rtp_f64(double noundef [[CONV]]) #[[ATTR3]] +// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_sqrt_rtp_f64(double noundef [[CONV]]) #[[ATTR3]] // CHECK-NEXT: [[CONV1:%.*]] = fptrunc double [[CALL_I]] to float // CHECK-NEXT: ret float [[CONV1]] // @@ -375,7 +375,7 @@ extern "C" __device__ float test___dsqrt_ru(float x) { // CHECK-LABEL: @test___dsqrt_rz( // CHECK-NEXT: entry: // CHECK-NEXT: [[CONV:%.*]] = fpext float [[X:%.*]] to double -// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_sqrt_rtz_f64(double noundef [[CONV]]) #[[ATTR3]] +// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_sqrt_rtz_f64(double noundef [[CONV]]) #[[ATTR3]] // CHECK-NEXT: [[CONV1:%.*]] = fptrunc double [[CALL_I]] to float // CHECK-NEXT: ret float [[CONV1]] // @@ -385,7 +385,7 @@ extern "C" __device__ float test___dsqrt_rz(float x) { // CHECK-LABEL: @test__fma_rd( // CHECK-NEXT: entry: -// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_fma_rtn_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]], double noundef [[Z:%.*]]) #[[ATTR3]] +// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_fma_rtn_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]], double noundef [[Z:%.*]]) #[[ATTR3]] // CHECK-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test__fma_rd(double x, double y, double z) { @@ -394,7 +394,7 @@ extern "C" __device__ double test__fma_rd(double x, double y, double z) { // CHECK-LABEL: @test__fma_rn( // CHECK-NEXT: entry: -// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_fma_rte_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]], double noundef [[Z:%.*]]) #[[ATTR3]] +// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_fma_rte_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]], double noundef [[Z:%.*]]) #[[ATTR3]] // CHECK-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test__fma_rn(double x, double y, double z) { @@ -403,7 +403,7 @@ extern "C" __device__ double test__fma_rn(double x, double y, double z) { // CHECK-LABEL: @test__fma_ru( // CHECK-NEXT: entry: -// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_fma_rtp_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]], double noundef [[Z:%.*]]) #[[ATTR3]] +// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_fma_rtp_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]], double noundef [[Z:%.*]]) #[[ATTR3]] // CHECK-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test__fma_ru(double x, double y, double z) { @@ -412,7 +412,7 @@ extern "C" __device__ double test__fma_ru(double x, double y, double z) { // CHECK-LABEL: @test__fma_rz( // CHECK-NEXT: entry: -// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract double @__ocml_fma_rtz_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]], double noundef [[Z:%.*]]) #[[ATTR3]] +// CHECK-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_fma_rtz_f64(double noundef [[X:%.*]], double noundef [[Y:%.*]], double noundef [[Z:%.*]]) #[[ATTR3]] // CHECK-NEXT: ret double [[CALL_I]] // extern "C" __device__ double test__fma_rz(double x, double y, double z) { diff --git a/clang/test/Headers/amdgcn_openmp_device_math.c b/clang/test/Headers/amdgcn_openmp_device_math.c index 296f89377e2ace..243d241628b2a0 100644 --- a/clang/test/Headers/amdgcn_openmp_device_math.c +++ b/clang/test/Headers/amdgcn_openmp_device_math.c @@ -113,21 +113,21 @@ // CHECK-CPP-NEXT: [[__X_ADDR_ASCAST_I:%.*]] = addrspacecast ptr addrspace(5) [[__X_ADDR_I]] to ptr // CHECK-CPP-NEXT: store double [[TMP0]], ptr [[__X_ADDR_ASCAST_I]], align 8 // CHECK-CPP-NEXT: [[TMP1:%.*]] = load double, ptr [[__X_ADDR_ASCAST_I]], align 8 -// CHECK-CPP-NEXT: [[CALL_I:%.*]] = call double @__ocml_sin_f64(double noundef [[TMP1]]) #[[ATTR3:[0-9]+]] +// CHECK-CPP-NEXT: [[CALL_I:%.*]] = call noundef double @__ocml_sin_f64(double noundef [[TMP1]]) #[[ATTR3:[0-9]+]] // CHECK-CPP-NEXT: store double [[CALL_I]], ptr [[L1_ASCAST]], align 8 // CHECK-CPP-NEXT: [[TMP2:%.*]] = load double, ptr [[X_ADDR_ASCAST]], align 8 // CHECK-CPP-NEXT: [[RETVAL_ASCAST_I6:%.*]] = addrspacecast ptr addrspace(5) [[RETVAL_I4]] to ptr // CHECK-CPP-NEXT: [[__X_ADDR_ASCAST_I7:%.*]] = addrspacecast ptr addrspace(5) [[__X_ADDR_I5]] to ptr // CHECK-CPP-NEXT: store double [[TMP2]], ptr [[__X_ADDR_ASCAST_I7]], align 8 // CHECK-CPP-NEXT: [[TMP3:%.*]] = load double, ptr [[__X_ADDR_ASCAST_I7]], align 8 -// CHECK-CPP-NEXT: [[CALL_I8:%.*]] = call double @__ocml_cos_f64(double noundef [[TMP3]]) #[[ATTR3]] +// CHECK-CPP-NEXT: [[CALL_I8:%.*]] = call noundef double @__ocml_cos_f64(double noundef [[TMP3]]) #[[ATTR3]] // CHECK-CPP-NEXT: store double [[CALL_I8]], ptr [[L2_ASCAST]], align 8 // CHECK-CPP-NEXT: [[TMP4:%.*]] = load double, ptr [[X_ADDR_ASCAST]], align 8 // CHECK-CPP-NEXT: [[RETVAL_ASCAST_I11:%.*]] = addrspacecast ptr addrspace(5) [[RETVAL_I9]] to ptr // CHECK-CPP-NEXT: [[__X_ADDR_ASCAST_I12:%.*]] = addrspacecast ptr addrspace(5) [[__X_ADDR_I10]] to ptr // CHECK-CPP-NEXT: store double [[TMP4]], ptr [[__X_ADDR_ASCAST_I12]], align 8 // CHECK-CPP-NEXT: [[TMP5:%.*]] = load double, ptr [[__X_ADDR_ASCAST_I12]], align 8 -// CHECK-CPP-NEXT: [[TMP6:%.*]] = call double @llvm.fabs.f64(double [[TMP5]]) +// CHECK-CPP-NEXT: [[TMP6:%.*]] = call noundef double @llvm.fabs.f64(double [[TMP5]]) // CHECK-CPP-NEXT: store double [[TMP6]], ptr [[L3_ASCAST]], align 8 // CHECK-CPP-NEXT: [[TMP7:%.*]] = load double, ptr [[X_ADDR_ASCAST]], align 8 // CHECK-CPP-NEXT: [[TMP8:%.*]] = load double, ptr [[Y_ADDR_ASCAST]], align 8 @@ -142,7 +142,7 @@ // CHECK-CPP-NEXT: [[TMP10:%.*]] = load double, ptr [[__X_ADDR_ASCAST_I16]], align 8 // CHECK-CPP-NEXT: [[TMP11:%.*]] = load double, ptr [[__Y_ADDR_ASCAST_I]], align 8 // CHECK-CPP-NEXT: [[TMP12:%.*]] = load double, ptr [[__Z_ADDR_ASCAST_I]], align 8 -// CHECK-CPP-NEXT: [[TMP13:%.*]] = call double @llvm.fma.f64(double [[TMP10]], double [[TMP11]], double [[TMP12]]) +// CHECK-CPP-NEXT: [[TMP13:%.*]] = call noundef double @llvm.fma.f64(double [[TMP10]], double [[TMP11]], double [[TMP12]]) // CHECK-CPP-NEXT: store double [[TMP13]], ptr [[L4_ASCAST]], align 8 // CHECK-CPP-NEXT: ret void // @@ -278,7 +278,7 @@ void test_math_f64(double x, double y, double z) { // CHECK-CPP-NEXT: [[__X_ADDR_ASCAST_I22:%.*]] = addrspacecast ptr addrspace(5) [[__X_ADDR_I20]] to ptr // CHECK-CPP-NEXT: store float [[TMP1]], ptr [[__X_ADDR_ASCAST_I22]], align 4 // CHECK-CPP-NEXT: [[TMP2:%.*]] = load float, ptr [[__X_ADDR_ASCAST_I22]], align 4 -// CHECK-CPP-NEXT: [[CALL_I23:%.*]] = call float @__ocml_sin_f32(float noundef [[TMP2]]) #[[ATTR3]] +// CHECK-CPP-NEXT: [[CALL_I23:%.*]] = call noundef float @__ocml_sin_f32(float noundef [[TMP2]]) #[[ATTR3]] // CHECK-CPP-NEXT: store float [[CALL_I23]], ptr [[L1_ASCAST]], align 4 // CHECK-CPP-NEXT: [[TMP3:%.*]] = load float, ptr [[X_ADDR_ASCAST]], align 4 // CHECK-CPP-NEXT: [[RETVAL_ASCAST_I6:%.*]] = addrspacecast ptr addrspace(5) [[RETVAL_I4]] to ptr @@ -289,7 +289,7 @@ void test_math_f64(double x, double y, double z) { // CHECK-CPP-NEXT: [[__X_ADDR_ASCAST_I27:%.*]] = addrspacecast ptr addrspace(5) [[__X_ADDR_I25]] to ptr // CHECK-CPP-NEXT: store float [[TMP4]], ptr [[__X_ADDR_ASCAST_I27]], align 4 // CHECK-CPP-NEXT: [[TMP5:%.*]] = load float, ptr [[__X_ADDR_ASCAST_I27]], align 4 -// CHECK-CPP-NEXT: [[CALL_I:%.*]] = call float @__ocml_cos_f32(float noundef [[TMP5]]) #[[ATTR3]] +// CHECK-CPP-NEXT: [[CALL_I:%.*]] = call noundef float @__ocml_cos_f32(float noundef [[TMP5]]) #[[ATTR3]] // CHECK-CPP-NEXT: store float [[CALL_I]], ptr [[L2_ASCAST]], align 4 // CHECK-CPP-NEXT: [[TMP6:%.*]] = load float, ptr [[X_ADDR_ASCAST]], align 4 // CHECK-CPP-NEXT: [[RETVAL_ASCAST_I11:%.*]] = addrspacecast ptr addrspace(5) [[RETVAL_I9]] to ptr @@ -300,7 +300,7 @@ void test_math_f64(double x, double y, double z) { // CHECK-CPP-NEXT: [[__X_ADDR_ASCAST_I31:%.*]] = addrspacecast ptr addrspace(5) [[__X_ADDR_I29]] to ptr // CHECK-CPP-NEXT: store float [[TMP7]], ptr [[__X_ADDR_ASCAST_I31]], align 4 // CHECK-CPP-NEXT: [[TMP8:%.*]] = load float, ptr [[__X_ADDR_ASCAST_I31]], align 4 -// CHECK-CPP-NEXT: [[TMP9:%.*]] = call float @llvm.fabs.f32(float [[TMP8]]) +// CHECK-CPP-NEXT: [[TMP9:%.*]] = call noundef float @llvm.fabs.f32(float [[TMP8]]) // CHECK-CPP-NEXT: store float [[TMP9]], ptr [[L3_ASCAST]], align 4 // CHECK-CPP-NEXT: [[TMP10:%.*]] = load float, ptr [[X_ADDR_ASCAST]], align 4 // CHECK-CPP-NEXT: [[TMP11:%.*]] = load float, ptr [[Y_ADDR_ASCAST]], align 4 @@ -325,7 +325,7 @@ void test_math_f64(double x, double y, double z) { // CHECK-CPP-NEXT: [[TMP16:%.*]] = load float, ptr [[__X_ADDR_ASCAST_I37]], align 4 // CHECK-CPP-NEXT: [[TMP17:%.*]] = load float, ptr [[__Y_ADDR_ASCAST_I38]], align 4 // CHECK-CPP-NEXT: [[TMP18:%.*]] = load float, ptr [[__Z_ADDR_ASCAST_I39]], align 4 -// CHECK-CPP-NEXT: [[TMP19:%.*]] = call float @llvm.fma.f32(float [[TMP16]], float [[TMP17]], float [[TMP18]]) +// CHECK-CPP-NEXT: [[TMP19:%.*]] = call noundef float @llvm.fma.f32(float [[TMP16]], float [[TMP17]], float [[TMP18]]) // CHECK-CPP-NEXT: store float [[TMP19]], ptr [[L4_ASCAST]], align 4 // CHECK-CPP-NEXT: ret void // @@ -437,21 +437,21 @@ void test_math_f32(float x, float y, float z) { // CHECK-CPP-NEXT: [[__X_ADDR_ASCAST_I:%.*]] = addrspacecast ptr addrspace(5) [[__X_ADDR_I]] to ptr // CHECK-CPP-NEXT: store float [[TMP0]], ptr [[__X_ADDR_ASCAST_I]], align 4 // CHECK-CPP-NEXT: [[TMP1:%.*]] = load float, ptr [[__X_ADDR_ASCAST_I]], align 4 -// CHECK-CPP-NEXT: [[CALL_I:%.*]] = call float @__ocml_sin_f32(float noundef [[TMP1]]) #[[ATTR3]] +// CHECK-CPP-NEXT: [[CALL_I:%.*]] = call noundef float @__ocml_sin_f32(float noundef [[TMP1]]) #[[ATTR3]] // CHECK-CPP-NEXT: store float [[CALL_I]], ptr [[L1_ASCAST]], align 4 // CHECK-CPP-NEXT: [[TMP2:%.*]] = load float, ptr [[X_ADDR_ASCAST]], align 4 // CHECK-CPP-NEXT: [[RETVAL_ASCAST_I6:%.*]] = addrspacecast ptr addrspace(5) [[RETVAL_I4]] to ptr // CHECK-CPP-NEXT: [[__X_ADDR_ASCAST_I7:%.*]] = addrspacecast ptr addrspace(5) [[__X_ADDR_I5]] to ptr // CHECK-CPP-NEXT: store float [[TMP2]], ptr [[__X_ADDR_ASCAST_I7]], align 4 // CHECK-CPP-NEXT: [[TMP3:%.*]] = load float, ptr [[__X_ADDR_ASCAST_I7]], align 4 -// CHECK-CPP-NEXT: [[CALL_I8:%.*]] = call float @__ocml_cos_f32(float noundef [[TMP3]]) #[[ATTR3]] +// CHECK-CPP-NEXT: [[CALL_I8:%.*]] = call noundef float @__ocml_cos_f32(float noundef [[TMP3]]) #[[ATTR3]] // CHECK-CPP-NEXT: store float [[CALL_I8]], ptr [[L2_ASCAST]], align 4 // CHECK-CPP-NEXT: [[TMP4:%.*]] = load float, ptr [[X_ADDR_ASCAST]], align 4 // CHECK-CPP-NEXT: [[RETVAL_ASCAST_I11:%.*]] = addrspacecast ptr addrspace(5) [[RETVAL_I9]] to ptr // CHECK-CPP-NEXT: [[__X_ADDR_ASCAST_I12:%.*]] = addrspacecast ptr addrspace(5) [[__X_ADDR_I10]] to ptr // CHECK-CPP-NEXT: store float [[TMP4]], ptr [[__X_ADDR_ASCAST_I12]], align 4 // CHECK-CPP-NEXT: [[TMP5:%.*]] = load float, ptr [[__X_ADDR_ASCAST_I12]], align 4 -// CHECK-CPP-NEXT: [[TMP6:%.*]] = call float @llvm.fabs.f32(float [[TMP5]]) +// CHECK-CPP-NEXT: [[TMP6:%.*]] = call noundef float @llvm.fabs.f32(float [[TMP5]]) // CHECK-CPP-NEXT: store float [[TMP6]], ptr [[L3_ASCAST]], align 4 // CHECK-CPP-NEXT: [[TMP7:%.*]] = load float, ptr [[X_ADDR_ASCAST]], align 4 // CHECK-CPP-NEXT: [[TMP8:%.*]] = load float, ptr [[Y_ADDR_ASCAST]], align 4 @@ -466,7 +466,7 @@ void test_math_f32(float x, float y, float z) { // CHECK-CPP-NEXT: [[TMP10:%.*]] = load float, ptr [[__X_ADDR_ASCAST_I16]], align 4 // CHECK-CPP-NEXT: [[TMP11:%.*]] = load float, ptr [[__Y_ADDR_ASCAST_I]], align 4 // CHECK-CPP-NEXT: [[TMP12:%.*]] = load float, ptr [[__Z_ADDR_ASCAST_I]], align 4 -// CHECK-CPP-NEXT: [[TMP13:%.*]] = call float @llvm.fma.f32(float [[TMP10]], float [[TMP11]], float [[TMP12]]) +// CHECK-CPP-NEXT: [[TMP13:%.*]] = call noundef float @llvm.fma.f32(float [[TMP10]], float [[TMP11]], float [[TMP12]]) // CHECK-CPP-NEXT: store float [[TMP13]], ptr [[L4_ASCAST]], align 4 // CHECK-CPP-NEXT: ret void // diff --git a/clang/test/Headers/amdgcn_openmp_device_math_constexpr.cpp b/clang/test/Headers/amdgcn_openmp_device_math_constexpr.cpp index ec34b237edd383..a5bb949ccaad3a 100644 --- a/clang/test/Headers/amdgcn_openmp_device_math_constexpr.cpp +++ b/clang/test/Headers/amdgcn_openmp_device_math_constexpr.cpp @@ -44,7 +44,7 @@ const float constexpr_fmaxf_f32 = fmaxf(2.0f, -4.0f); // CHECK-NEXT: [[__X_ADDR_ASCAST_I:%.*]] = addrspacecast ptr addrspace(5) [[__X_ADDR_I]] to ptr // CHECK-NEXT: store float -2.000000e+00, ptr [[__X_ADDR_ASCAST_I]], align 4 // CHECK-NEXT: [[TMP0:%.*]] = load float, ptr [[__X_ADDR_ASCAST_I]], align 4 -// CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[TMP0]]) +// CHECK-NEXT: [[TMP1:%.*]] = call noundef float @llvm.fabs.f32(float [[TMP0]]) // CHECK-NEXT: store float [[TMP1]], ptr addrspacecast (ptr addrspace(1) @_ZL19constexpr_fabsf_f32 to ptr), align 4 // CHECK-NEXT: ret void // @@ -64,7 +64,7 @@ const float constexpr_fmaxf_f32 = fmaxf(2.0f, -4.0f); // CHECK-NEXT: [[__X_ADDR_ASCAST_I_I:%.*]] = addrspacecast ptr addrspace(5) [[__X_ADDR_I_I]] to ptr // CHECK-NEXT: store float [[TMP0]], ptr [[__X_ADDR_ASCAST_I_I]], align 4 // CHECK-NEXT: [[TMP1:%.*]] = load float, ptr [[__X_ADDR_ASCAST_I_I]], align 4 -// CHECK-NEXT: [[TMP2:%.*]] = call float @llvm.fabs.f32(float [[TMP1]]) +// CHECK-NEXT: [[TMP2:%.*]] = call noundef float @llvm.fabs.f32(float [[TMP1]]) // CHECK-NEXT: store float [[TMP2]], ptr addrspacecast (ptr addrspace(1) @_ZL18constexpr_fabs_f32 to ptr), align 4 // CHECK-NEXT: ret void // @@ -78,7 +78,7 @@ const float constexpr_fmaxf_f32 = fmaxf(2.0f, -4.0f); // CHECK-NEXT: [[__X_ADDR_ASCAST_I:%.*]] = addrspacecast ptr addrspace(5) [[__X_ADDR_I]] to ptr // CHECK-NEXT: store float -2.000000e+00, ptr [[__X_ADDR_ASCAST_I]], align 4 // CHECK-NEXT: [[TMP0:%.*]] = load float, ptr [[__X_ADDR_ASCAST_I]], align 4 -// CHECK-NEXT: [[CALL_I:%.*]] = call float @__ocml_sin_f32(float noundef [[TMP0]]) #[[ATTR3:[0-9]+]] +// CHECK-NEXT: [[CALL_I:%.*]] = call noundef float @__ocml_sin_f32(float noundef [[TMP0]]) #[[ATTR3:[0-9]+]] // CHECK-NEXT: store float [[CALL_I]], ptr addrspacecast (ptr addrspace(1) @_ZL18constexpr_sinf_f32 to ptr), align 4 // CHECK-NEXT: ret void // @@ -98,7 +98,7 @@ const float constexpr_fmaxf_f32 = fmaxf(2.0f, -4.0f); // CHECK-NEXT: [[__X_ADDR_ASCAST_I_I:%.*]] = addrspacecast ptr addrspace(5) [[__X_ADDR_I_I]] to ptr // CHECK-NEXT: store float [[TMP0]], ptr [[__X_ADDR_ASCAST_I_I]], align 4 // CHECK-NEXT: [[TMP1:%.*]] = load float, ptr [[__X_ADDR_ASCAST_I_I]], align 4 -// CHECK-NEXT: [[CALL_I_I:%.*]] = call float @__ocml_sin_f32(float noundef [[TMP1]]) #[[ATTR3]] +// CHECK-NEXT: [[CALL_I_I:%.*]] = call noundef float @__ocml_sin_f32(float noundef [[TMP1]]) #[[ATTR3]] // CHECK-NEXT: store float [[CALL_I_I]], ptr addrspacecast (ptr addrspace(1) @_ZL17constexpr_sin_f32 to ptr), align 4 // CHECK-NEXT: ret void // @@ -112,7 +112,7 @@ const float constexpr_fmaxf_f32 = fmaxf(2.0f, -4.0f); // CHECK-NEXT: [[__X_ADDR_ASCAST_I:%.*]] = addrspacecast ptr addrspace(5) [[__X_ADDR_I]] to ptr // CHECK-NEXT: store float -2.000000e+00, ptr [[__X_ADDR_ASCAST_I]], align 4 // CHECK-NEXT: [[TMP0:%.*]] = load float, ptr [[__X_ADDR_ASCAST_I]], align 4 -// CHECK-NEXT: [[CALL_I:%.*]] = call float @__ocml_cos_f32(float noundef [[TMP0]]) #[[ATTR3]] +// CHECK-NEXT: [[CALL_I:%.*]] = call noundef float @__ocml_cos_f32(float noundef [[TMP0]]) #[[ATTR3]] // CHECK-NEXT: store float [[CALL_I]], ptr addrspacecast (ptr addrspace(1) @_ZL18constexpr_cosf_f32 to ptr), align 4 // CHECK-NEXT: ret void // @@ -132,7 +132,7 @@ const float constexpr_fmaxf_f32 = fmaxf(2.0f, -4.0f); // CHECK-NEXT: [[__X_ADDR_ASCAST_I_I:%.*]] = addrspacecast ptr addrspace(5) [[__X_ADDR_I_I]] to ptr // CHECK-NEXT: store float [[TMP0]], ptr [[__X_ADDR_ASCAST_I_I]], align 4 // CHECK-NEXT: [[TMP1:%.*]] = load float, ptr [[__X_ADDR_ASCAST_I_I]], align 4 -// CHECK-NEXT: [[CALL_I_I:%.*]] = call float @__ocml_cos_f32(float noundef [[TMP1]]) #[[ATTR3]] +// CHECK-NEXT: [[CALL_I_I:%.*]] = call noundef float @__ocml_cos_f32(float noundef [[TMP1]]) #[[ATTR3]] // CHECK-NEXT: store float [[CALL_I_I]], ptr addrspacecast (ptr addrspace(1) @_ZL17constexpr_cos_f32 to ptr), align 4 // CHECK-NEXT: ret void // @@ -154,7 +154,7 @@ const float constexpr_fmaxf_f32 = fmaxf(2.0f, -4.0f); // CHECK-NEXT: [[TMP0:%.*]] = load float, ptr [[__X_ADDR_ASCAST_I]], align 4 // CHECK-NEXT: [[TMP1:%.*]] = load float, ptr [[__Y_ADDR_ASCAST_I]], align 4 // CHECK-NEXT: [[TMP2:%.*]] = load float, ptr [[__Z_ADDR_ASCAST_I]], align 4 -// CHECK-NEXT: [[TMP3:%.*]] = call float @llvm.fma.f32(float [[TMP0]], float [[TMP1]], float [[TMP2]]) +// CHECK-NEXT: [[TMP3:%.*]] = call noundef float @llvm.fma.f32(float [[TMP0]], float [[TMP1]], float [[TMP2]]) // CHECK-NEXT: store float [[TMP3]], ptr addrspacecast (ptr addrspace(1) @_ZL18constexpr_fmaf_f32 to ptr), align 4 // CHECK-NEXT: ret void // @@ -190,7 +190,7 @@ const float constexpr_fmaxf_f32 = fmaxf(2.0f, -4.0f); // CHECK-NEXT: [[TMP3:%.*]] = load float, ptr [[__X_ADDR_ASCAST_I_I]], align 4 // CHECK-NEXT: [[TMP4:%.*]] = load float, ptr [[__Y_ADDR_ASCAST_I_I]], align 4 // CHECK-NEXT: [[TMP5:%.*]] = load float, ptr [[__Z_ADDR_ASCAST_I_I]], align 4 -// CHECK-NEXT: [[TMP6:%.*]] = call float @llvm.fma.f32(float [[TMP3]], float [[TMP4]], float [[TMP5]]) +// CHECK-NEXT: [[TMP6:%.*]] = call noundef float @llvm.fma.f32(float [[TMP3]], float [[TMP4]], float [[TMP5]]) // CHECK-NEXT: store float [[TMP6]], ptr addrspacecast (ptr addrspace(1) @_ZL17constexpr_fma_f32 to ptr), align 4 // CHECK-NEXT: ret void // @@ -208,7 +208,7 @@ const float constexpr_fmaxf_f32 = fmaxf(2.0f, -4.0f); // CHECK-NEXT: store float -4.000000e+00, ptr [[__Y_ADDR_ASCAST_I]], align 4 // CHECK-NEXT: [[TMP0:%.*]] = load float, ptr [[__X_ADDR_ASCAST_I]], align 4 // CHECK-NEXT: [[TMP1:%.*]] = load float, ptr [[__Y_ADDR_ASCAST_I]], align 4 -// CHECK-NEXT: [[TMP2:%.*]] = call float @llvm.minnum.f32(float [[TMP0]], float [[TMP1]]) +// CHECK-NEXT: [[TMP2:%.*]] = call noundef float @llvm.minnum.f32(float [[TMP0]], float [[TMP1]]) // CHECK-NEXT: store float [[TMP2]], ptr addrspacecast (ptr addrspace(1) @_ZL17constexpr_min_f32 to ptr), align 4 // CHECK-NEXT: ret void // @@ -226,7 +226,7 @@ const float constexpr_fmaxf_f32 = fmaxf(2.0f, -4.0f); // CHECK-NEXT: store float -4.000000e+00, ptr [[__Y_ADDR_ASCAST_I]], align 4 // CHECK-NEXT: [[TMP0:%.*]] = load float, ptr [[__X_ADDR_ASCAST_I]], align 4 // CHECK-NEXT: [[TMP1:%.*]] = load float, ptr [[__Y_ADDR_ASCAST_I]], align 4 -// CHECK-NEXT: [[TMP2:%.*]] = call float @llvm.maxnum.f32(float [[TMP0]], float [[TMP1]]) +// CHECK-NEXT: [[TMP2:%.*]] = call noundef float @llvm.maxnum.f32(float [[TMP0]], float [[TMP1]]) // CHECK-NEXT: store float [[TMP2]], ptr addrspacecast (ptr addrspace(1) @_ZL17constexpr_max_f32 to ptr), align 4 // CHECK-NEXT: ret void // @@ -260,7 +260,7 @@ const float constexpr_fmaxf_f32 = fmaxf(2.0f, -4.0f); // CHECK-NEXT: store float -4.000000e+00, ptr [[__Y_ADDR_ASCAST_I]], align 4 // CHECK-NEXT: [[TMP0:%.*]] = load float, ptr [[__X_ADDR_ASCAST_I]], align 4 // CHECK-NEXT: [[TMP1:%.*]] = load float, ptr [[__Y_ADDR_ASCAST_I]], align 4 -// CHECK-NEXT: [[TMP2:%.*]] = call float @llvm.minnum.f32(float [[TMP0]], float [[TMP1]]) +// CHECK-NEXT: [[TMP2:%.*]] = call noundef float @llvm.minnum.f32(float [[TMP0]], float [[TMP1]]) // CHECK-NEXT: store float [[TMP2]], ptr addrspacecast (ptr addrspace(1) @_ZL19constexpr_fminf_f32 to ptr), align 4 // CHECK-NEXT: ret void // @@ -278,7 +278,7 @@ const float constexpr_fmaxf_f32 = fmaxf(2.0f, -4.0f); // CHECK-NEXT: store float -4.000000e+00, ptr [[__Y_ADDR_ASCAST_I]], align 4 // CHECK-NEXT: [[TMP0:%.*]] = load float, ptr [[__X_ADDR_ASCAST_I]], align 4 // CHECK-NEXT: [[TMP1:%.*]] = load float, ptr [[__Y_ADDR_ASCAST_I]], align 4 -// CHECK-NEXT: [[TMP2:%.*]] = call float @llvm.maxnum.f32(float [[TMP0]], float [[TMP1]]) +// CHECK-NEXT: [[TMP2:%.*]] = call noundef float @llvm.maxnum.f32(float [[TMP0]], float [[TMP1]]) // CHECK-NEXT: store float [[TMP2]], ptr addrspacecast (ptr addrspace(1) @_ZL19constexpr_fmaxf_f32 to ptr), align 4 // CHECK-NEXT: ret void // diff --git a/clang/test/Headers/hip-header.hip b/clang/test/Headers/hip-header.hip index e8654c867fcb1f..146a43b643dba1 100644 --- a/clang/test/Headers/hip-header.hip +++ b/clang/test/Headers/hip-header.hip @@ -111,7 +111,7 @@ __device__ void test_numeric_type() { // instead of fma(_Float16, _Float16, _Float16). // CXX14-LABEL: define{{.*}}@_Z8test_fma -// CXX14: call contract half @llvm.fma.f16 +// CXX14: call contract noundef half @llvm.fma.f16 __device__ double test_fma(_Float16 h, int i) { return fma(h, h, i); } @@ -149,12 +149,12 @@ __device__ double test_isnan() { double d = 5.0; float f = 5.0; - // AMD_INT_RETURN: call i1 @llvm.is.fpclass.f32(float {{.*}}, i32 3) - // AMD_BOOL_RETURN: call i1 @llvm.is.fpclass.f32(float {{.*}}, i32 3) + // AMD_INT_RETURN: call noundef i1 @llvm.is.fpclass.f32(float {{.*}}, i32 3) + // AMD_BOOL_RETURN: call noundef i1 @llvm.is.fpclass.f32(float {{.*}}, i32 3) r += isnan(f); - // AMD_INT_RETURN: call i1 @llvm.is.fpclass.f64(double {{.*}}, i32 3) - // AMD_BOOL_RETURN: call i1 @llvm.is.fpclass.f64(double {{.*}}, i32 3) + // AMD_INT_RETURN: call noundef i1 @llvm.is.fpclass.f64(double {{.*}}, i32 3) + // AMD_BOOL_RETURN: call noundef i1 @llvm.is.fpclass.f64(double {{.*}}, i32 3) r += isnan(d); return r ; diff --git a/clang/test/Headers/nvptx_device_cmath_functions.cpp b/clang/test/Headers/nvptx_device_cmath_functions.cpp index 9e73172fa28e03..898a8544a6e6a8 100644 --- a/clang/test/Headers/nvptx_device_cmath_functions.cpp +++ b/clang/test/Headers/nvptx_device_cmath_functions.cpp @@ -12,15 +12,15 @@ void test_sqrt(double a1) { #pragma omp target { - // CHECK-YES: call double @__nv_sqrt(double + // CHECK-YES: call noundef double @__nv_sqrt(double double l1 = sqrt(a1); - // CHECK-YES: call double @__nv_pow(double + // CHECK-YES: call noundef double @__nv_pow(double double l2 = pow(a1, a1); - // CHECK-YES: call double @__nv_modf(double + // CHECK-YES: call noundef double @__nv_modf(double double l3 = modf(a1 + 3.5, &a1); - // CHECK-YES: call double @__nv_fabs(double + // CHECK-YES: call noundef double @__nv_fabs(double double l4 = fabs(a1); - // CHECK-YES: call i32 @__nv_abs(i32 + // CHECK-YES: call noundef i32 @__nv_abs(i32 double l5 = abs((int)a1); } } diff --git a/clang/test/Headers/nvptx_device_cmath_functions_cxx17.cpp b/clang/test/Headers/nvptx_device_cmath_functions_cxx17.cpp index 8c3cd8779015f7..5a68854a43ea77 100644 --- a/clang/test/Headers/nvptx_device_cmath_functions_cxx17.cpp +++ b/clang/test/Headers/nvptx_device_cmath_functions_cxx17.cpp @@ -12,15 +12,15 @@ void test_sqrt(double a1) { #pragma omp target { - // CHECK-YES: call double @__nv_sqrt(double + // CHECK-YES: call noundef double @__nv_sqrt(double double l1 = sqrt(a1); - // CHECK-YES: call double @__nv_pow(double + // CHECK-YES: call noundef double @__nv_pow(double double l2 = pow(a1, a1); - // CHECK-YES: call double @__nv_modf(double + // CHECK-YES: call noundef double @__nv_modf(double double l3 = modf(a1 + 3.5, &a1); - // CHECK-YES: call double @__nv_fabs(double + // CHECK-YES: call noundef double @__nv_fabs(double double l4 = fabs(a1); - // CHECK-YES: call i32 @__nv_abs(i32 + // CHECK-YES: call noundef i32 @__nv_abs(i32 double l5 = abs((int)a1); } } diff --git a/clang/test/Headers/nvptx_device_math_functions.c b/clang/test/Headers/nvptx_device_math_functions.c index 3cbeeafe4b3a29..47781f2206dea7 100644 --- a/clang/test/Headers/nvptx_device_math_functions.c +++ b/clang/test/Headers/nvptx_device_math_functions.c @@ -4,9 +4,9 @@ // REQUIRES: nvptx-registered-target // RUN: %clang_cc1 -x c -internal-isystem %S/Inputs/include -fopenmp -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm-bc %s -o %t-ppc-host.bc -// RUN: %clang_cc1 -x c -internal-isystem %S/../../lib/Headers/openmp_wrappers -include __clang_openmp_device_functions.h -internal-isystem %S/Inputs/include -fopenmp -triple nvptx64-nvidia-cuda -aux-triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-target-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s +// RUN: %clang_cc1 -x c -internal-isystem %S/../../lib/Headers/openmp_wrappers -include __clang_openmp_device_functions.h -internal-isystem %S/Inputs/include -fopenmp -triple nvptx64-nvidia-cuda -aux-triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-target-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix=CHECK-C // RUN: %clang_cc1 -x c++ -internal-isystem %S/Inputs/include -fopenmp -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm-bc %s -o %t-ppc-host.bc -// RUN: %clang_cc1 -x c++ -internal-isystem %S/../../lib/Headers/openmp_wrappers -include __clang_openmp_device_functions.h -internal-isystem %S/Inputs/include -fopenmp -triple nvptx64-nvidia-cuda -aux-triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-target-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s +// RUN: %clang_cc1 -x c++ -internal-isystem %S/../../lib/Headers/openmp_wrappers -include __clang_openmp_device_functions.h -internal-isystem %S/Inputs/include -fopenmp -triple nvptx64-nvidia-cuda -aux-triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-target-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s --check-prefix=CHECK-CXX #ifdef __cplusplus #include @@ -19,15 +19,20 @@ void test_sqrt(double a1) { #pragma omp target { - // CHECK: call double @__nv_sqrt(double + // CHECK-C: call double @__nv_sqrt(double + // CHECK-CXX: call noundef double @__nv_sqrt(double double l1 = sqrt(a1); - // CHECK: call double @__nv_pow(double + // CHECK-C: call double @__nv_pow(double + // CHECK-CXX: call noundef double @__nv_pow(double double l2 = pow(a1, a1); - // CHECK: call double @__nv_modf(double + // CHECK-C: call double @__nv_modf(double + // CHECK-CXX: call noundef double @__nv_modf(double double l3 = modf(a1 + 3.5, &a1); - // CHECK: call double @__nv_fabs(double + // CHECK-C: call double @__nv_fabs(double + // CHECK-CXX: call noundef double @__nv_fabs(double double l4 = fabs(a1); - // CHECK: call i32 @__nv_abs(i32 + // CHECK-C: call i32 @__nv_abs(i32 + // CHECK-CXX: call noundef i32 @__nv_abs(i32 double l5 = abs((int)a1); } } diff --git a/clang/test/Headers/nvptx_device_math_functions.cpp b/clang/test/Headers/nvptx_device_math_functions.cpp index 1bb20c3a24f8dd..791cb49f918c7a 100644 --- a/clang/test/Headers/nvptx_device_math_functions.cpp +++ b/clang/test/Headers/nvptx_device_math_functions.cpp @@ -12,15 +12,15 @@ void test_sqrt(double a1) { #pragma omp target { - // CHECK-YES: call double @__nv_sqrt(double + // CHECK-YES: call noundef double @__nv_sqrt(double double l1 = sqrt(a1); - // CHECK-YES: call double @__nv_pow(double + // CHECK-YES: call noundef double @__nv_pow(double double l2 = pow(a1, a1); - // CHECK-YES: call double @__nv_modf(double + // CHECK-YES: call noundef double @__nv_modf(double double l3 = modf(a1 + 3.5, &a1); - // CHECK-YES: call double @__nv_fabs(double + // CHECK-YES: call noundef double @__nv_fabs(double double l4 = fabs(a1); - // CHECK-YES: call i32 @__nv_abs(i32 + // CHECK-YES: call noundef i32 @__nv_abs(i32 double l5 = abs((int)a1); } } diff --git a/clang/test/Headers/nvptx_device_math_functions_cxx17.cpp b/clang/test/Headers/nvptx_device_math_functions_cxx17.cpp index e6fd867c955fae..aa759ec6a54c88 100644 --- a/clang/test/Headers/nvptx_device_math_functions_cxx17.cpp +++ b/clang/test/Headers/nvptx_device_math_functions_cxx17.cpp @@ -12,15 +12,15 @@ void test_sqrt(double a1) { #pragma omp target { - // CHECK-YES: call double @__nv_sqrt(double + // CHECK-YES: call noundef double @__nv_sqrt(double double l1 = sqrt(a1); - // CHECK-YES: call double @__nv_pow(double + // CHECK-YES: call noundef double @__nv_pow(double double l2 = pow(a1, a1); - // CHECK-YES: call double @__nv_modf(double + // CHECK-YES: call noundef double @__nv_modf(double double l3 = modf(a1 + 3.5, &a1); - // CHECK-YES: call double @__nv_fabs(double + // CHECK-YES: call noundef double @__nv_fabs(double double l4 = fabs(a1); - // CHECK-YES: call i32 @__nv_abs(i32 + // CHECK-YES: call noundef i32 @__nv_abs(i32 double l5 = abs((int)a1); } } diff --git a/clang/test/Headers/nvptx_device_math_modf.cpp b/clang/test/Headers/nvptx_device_math_modf.cpp index eb9f57538a625d..fdd87c5915e5b2 100644 --- a/clang/test/Headers/nvptx_device_math_modf.cpp +++ b/clang/test/Headers/nvptx_device_math_modf.cpp @@ -7,13 +7,13 @@ // 4 calls to modf(f), all translated to __nv_modf calls: // CHECK-NOT: _Z.modf -// CHECK: call double @__nv_modf(double +// CHECK: call noundef double @__nv_modf(double // CHECK-NOT: _Z.modf -// CHECK: call float @__nv_modff(float +// CHECK: call noundef float @__nv_modff(float // CHECK-NOT: _Z.modf -// CHECK: call double @__nv_modf(double +// CHECK: call noundef double @__nv_modf(double // CHECK-NOT: _Z.modf -// CHECK: call float @__nv_modff(float +// CHECK: call noundef float @__nv_modff(float // CHECK-NOT: _Z.modf template diff --git a/clang/test/Headers/nvptx_device_math_sin.cpp b/clang/test/Headers/nvptx_device_math_sin.cpp index 3f4fe5bff6b2e0..5db132f02c9ae7 100644 --- a/clang/test/Headers/nvptx_device_math_sin.cpp +++ b/clang/test/Headers/nvptx_device_math_sin.cpp @@ -9,11 +9,11 @@ double math(float f, double d) { double r = 0; -// SLOW: call float @__nv_sinf(float -// FAST: call fast nofpclass(nan inf) float @__nv_fast_sinf(float +// SLOW: call noundef float @__nv_sinf(float +// FAST: call fast noundef nofpclass(nan inf) float @__nv_fast_sinf(float r += sin(f); -// SLOW: call double @__nv_sin(double -// FAST: call fast nofpclass(nan inf) double @__nv_sin(double +// SLOW: call noundef double @__nv_sin(double +// FAST: call fast noundef nofpclass(nan inf) double @__nv_sin(double r += sin(d); return r; } diff --git a/clang/test/Headers/nvptx_device_math_sin_cos.cpp b/clang/test/Headers/nvptx_device_math_sin_cos.cpp index 98e7b3feb6b999..9be082802303b9 100644 --- a/clang/test/Headers/nvptx_device_math_sin_cos.cpp +++ b/clang/test/Headers/nvptx_device_math_sin_cos.cpp @@ -8,22 +8,22 @@ // CHECK-NOT: _Z.sin // CHECK-NOT: _Z.cos -// CHECK: call double @__nv_sin(double +// CHECK: call noundef double @__nv_sin(double // CHECK-NOT: _Z.sin // CHECK-NOT: _Z.cos -// CHECK: call float @__nv_sinf(float +// CHECK: call noundef float @__nv_sinf(float // CHECK-NOT: _Z.sin // CHECK-NOT: _Z.cos -// CHECK: call double @__nv_sin(double +// CHECK: call noundef double @__nv_sin(double // CHECK-NOT: _Z.sin // CHECK-NOT: _Z.cos -// CHECK: call double @__nv_cos(double +// CHECK: call noundef double @__nv_cos(double // CHECK-NOT: _Z.sin // CHECK-NOT: _Z.cos -// CHECK: call float @__nv_sinf(float +// CHECK: call noundef float @__nv_sinf(float // CHECK-NOT: _Z.sin // CHECK-NOT: _Z.cos -// CHECK: call float @__nv_cosf(float +// CHECK: call noundef float @__nv_cosf(float // CHECK-NOT: _Z.sin // CHECK-NOT: _Z.cos diff --git a/clang/test/Headers/openmp_device_math_isnan.cpp b/clang/test/Headers/openmp_device_math_isnan.cpp index 0a632abcd8b06d..a297cfc5b9293d 100644 --- a/clang/test/Headers/openmp_device_math_isnan.cpp +++ b/clang/test/Headers/openmp_device_math_isnan.cpp @@ -20,17 +20,17 @@ double math(float f, double d) { double r = 0; - // INT_RETURN: call i32 @__nv_isnanf(float + // INT_RETURN: call noundef i32 @__nv_isnanf(float // AMD_INT_RETURN_SAFE: call i1 @llvm.is.fpclass.f32(float{{.*}}, i32 3) // AMD_INT_RETURN_FAST: sitofp i32 {{.*}} to double - // BOOL_RETURN: call i32 @__nv_isnanf(float + // BOOL_RETURN: call noundef i32 @__nv_isnanf(float // AMD_BOOL_RETURN_SAFE: call i1 @llvm.is.fpclass.f32(float{{.*}}, i32 3) // AMD_BOOL_RETURN_FAST: icmp ne i32 {{.*}}, 0 r += std::isnan(f); - // INT_RETURN: call i32 @__nv_isnand(double + // INT_RETURN: call noundef i32 @__nv_isnand(double // AMD_INT_RETURN_SAFE: call i1 @llvm.is.fpclass.f64(double{{.*}}, i32 3) // AMD_INT_RETURN_FAST: sitofp i32 {{.*}} to double - // BOOL_RETURN: call i32 @__nv_isnand(double + // BOOL_RETURN: call noundef i32 @__nv_isnand(double // AMD_BOOL_RETURN_SAFE: call i1 @llvm.is.fpclass.f64(double{{.*}}, i32 3) // AMD_BOOL_RETURN_FAST: icmp ne i32 {{.*}}, 0 r += std::isnan(d); diff --git a/clang/test/Headers/stdarg.c b/clang/test/Headers/stdarg.c index 49df42caa3300a..1c403d109bf7c3 100644 --- a/clang/test/Headers/stdarg.c +++ b/clang/test/Headers/stdarg.c @@ -1,29 +1,47 @@ +// RUN: rm -fR %t // RUN: split-file %s %t // RUN: %clang_cc1 -fsyntax-only -verify=c89 -Werror=implicit-function-declaration -std=c89 %t/stdarg0.c // RUN: %clang_cc1 -fsyntax-only -verify=c99 -Werror=implicit-function-declaration -std=c99 %t/stdarg0.c +// RUN: %clang_cc1 -fsyntax-only -verify=c89-modules -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -Werror=implicit-function-declaration -std=c89 %t/stdarg0.c +// RUN: %clang_cc1 -fsyntax-only -verify=c99-modules -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -Werror=implicit-function-declaration -std=c99 %t/stdarg0.c // RUN: %clang_cc1 -fsyntax-only -verify=c89 -Werror=implicit-function-declaration -std=c89 %t/stdarg1.c // RUN: %clang_cc1 -fsyntax-only -verify=c99 -Werror=implicit-function-declaration -std=c99 %t/stdarg1.c +// RUN: %clang_cc1 -fsyntax-only -verify=c89-modules -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -Werror=implicit-function-declaration -std=c89 %t/stdarg1.c +// RUN: %clang_cc1 -fsyntax-only -verify=c99-modules -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -Werror=implicit-function-declaration -std=c99 %t/stdarg1.c // Split the file so that the "implicitly declaring library function" errors get repeated. //--- stdarg0.c static void f(int p, ...) { - __gnuc_va_list g; // c89-error{{undeclared identifier '__gnuc_va_list'}} c99-error{{undeclared identifier}} - va_list v; // c89-error{{undeclared identifier 'va_list'}} c99-error{{undeclared identifier}} + __gnuc_va_list g; // c89-error{{undeclared identifier '__gnuc_va_list'}} c99-error{{undeclared identifier}} \ + c89-modules-error{{undeclared identifier}} c99-modules-error{{undeclared identifier}} + va_list v; // c89-error{{undeclared identifier 'va_list'}} c99-error{{undeclared identifier}} \ + c89-modules-error{{undeclared identifier}} c99-modules-error{{undeclared identifier}} va_start(v, p); // c89-error{{implicitly declaring library function 'va_start'}} c89-note{{include the header or explicitly provide a declaration for 'va_start'}} c89-error{{undeclared identifier 'v'}} \ - c99-error{{call to undeclared library function 'va_start'}} c99-note{{provide a declaration}} c99-error{{undeclared identifier}} + c99-error{{call to undeclared library function 'va_start'}} c99-note{{provide a declaration}} c99-error{{undeclared identifier}} \ + c89-modules-error{{implicitly declaring library function}} c89-modules-note{{provide a declaration}} c89-modules-error{{undeclared identifier}} \ + c99-modules-error{{undeclared library function}} c99-modules-note{{provide a declaration}} c99-modules-error{{undeclared identifier}} int i = va_arg(v, int); // c89-error{{implicit declaration of function 'va_arg'}} c89-error{{expected expression}} c89-error{{use of undeclared identifier 'v'}} \ - c99-error{{call to undeclared function 'va_arg'}} c99-error{{expected expression}} c99-error{{undeclared identifier}} + c99-error{{call to undeclared function 'va_arg'}} c99-error{{expected expression}} c99-error{{undeclared identifier}} \ + c89-modules-error{{implicit declaration of function}} c89-modules-error{{expected expression}} c89-modules-error{{undeclared identifier}} \ + c99-modules-error{{undeclared function}} c99-modules-error{{expected expression}} c99-modules-error{{undeclared identifier}} va_end(v); // c89-error{{implicitly declaring library function 'va_end'}} c89-note{{include the header or explicitly provide a declaration for 'va_end'}} c89-error{{undeclared identifier 'v'}} \ - c99-error{{call to undeclared library function 'va_end'}} c99-note{{provide a declaration}} c99-error{{undeclared identifier}} + c99-error{{call to undeclared library function 'va_end'}} c99-note{{provide a declaration}} c99-error{{undeclared identifier}} \ + c89-modules-error{{implicitly declaring library function}} c89-modules-note{{provide a declaration}} c89-modules-error{{undeclared identifier}} \ + c99-modules-error{{undeclared library function}} c99-modules-note{{provide a declaration}} c99-modules-error{{undeclared identifier}} __va_copy(g, v); // c89-error{{implicit declaration of function '__va_copy'}} c89-error{{use of undeclared identifier 'g'}} c89-error{{use of undeclared identifier 'v'}} \ - c99-error{{call to undeclared function '__va_copy'}} c99-error{{undeclared identifier}} c99-error{{undeclared identifier}} + c99-error{{call to undeclared function '__va_copy'}} c99-error{{undeclared identifier}} c99-error{{undeclared identifier}} \ + c89-modules-error{{implicit declaration of function}} c89-modules-error{{undeclared identifier}} c89-modules-error{{undeclared identifier}} \ + c99-modules-error{{undeclared function}} c99-modules-error{{undeclared identifier}} c99-modules-error{{undeclared identifier}} va_copy(g, v); // c89-error{{implicitly declaring library function 'va_copy'}} c89-note{{include the header or explicitly provide a declaration for 'va_copy'}} c89-error{{use of undeclared identifier 'g'}} c89-error{{use of undeclared identifier 'v'}} \ - c99-error{{call to undeclared library function 'va_copy'}} c99-note{{provide a declaration}} c99-error{{undeclared identifier}} c99-error{{undeclared identifier}} + c99-error{{call to undeclared library function 'va_copy'}} c99-note{{provide a declaration}} c99-error{{undeclared identifier}} c99-error{{undeclared identifier}} \ + c89-modules-error{{implicitly declaring library function}} c89-modules-note{{provide a declaration}} c89-modules-error{{undeclared identifier}} c89-modules-error{{undeclared identifier}} \ + c99-modules-error{{undeclared library function}} c99-modules-note{{provide a declaration}} c99-modules-error{{undeclared identifier}} c99-modules-error{{undeclared identifier}} } //--- stdarg1.c // c99-no-diagnostics +// c99-modules-no-diagnostics #include static void f(int p, ...) { @@ -33,5 +51,6 @@ static void f(int p, ...) { int i = va_arg(v, int); va_end(v); __va_copy(g, v); - va_copy(g, v); // c89-error{{implicitly declaring library function}} c89-note{{provide a declaration}} + va_copy(g, v); // c89-error{{implicitly declaring library function}} c89-note{{provide a declaration}} \ + c89-modules-error{{implicitly declaring library function}} c89-modules-note{{provide a declaration}} } diff --git a/clang/test/Headers/stdargneeds.c b/clang/test/Headers/stdargneeds.c index 7505ff55731f14..8ef76e90deaef0 100644 --- a/clang/test/Headers/stdargneeds.c +++ b/clang/test/Headers/stdargneeds.c @@ -1,23 +1,35 @@ +// RUN: rm -fR %t // RUN: split-file %s %t // RUN: %clang_cc1 -fsyntax-only -verify -Werror=implicit-function-declaration -std=c89 %t/stdargneeds0.c +// RUN: %clang_cc1 -fsyntax-only -verify=expected-modules -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -Werror=implicit-function-declaration -std=c89 %t/stdargneeds0.c // RUN: %clang_cc1 -fsyntax-only -verify -Werror=implicit-function-declaration -std=c89 %t/stdargneeds1.c +// RUN: %clang_cc1 -fsyntax-only -verify=expected-modules -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -Werror=implicit-function-declaration -std=c89 %t/stdargneeds1.c // RUN: %clang_cc1 -fsyntax-only -verify -Werror=implicit-function-declaration -std=c89 %t/stdargneeds2.c +// RUN: %clang_cc1 -fsyntax-only -verify=expected-modules -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -Werror=implicit-function-declaration -std=c89 %t/stdargneeds2.c // RUN: %clang_cc1 -fsyntax-only -verify -Werror=implicit-function-declaration -std=c89 %t/stdargneeds3.c +// RUN: %clang_cc1 -fsyntax-only -verify=expected-modules -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -Werror=implicit-function-declaration -std=c89 %t/stdargneeds3.c // RUN: %clang_cc1 -fsyntax-only -verify -Werror=implicit-function-declaration -std=c89 %t/stdargneeds4.c +// RUN: %clang_cc1 -fsyntax-only -verify=expected-modules -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -Werror=implicit-function-declaration -std=c89 %t/stdargneeds4.c // RUN: %clang_cc1 -fsyntax-only -verify -Werror=implicit-function-declaration -std=c89 %t/stdargneeds5.c +// RUN: %clang_cc1 -fsyntax-only -verify=expected-modules -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -Werror=implicit-function-declaration -std=c89 %t/stdargneeds5.c // Split the file so that the "implicitly declaring library function" errors get repeated. // Use C89 to verify that __need_ can be used to get types that wouldn't normally be available. //--- stdargneeds0.c static void f(int p, ...) { - __gnuc_va_list g; // expected-error{{undeclared identifier '__gnuc_va_list'}} - va_list v; // expected-error{{undeclared identifier 'va_list'}} - va_start(v, p); // expected-error{{implicitly declaring library function 'va_start'}} expected-note{{include the header or explicitly provide a declaration for 'va_start'}} expected-error{{undeclared identifier 'v'}} - int i = va_arg(v, int); // expected-error{{implicit declaration of function 'va_arg'}} expected-error{{expected expression}} expected-error{{use of undeclared identifier 'v'}} - va_end(v); // expected-error{{implicitly declaring library function 'va_end'}} expected-note{{include the header or explicitly provide a declaration for 'va_end'}} expected-error{{undeclared identifier 'v'}} - __va_copy(g, v); // expected-error{{implicit declaration of function '__va_copy'}} expected-error{{use of undeclared identifier 'g'}} expected-error{{use of undeclared identifier 'v'}} - va_copy(g, v); // expected-error{{implicitly declaring library function 'va_copy'}} expected-note{{include the header or explicitly provide a declaration for 'va_copy'}} expected-error{{use of undeclared identifier 'g'}} expected-error{{use of undeclared identifier 'v'}} + __gnuc_va_list g; // expected-error{{undeclared identifier '__gnuc_va_list'}} expected-modules-error{{undeclared identifier}} + va_list v; // expected-error{{undeclared identifier 'va_list'}} expected-modules-error{{undeclared identifier}} + va_start(v, p); // expected-error{{implicitly declaring library function 'va_start'}} expected-note{{include the header or explicitly provide a declaration for 'va_start'}} expected-error{{undeclared identifier 'v'}} \ + expected-modules-error{{implicitly declaring library function}} expected-modules-note{{provide a declaration}} expected-modules-error{{undeclared identifier}} + int i = va_arg(v, int); // expected-error{{implicit declaration of function 'va_arg'}} expected-error{{expected expression}} expected-error{{use of undeclared identifier 'v'}} \ + expected-modules-error{{implicit declaration of function}} expected-modules-error{{expected expression}} expected-modules-error{{undeclared identifier}} + va_end(v); // expected-error{{implicitly declaring library function 'va_end'}} expected-note{{include the header or explicitly provide a declaration for 'va_end'}} expected-error{{undeclared identifier 'v'}} \ + expected-modules-error{{implicitly declaring library function}} expected-modules-note{{provide a declaration}} expected-modules-error{{undeclared identifier}} + __va_copy(g, v); // expected-error{{implicit declaration of function '__va_copy'}} expected-error{{use of undeclared identifier 'g'}} expected-error{{use of undeclared identifier 'v'}} \ + expected-modules-error{{implicit declaration of function}} expected-modules-error{{undeclared identifier}} expected-modules-error{{undeclared identifier}} + va_copy(g, v); // expected-error{{implicitly declaring library function 'va_copy'}} expected-note{{include the header or explicitly provide a declaration for 'va_copy'}} expected-error{{use of undeclared identifier 'g'}} expected-error{{use of undeclared identifier 'v'}} \ + expected-modules-error{{implicitly declaring library function}} expected-modules-note{{provide a declaration}} expected-modules-error{{undeclared identifier}} expected-modules-error{{undeclared identifier}} } //--- stdargneeds1.c @@ -25,25 +37,37 @@ static void f(int p, ...) { #include static void f(int p, ...) { __gnuc_va_list g; - va_list v; // expected-error{{undeclared identifier}} - va_start(v, p); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}} expected-error{{undeclared identifier}} - int i = va_arg(v, int); // expected-error{{implicit declaration of function}} expected-error{{expected expression}} expected-error{{undeclared identifier}} - va_end(v); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}} expected-error{{undeclared identifier}} - __va_copy(g, v); // expected-error{{implicit declaration of function}} expected-error{{undeclared identifier}} - va_copy(g, v); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}} expected-error{{undeclared identifier}} + va_list v; // expected-error{{undeclared identifier}} \ + expected-modules-error{{'va_list' must be declared before it is used}} expected-modules-note@__stdarg_va_list.h:*{{declaration here is not visible}} + va_start(v, p); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}} expected-error{{undeclared identifier}} \ + expected-modules-error{{implicitly declaring library function}} expected-modules-note{{provide a declaration}} + int i = va_arg(v, int); // expected-error{{implicit declaration of function}} expected-error{{expected expression}} expected-error{{undeclared identifier}} \ + expected-modules-error{{implicit declaration of function}} expected-modules-error{{expected expression}} + va_end(v); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}} expected-error{{undeclared identifier}} \ + expected-modules-error{{implicitly declaring library function}} expected-modules-note{{provide a declaration}} + __va_copy(g, v); // expected-error{{implicit declaration of function}} expected-error{{undeclared identifier}} \ + expected-modules-error{{implicit declaration of function}} + va_copy(g, v); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}} expected-error{{undeclared identifier}} \ + expected-modules-error{{implicitly declaring library function}} expected-modules-note{{provide a declaration}} } //--- stdargneeds2.c #define __need_va_list #include static void f(int p, ...) { - __gnuc_va_list g; // expected-error{{undeclared identifier}} + __gnuc_va_list g; // expected-error{{undeclared identifier}} \ + expected-modules-error{{'__gnuc_va_list' must be declared before it is used}} expected-modules-note@__stdarg___gnuc_va_list.h:*{{declaration here is not visible}} va_list v; - va_start(v, p); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}} - int i = va_arg(v, int); // expected-error{{implicit declaration of function}} expected-error{{expected expression}} - va_end(v); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}} - __va_copy(g, v); // expected-error{{implicit declaration of function}} expected-error{{undeclared identifier}} - va_copy(g, v); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}} expected-error{{undeclared identifier}} + va_start(v, p); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}} \ + expected-modules-error{{implicitly declaring library function}} expected-modules-note{{provide a declaration}} + int i = va_arg(v, int); // expected-error{{implicit declaration of function}} expected-error{{expected expression}} \ + expected-modules-error{{implicit declaration of function}} expected-modules-error{{expected expression}} + va_end(v); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}} \ + expected-modules-error{{implicitly declaring library function}} expected-modules-note{{provide a declaration}} + __va_copy(g, v); // expected-error{{implicit declaration of function}} expected-error{{undeclared identifier}} \ + expected-modules-error{{implicit declaration of function}} + va_copy(g, v); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}} expected-error{{undeclared identifier}} \ + expected-modules-error{{implicitly declaring library function}} expected-modules-note{{provide a declaration}} } //--- stdargneeds3.c @@ -51,13 +75,16 @@ static void f(int p, ...) { #define __need_va_arg #include static void f(int p, ...) { - __gnuc_va_list g; // expected-error{{undeclared identifier}} + __gnuc_va_list g; // expected-error{{undeclared identifier}} \ + expected-modules-error{{'__gnuc_va_list' must be declared before it is used}} expected-modules-note@__stdarg___gnuc_va_list.h:*{{declaration here is not visible}} va_list v; va_start(v, p); int i = va_arg(v, int); va_end(v); - __va_copy(g, v); // expected-error{{implicit declaration of function}} expected-error{{undeclared identifier}} - va_copy(g, v); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}} expected-error{{undeclared identifier}} + __va_copy(g, v); // expected-error{{implicit declaration of function}} expected-error{{undeclared identifier}} \ + expected-modules-error{{implicit declaration of function}} + va_copy(g, v); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}} expected-error{{undeclared identifier}} \ + expected-modules-error{{implicitly declaring library function}} expected-modules-note{{provide a declaration}} } //--- stdargneeds4.c @@ -68,11 +95,15 @@ static void f(int p, ...) { static void f(int p, ...) { __gnuc_va_list g; va_list v; - va_start(v, p); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}} - int i = va_arg(v, int); // expected-error{{implicit declaration of function}} expected-error{{expected expression}} - va_end(v); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}} + va_start(v, p); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}} \ + expected-modules-error{{implicitly declaring library function}} expected-modules-note{{provide a declaration}} + int i = va_arg(v, int); // expected-error{{implicit declaration of function}} expected-error{{expected expression}} \ + expected-modules-error{{implicit declaration of function}} expected-modules-error{{expected expression}} + va_end(v); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}} \ + expected-modules-error{{implicitly declaring library function}} expected-modules-note{{provide a declaration}} __va_copy(g, v); - va_copy(g, v); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}} + va_copy(g, v); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}} \ + expected-modules-error{{implicitly declaring library function}} expected-modules-note{{provide a declaration}} } //--- stdargneeds5.c @@ -83,9 +114,12 @@ static void f(int p, ...) { static void f(int p, ...) { __gnuc_va_list g; va_list v; - va_start(v, p); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}} - int i = va_arg(v, int); // expected-error{{implicit declaration of function}} expected-error{{expected expression}} - va_end(v); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}} - __va_copy(g, v); // expected-error{{implicit declaration of function}} + va_start(v, p); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}} \ + expected-modules-error{{implicitly declaring library function}} expected-modules-note{{provide a declaration}} + int i = va_arg(v, int); // expected-error{{implicit declaration of function}} expected-error{{expected expression}} \ + expected-modules-error{{implicit declaration of function}} expected-modules-error{{expected expression}} + va_end(v); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}} \ + expected-modules-error{{implicitly declaring library function}} expected-modules-note{{provide a declaration}} + __va_copy(g, v); // expected-error{{implicit declaration of function}} expected-modules-error{{implicit declaration of function}} va_copy(g, v); } diff --git a/clang/test/Headers/stddef.c b/clang/test/Headers/stddef.c index d2bceb84a0ba0b..bf564fb15221ae 100644 --- a/clang/test/Headers/stddef.c +++ b/clang/test/Headers/stddef.c @@ -1,35 +1,57 @@ +// RUN: rm -fR %t // RUN: %clang_cc1 -fsyntax-only -verify=c99 -std=c99 %s // RUN: %clang_cc1 -fsyntax-only -verify=c11 -std=c11 %s // RUN: %clang_cc1 -fsyntax-only -verify=c23 -std=c23 %s +// RUN: %clang_cc1 -fsyntax-only -verify=c99-modules -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -std=c99 %s +// RUN: %clang_cc1 -fsyntax-only -verify=c11-modules -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -std=c11 %s +// RUN: %clang_cc1 -fsyntax-only -verify=c23-modules -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -std=c23 %s struct astruct { char member; }; -ptrdiff_t p0; // c99-error{{unknown type name 'ptrdiff_t'}} c11-error{{unknown type}} c23-error{{unknown type}} -size_t s0; // c99-error{{unknown type name 'size_t'}} c11-error{{unknown type}} c23-error{{unknown type}} -rsize_t r0; // c99-error{{unknown type name 'rsize_t'}} c11-error{{unknown type}} c23-error{{unknown type}} -wchar_t wc0; // c99-error{{unknown type name 'wchar_t'}} c11-error{{unknown type}} c23-error{{unknown type}} -void *v0 = NULL; // c99-error{{use of undeclared identifier 'NULL'}} c11-error{{undeclared identifier}} c23-error{{undeclared identifier}} -nullptr_t n0; // c99-error{{unknown type name 'nullptr_t'}} c11-error{{unknown type}} c23-error{{unknown type}} -static void f0(void) { unreachable(); } // c99-error{{call to undeclared function 'unreachable'}} c11-error{{undeclared function}} c23-error{{undeclared identifier}} -max_align_t m0; // c99-error{{unknown type name 'max_align_t'}} c11-error{{unknown type}} c23-error{{unknown type}} +ptrdiff_t p0; // c99-error{{unknown type name 'ptrdiff_t'}} c11-error{{unknown type}} c23-error{{unknown type}} \ + c99-modules-error{{unknown type}} c11-modules-error{{unknown type}} c23-modules-error{{unknown type}} +size_t s0; // c99-error{{unknown type name 'size_t'}} c11-error{{unknown type}} c23-error{{unknown type}} \ + c99-modules-error{{unknown type}} c11-modules-error{{unknown type}} c23-modules-error{{unknown type}} +rsize_t r0; // c99-error{{unknown type name 'rsize_t'}} c11-error{{unknown type}} c23-error{{unknown type}} \ + c99-modules-error{{unknown type}} c11-modules-error{{unknown type}} c23-modules-error{{unknown type}} +wchar_t wc0; // c99-error{{unknown type name 'wchar_t'}} c11-error{{unknown type}} c23-error{{unknown type}} \ + c99-modules-error{{unknown type}} c11-modules-error{{unknown type}} c23-modules-error{{unknown type}} +void *v0 = NULL; // c99-error{{use of undeclared identifier 'NULL'}} c11-error{{undeclared identifier}} c23-error{{undeclared identifier}} \ + c99-modules-error{{undeclared identifier}} c11-modules-error{{undeclared identifier}} c23-modules-error{{undeclared identifier}} +nullptr_t n0; // c99-error{{unknown type name 'nullptr_t'}} c11-error{{unknown type}} c23-error{{unknown type}} \ + c99-modules-error{{unknown type}} c11-modules-error{{unknown type}} c23-modules-error{{unknown type}} +static void f0(void) { unreachable(); } // c99-error{{call to undeclared function 'unreachable'}} c11-error{{undeclared function}} c23-error{{undeclared identifier}} \ + c99-modules-error{{undeclared function}} c11-modules-error{{undeclared function}} c23-modules-error{{undeclared identifier}} +max_align_t m0; // c99-error{{unknown type name 'max_align_t'}} c11-error{{unknown type}} c23-error{{unknown type}} \ + c99-modules-error{{unknown type}} c11-modules-error{{unknown type}} c23-modules-error{{unknown type}} size_t o0 = offsetof(struct astruct, member); // c99-error{{unknown type name 'size_t'}} c99-error{{call to undeclared function 'offsetof'}} c99-error{{expected expression}} c99-error{{use of undeclared identifier 'member'}} \ c11-error{{unknown type}} c11-error{{undeclared function}} c11-error{{expected expression}} c11-error{{undeclared identifier}} \ - c23-error{{unknown type}} c23-error{{undeclared identifier}} c23-error{{expected expression}} c23-error{{undeclared identifier}} -wint_t wi0; // c99-error{{unknown type name 'wint_t'}} c11-error{{unknown type}} c23-error{{unknown type}} + c23-error{{unknown type}} c23-error{{undeclared identifier}} c23-error{{expected expression}} c23-error{{undeclared identifier}} \ + c99-modules-error{{unknown type}} c99-modules-error{{undeclared function}} c99-modules-error{{expected expression}} c99-modules-error{{undeclared identifier}} \ + c11-modules-error{{unknown type}} c11-modules-error{{undeclared function}} c11-modules-error{{expected expression}} c11-modules-error{{undeclared identifier}} \ + c23-modules-error{{unknown type}} c23-modules-error{{undeclared identifier}} c23-modules-error{{expected expression}} c23-modules-error{{undeclared identifier}} +wint_t wi0; // c99-error{{unknown type name 'wint_t'}} c11-error{{unknown type}} c23-error{{unknown type}} \ + c99-modules-error{{unknown type name 'wint_t'}} c11-modules-error{{unknown type}} c23-modules-error{{unknown type}} #include ptrdiff_t p1; size_t s1; -rsize_t r1; // c99-error{{unknown type}} c11-error{{unknown type}} c23-error{{unknown type}} - // c99-note@__stddef_size_t.h:*{{'size_t' declared here}} c11-note@__stddef_size_t.h:*{{'size_t' declared here}} c23-note@__stddef_size_t.h:*{{'size_t' declared here}} +rsize_t r1; // c99-error{{unknown type}} c11-error{{unknown type}} c23-error{{unknown type}} \ + c99-note@__stddef_size_t.h:*{{'size_t' declared here}} c11-note@__stddef_size_t.h:*{{'size_t' declared here}} c23-note@__stddef_size_t.h:*{{'size_t' declared here}} \ + c99-modules-error{{'rsize_t' must be declared before it is used}} c11-modules-error{{must be declared}} c23-modules-error{{must be declared}} \ + c99-modules-note@__stddef_rsize_t.h:*{{declaration here is not visible}} c11-modules-note@__stddef_rsize_t.h:*{{declaration here is not visible}} c23-modules-note@__stddef_rsize_t.h:*{{declaration here is not visible}} wchar_t wc1; void *v1 = NULL; -nullptr_t n1; // c99-error{{unknown type}} c11-error{{unknown type}} -static void f1(void) { unreachable(); } // c99-error{{undeclared function}} c11-error{{undeclared function}} -max_align_t m1; // c99-error{{unknown type}} +nullptr_t n1; // c99-error{{unknown type}} c11-error{{unknown type}} \ + c99-modules-error{{unknown type}} c11-modules-error{{unknown type}} +static void f1(void) { unreachable(); } // c99-error{{undeclared function}} c11-error{{undeclared function}} \ + c99-modules-error{{undeclared function}} c11-modules-error{{undeclared function}} +max_align_t m1; // c99-error{{unknown type}} c99-modules-error{{'max_align_t' must be declared before it is used}} \ + c99-modules-note@__stddef_max_align_t.h:*{{declaration here is not visible}} size_t o1 = offsetof(struct astruct, member); -wint_t wi1; // c99-error{{unknown type}} c11-error{{unknown type}} c23-error{{unknown type}} +wint_t wi1; // c99-error{{unknown type}} c11-error{{unknown type}} c23-error{{unknown type}} \ + c99-modules-error{{unknown type}} c11-modules-error{{unknown type}} c23-modules-error{{unknown type}} // rsize_t needs to be opted into via __STDC_WANT_LIB_EXT1__ >= 1. #define __STDC_WANT_LIB_EXT1__ 1 @@ -39,8 +61,14 @@ size_t s2; rsize_t r2; wchar_t wc2; void *v2 = NULL; -nullptr_t n2; // c99-error{{unknown type}} c11-error{{unknown type}} -static void f2(void) { unreachable(); } // c99-error{{undeclared function}} c11-error{{undeclared function}} +nullptr_t n2; // c99-error{{unknown type}} c11-error{{unknown type}} \ + c99-modules-error{{unknown type}} c11-modules-error{{unknown type}} +static void f2(void) { unreachable(); } // c99-error{{undeclared function}} c11-error{{undeclared function}} \ + c99-modules-error{{undeclared function}} c11-modules-error{{undeclared function}} max_align_t m2; // c99-error{{unknown type}} size_t o2 = offsetof(struct astruct, member); -wint_t wi2; // c99-error{{unknown type}} c11-error{{unknown type}} c23-error{{unknown type}} +wint_t wi2; // c99-error{{unknown type}} c11-error{{unknown type}} c23-error{{unknown type}} \ + c99-modules-error{{unknown type}} c11-modules-error{{unknown type}} c23-modules-error{{unknown type}} + +// m2 and wi2 don't generate errors in modules, the "must be declared before used" +// errors are only emitted the first time the known-but-not-visible type is seen. diff --git a/clang/test/Headers/stddefneeds.c b/clang/test/Headers/stddefneeds.c index dd7ecd0e6028da..fae7d7041d6af5 100644 --- a/clang/test/Headers/stddefneeds.c +++ b/clang/test/Headers/stddefneeds.c @@ -1,36 +1,72 @@ +// RUN: rm -fR %t // RUN: %clang_cc1 -fsyntax-only -verify=c99 -std=c99 %s // RUN: %clang_cc1 -fsyntax-only -verify=c23 -std=c23 %s +// RUN: %clang_cc1 -fsyntax-only -verify=c99-modules -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -std=c99 %s +// RUN: %clang_cc1 -fsyntax-only -verify=c23-modules -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -std=c23 %s // Use C99 to verify that __need_ can be used to get types that wouldn't normally be available. struct astruct { char member; }; -ptrdiff_t p0; // c99-error{{unknown type name 'ptrdiff_t'}} c23-error{{unknown type}} -size_t s0; // c99-error{{unknown type name 'size_t'}} c23-error{{unknown type}} -rsize_t r0; // c99-error{{unknown type name 'rsize_t'}} c23-error{{unknown type}} -wchar_t wc0; // c99-error{{unknown type name 'wchar_t'}} c23-error{{unknown type}} -void *v0 = NULL; // c99-error{{use of undeclared identifier 'NULL'}} c23-error{{undeclared identifier}} -nullptr_t n0; // c99-error{{unknown type name 'nullptr_t'}} c23-error{{unknown type}} -static void f0(void) { unreachable(); } // c99-error{{call to undeclared function 'unreachable'}} c23-error{{undeclared identifier 'unreachable'}} -max_align_t m0; // c99-error{{unknown type name 'max_align_t'}} c23-error{{unknown type}} +ptrdiff_t p0; // c99-error{{unknown type name 'ptrdiff_t'}} c23-error{{unknown type}} \ + c99-modules-error{{unknown type}} c23-modules-error{{unknown type}} +size_t s0; // c99-error{{unknown type name 'size_t'}} c23-error{{unknown type}} \ + c99-modules-error{{unknown type}} c23-modules-error{{unknown type}} +rsize_t r0; // c99-error{{unknown type name 'rsize_t'}} c23-error{{unknown type}} \ + c99-modules-error{{unknown type}} c23-modules-error{{unknown type}} +wchar_t wc0; // c99-error{{unknown type name 'wchar_t'}} c23-error{{unknown type}} \ + c99-modules-error{{unknown type}} c23-modules-error{{unknown type}} +void *v0 = NULL; // c99-error{{use of undeclared identifier 'NULL'}} c23-error{{undeclared identifier}} \ + c99-modules-error{{undeclared identifier}} c23-modules-error{{undeclared identifier}} +nullptr_t n0; // c99-error{{unknown type name 'nullptr_t'}} c23-error{{unknown type}} \ + c99-modules-error{{unknown type}} c23-modules-error{{unknown type}} +static void f0(void) { unreachable(); } // c99-error{{call to undeclared function 'unreachable'}} c23-error{{undeclared identifier 'unreachable'}} \ + c99-modules-error{{undeclared function}} c23-modules-error{{undeclared identifier}} +max_align_t m0; // c99-error{{unknown type name 'max_align_t'}} c23-error{{unknown type}} \ + c99-modules-error{{unknown type}} c23-modules-error{{unknown type}} size_t o0 = offsetof(struct astruct, member); // c99-error{{unknown type name 'size_t'}} c99-error{{call to undeclared function 'offsetof'}} c99-error{{expected expression}} c99-error{{use of undeclared identifier 'member'}} \ - c23-error{{unknown type name 'size_t'}} c23-error{{undeclared identifier 'offsetof'}} c23-error{{expected expression}} c23-error{{use of undeclared identifier 'member'}} -wint_t wi0; // c99-error{{unknown type name 'wint_t'}} c23-error{{unknown type}} + c23-error{{unknown type name 'size_t'}} c23-error{{undeclared identifier 'offsetof'}} c23-error{{expected expression}} c23-error{{use of undeclared identifier 'member'}} \ + c99-modules-error{{unknown type}} c99-modules-error{{undeclared function}} c99-modules-error{{expected expression}} c99-modules-error{{undeclared identifier}} \ + c23-modules-error{{unknown type}} c23-modules-error{{undeclared identifier}} c23-modules-error{{expected expression}} c23-modules-error{{undeclared identifier}} +wint_t wi0; // c99-error{{unknown type name 'wint_t'}} c23-error{{unknown type}} \ + c99-modules-error{{unknown type}} c23-modules-error{{unknown type}} #define __need_ptrdiff_t #include ptrdiff_t p1; -size_t s1; // c99-error{{unknown type}} c23-error{{unknown type}} -rsize_t r1; // c99-error{{unknown type}} c23-error{{unknown type}} -wchar_t wc1; // c99-error{{unknown type}} c23-error{{unknown type}} -void *v1 = NULL; // c99-error{{undeclared identifier}} c23-error{{undeclared identifier}} -nullptr_t n1; // c99-error{{unknown type}} c23-error{{unknown type}} -static void f1(void) { unreachable(); } // c99-error{{undeclared function}} c23-error{{undeclared identifier}} -max_align_t m1; // c99-error{{unknown type}} c23-error{{unknown type}} +size_t s1; // c99-error{{unknown type}} c23-error{{unknown type}} \ + c99-modules-error{{'size_t' must be declared before it is used}} c23-modules-error{{must be declared}} \ + c99-modules-note@__stddef_size_t.h:*{{declaration here is not visible}} c23-modules-note@__stddef_size_t.h:*{{declaration here is not visible}} +rsize_t r1; // c99-error{{unknown type}} c23-error{{unknown type}} \ + c99-modules-error{{'rsize_t' must be declared before it is used}} c23-modules-error{{must be declared}} \ + c99-modules-note@__stddef_rsize_t.h:*{{declaration here is not visible}} c23-modules-note@__stddef_rsize_t.h:*{{declaration here is not visible}} +wchar_t wc1; // c99-error{{unknown type}} c23-error{{unknown type}} \ + c99-modules-error{{'wchar_t' must be declared before it is used}} c23-modules-error{{must be declared}} \ + c99-modules-note@__stddef_wchar_t.h:*{{declaration here is not visible}} c23-modules-note@__stddef_wchar_t.h:*{{declaration here is not visible}} +void *v1 = NULL; // c99-error{{undeclared identifier}} c23-error{{undeclared identifier}} \ + c99-modules-error{{undeclared identifier}} c23-modules-error{{undeclared identifier}} +nullptr_t n1; // c99-error{{unknown type}} c23-error{{unknown type}} \ + c99-modules-error{{unknown type}} c23-modules-error{{'nullptr_t' must be declared before it is used}} \ + c23-modules-note@__stddef_nullptr_t.h:*{{declaration here is not visible}} +static void f1(void) { unreachable(); } // c99-error{{undeclared function}} c23-error{{undeclared identifier}} \ + c99-modules-error{{undeclared function}} c23-modules-error{{undeclared identifier}} +max_align_t m1; // c99-error{{unknown type}} c23-error{{unknown type}} \ + c99-modules-error{{'max_align_t' must be declared before it is used}} c23-modules-error{{must be declared}} \ + c99-modules-note@__stddef_max_align_t.h:*{{declaration here is not visible}} c23-modules-note@__stddef_max_align_t.h:*{{declaration here is not visible}} size_t o1 = offsetof(struct astruct, member); // c99-error{{unknown type}} c99-error{{expected expression}} c99-error{{undeclared identifier}} \ - c23-error{{unknown type}} c23-error{{undeclared identifier}} c23-error{{expected expression}} c23-error{{undeclared identifier}} -wint_t wi1; // c99-error{{unknown type}} c23-error{{unknown type}} + c23-error{{unknown type}} c23-error{{undeclared identifier}} c23-error{{expected expression}} c23-error{{undeclared identifier}} \ + c99-modules-error{{expected expression}} c99-modules-error{{undeclared identifier}} \ + c23-modules-error{{undeclared identifier}} c23-modules-error{{expected expression}} c23-modules-error{{undeclared identifier}} +wint_t wi1; // c99-error{{unknown type}} c23-error{{unknown type}} \ + c99-modules-error{{unknown type}} c23-modules-error{{unknown type}} + +// The "must be declared before used" errors are only emitted the first time a +// known-but-not-visible type is seen. At this point the _Builtin_stddef module +// has been built and all of the types tried, so most of the errors won't be +// repeated below in modules. The types still aren't available, just the errors +// aren't repeated. e.g. rsize_t still isn't available, if r1 above got deleted, +// its error would move to r2 below. #define __need_size_t #include @@ -40,13 +76,19 @@ size_t s2; rsize_t r2; // c99-error{{unknown type}} c23-error{{unknown type}} // c99-note@__stddef_size_t.h:*{{'size_t' declared here}} c23-note@__stddef_size_t.h:*{{'size_t' declared here}} wchar_t wc2; // c99-error{{unknown type}} c23-error{{unknown type}} -void *v2 = NULL; // c99-error{{undeclared identifier}} c23-error{{undeclared identifier}} -nullptr_t n2; // c99-error{{unknown type}} c23-error{{unknown type}} -static void f2(void) { unreachable(); } // c99-error{{undeclared function}} c23-error{{undeclared identifier}} +void *v2 = NULL; // c99-error{{undeclared identifier}} c23-error{{undeclared identifier}} \ + c99-modules-error{{undeclared identifier}} c23-modules-error{{undeclared identifier}} +nullptr_t n2; // c99-error{{unknown type}} c23-error{{unknown type}} \ + c99-modules-error{{unknown type}} +static void f2(void) { unreachable(); } // c99-error{{undeclared function}} c23-error{{undeclared identifier}} \ + c99-modules-error{{undeclared function}} c23-modules-error{{undeclared identifier}} max_align_t m2; // c99-error{{unknown type}} c23-error{{unknown type}} size_t o2 = offsetof(struct astruct, member); // c99-error{{expected expression}} c99-error{{undeclared identifier}} \ - c23-error{{undeclared identifier}} c23-error{{expected expression}} c23-error{{undeclared identifier}} -wint_t wi2; // c99-error{{unknown type}} c23-error{{unknown type}} + c23-error{{undeclared identifier}} c23-error{{expected expression}} c23-error{{undeclared identifier}} \ + c99-modules-error{{expected expression}} c99-modules-error{{undeclared identifier}} \ + c23-modules-error{{undeclared identifier}} c23-modules-error{{expected expression}} c23-modules-error{{undeclared identifier}} +wint_t wi2; // c99-error{{unknown type}} c23-error{{unknown type}} \ + c99-modules-error{{unknown type}} c23-modules-error{{unknown type}} #define __need_rsize_t #include @@ -55,13 +97,19 @@ ptrdiff_t p3; size_t s3; rsize_t r3; wchar_t wc3; // c99-error{{unknown type}} c23-error{{unknown type}} -void *v3 = NULL; // c99-error{{undeclared identifier}} c23-error{{undeclared identifier}} -nullptr_t n3; // c99-error{{unknown type}} c23-error{{unknown type}} -static void f3(void) { unreachable(); } // c99-error{{undeclared function}} c23-error{{undeclared identifier}} +void *v3 = NULL; // c99-error{{undeclared identifier}} c23-error{{undeclared identifier}} \ + c99-modules-error{{undeclared identifier}} c23-modules-error{{undeclared identifier}} +nullptr_t n3; // c99-error{{unknown type}} c23-error{{unknown type}} \ + c99-modules-error{{unknown type}} +static void f3(void) { unreachable(); } // c99-error{{undeclared function}} c23-error{{undeclared identifier}} \ + c99-modules-error{{undeclared function}} c23-modules-error{{undeclared identifier}} max_align_t m3; // c99-error{{unknown type}} c23-error{{unknown type}} size_t o3 = offsetof(struct astruct, member); // c99-error{{expected expression}} c99-error{{undeclared identifier}} \ - c23-error{{undeclared identifier}} c23-error{{expected expression}} c23-error{{undeclared identifier}} -wint_t wi3; // c99-error{{unknown type}} c23-error{{unknown type}} + c23-error{{undeclared identifier}} c23-error{{expected expression}} c23-error{{undeclared identifier}} \ + c99-modules-error{{expected expression}} c99-modules-error{{undeclared identifier}} \ + c23-modules-error{{undeclared identifier}} c23-modules-error{{expected expression}} c23-modules-error{{undeclared identifier}} +wint_t wi3; // c99-error{{unknown type}} c23-error{{unknown type}} \ + c99-modules-error{{unknown type}} c23-modules-error{{unknown type}} #define __need_wchar_t #include @@ -70,13 +118,19 @@ ptrdiff_t p4; size_t s4; rsize_t r4; wchar_t wc4; -void *v4 = NULL; // c99-error{{undeclared identifier}} c23-error{{undeclared identifier}} -nullptr_t n4; // c99-error{{unknown type}} c23-error{{unknown type}} -static void f4(void) { unreachable(); } // c99-error{{undeclared function}} c23-error{{undeclared identifier}} +void *v4 = NULL; // c99-error{{undeclared identifier}} c23-error{{undeclared identifier}} \ + c99-modules-error{{undeclared identifier}} c23-modules-error{{undeclared identifier}} +nullptr_t n4; // c99-error{{unknown type}} c23-error{{unknown type}} \ + c99-modules-error{{unknown type}} +static void f4(void) { unreachable(); } // c99-error{{undeclared function}} c23-error{{undeclared identifier}} \ + c99-modules-error{{undeclared function}} c23-modules-error{{undeclared identifier}} max_align_t m4; // c99-error{{unknown type}} c23-error{{unknown type}} size_t o4 = offsetof(struct astruct, member); // c99-error{{expected expression}} c99-error{{undeclared identifier}} \ - c23-error{{undeclared identifier}} c23-error{{expected expression}} c23-error{{undeclared identifier}} -wint_t wi4; // c99-error{{unknown type}} c23-error{{unknown type}} + c23-error{{undeclared identifier}} c23-error{{expected expression}} c23-error{{undeclared identifier}} \ + c99-modules-error{{expected expression}} c99-modules-error{{undeclared identifier}} \ + c23-modules-error{{undeclared identifier}} c23-modules-error{{expected expression}} c23-modules-error{{undeclared identifier}} +wint_t wi4; // c99-error{{unknown type}} c23-error{{unknown type}} \ + c99-modules-error{{unknown type}} c23-modules-error{{unknown type}} #define __need_NULL #include @@ -86,29 +140,38 @@ size_t s5; rsize_t r5; wchar_t wc5; void *v5 = NULL; -nullptr_t n5; // c99-error{{unknown type}} c23-error{{unknown type}} -static void f5(void) { unreachable(); } // c99-error{{undeclared function}} c23-error{{undeclared identifier}} +nullptr_t n5; // c99-error{{unknown type}} c23-error{{unknown type}} \ + c99-modules-error{{unknown type}} +static void f5(void) { unreachable(); } // c99-error{{undeclared function}} c23-error{{undeclared identifier}} \ + c99-modules-error{{undeclared function}} c23-modules-error{{undeclared identifier}} max_align_t m5; // c99-error{{unknown type}} c23-error{{unknown type}} size_t o5 = offsetof(struct astruct, member); // c99-error{{expected expression}} c99-error{{undeclared identifier}} \ - c23-error{{undeclared identifier}} c23-error{{expected expression}} c23-error{{undeclared identifier}} -wint_t wi5; // c99-error{{unknown type}} c23-error{{unknown type}} + c23-error{{undeclared identifier}} c23-error{{expected expression}} c23-error{{undeclared identifier}} \ + c99-modules-error{{expected expression}} c99-modules-error{{undeclared identifier}} \ + c23-modules-error{{undeclared identifier}} c23-modules-error{{expected expression}} c23-modules-error{{undeclared identifier}} +wint_t wi5; // c99-error{{unknown type}} c23-error{{unknown type}} \ + c99-modules-error{{unknown type}} c23-modules-error{{unknown type}} -// __need_nullptr_t generates an error in // c99-error@__stddef_nullptr_t.h:*{{expected function body}} +#include ptrdiff_t p6; size_t s6; rsize_t r6; wchar_t wc6; void *v6 = NULL; -nullptr_t n6; // c99-error{{unknown type}} -static void f6(void) { unreachable(); } // c99-error{{undeclared function}} c23-error{{undeclared identifier}} +nullptr_t n6; // c99-error{{unknown type}} c99-modules-error{{unknown type}} +static void f6(void) { unreachable(); } // c99-error{{undeclared function}} c23-error{{undeclared identifier}} \ + c99-modules-error{{undeclared function}} c23-modules-error{{undeclared identifier}} max_align_t m6; // c99-error{{unknown type}} c23-error{{unknown type}} size_t o6 = offsetof(struct astruct, member); // c99-error{{expected expression}} c99-error{{undeclared identifier}} \ - c23-error{{undeclared identifier}} c23-error{{expected expression}} c23-error{{undeclared identifier}} -wint_t wi6; // c99-error{{unknown type}} c23-error{{unknown type}} + c23-error{{undeclared identifier}} c23-error{{expected expression}} c23-error{{undeclared identifier}} \ + c99-modules-error{{expected expression}} c99-modules-error{{undeclared identifier}} \ + c23-modules-error{{undeclared identifier}} c23-modules-error{{expected expression}} c23-modules-error{{undeclared identifier}} +wint_t wi6; // c99-error{{unknown type}} c23-error{{unknown type}} \ + c99-modules-error{{unknown type}} c23-modules-error{{unknown type}} #define __need_unreachable #include @@ -118,12 +181,15 @@ size_t s7; rsize_t r7; wchar_t wc7; void *v7 = NULL; -nullptr_t n7 ; // c99-error{{unknown type}} +nullptr_t n7 ; // c99-error{{unknown type}} c99-modules-error{{unknown type}} static void f7(void) { unreachable(); } max_align_t m7; // c99-error{{unknown type}} c23-error{{unknown type}} size_t o7 = offsetof(struct astruct, member); // c99-error{{expected expression}} c99-error{{undeclared identifier}} \ - c23-error{{undeclared identifier}} c23-error{{expected expression}} c23-error{{undeclared identifier}} -wint_t wi7; // c99-error{{unknown type}} c23-error{{unknown type}} + c23-error{{undeclared identifier}} c23-error{{expected expression}} c23-error{{undeclared identifier}} \ + c99-modules-error{{expected expression}} c99-modules-error{{undeclared identifier}} \ + c23-modules-error{{undeclared identifier}} c23-modules-error{{expected expression}} c23-modules-error{{undeclared identifier}} +wint_t wi7; // c99-error{{unknown type}} c23-error{{unknown type}} \ + c99-modules-error{{unknown type}} c23-modules-error{{unknown type}} #define __need_max_align_t #include @@ -133,12 +199,15 @@ size_t s8; rsize_t r8; wchar_t wc8; void *v8 = NULL; -nullptr_t n8; // c99-error{{unknown type}} +nullptr_t n8; // c99-error{{unknown type}} c99-modules-error{{unknown type}} static void f8(void) { unreachable(); } max_align_t m8; size_t o8 = offsetof(struct astruct, member); // c99-error{{expected expression}} c99-error{{undeclared identifier}} \ - c23-error{{undeclared identifier}} c23-error{{expected expression}} c23-error{{undeclared identifier}} -wint_t wi8; // c99-error{{unknown type}} c23-error{{unknown type}} + c23-error{{undeclared identifier}} c23-error{{expected expression}} c23-error{{undeclared identifier}} \ + c99-modules-error{{expected expression}} c99-modules-error{{undeclared identifier}} \ + c23-modules-error{{undeclared identifier}} c23-modules-error{{expected expression}} c23-modules-error{{undeclared identifier}} +wint_t wi8; // c99-error{{unknown type}} c23-error{{unknown type}} \ + c99-modules-error{{unknown type}} c23-modules-error{{unknown type}} #define __need_offsetof #include @@ -146,13 +215,14 @@ wint_t wi8; // c99-error{{unknown type}} c23-error{{unknown type}} ptrdiff_t p9; size_t s9; rsize_t r9; -nullptr_t n9; // c99-error{{unknown type}} +nullptr_t n9; // c99-error{{unknown type}} c99-modules-error{{unknown type}} static void f9(void) { unreachable(); } wchar_t wc9; void *v9 = NULL; max_align_t m9; size_t o9 = offsetof(struct astruct, member); -wint_t wi9; // c99-error{{unknown type}} c23-error{{unknown type}} +wint_t wi9; // c99-error{{unknown type}} c23-error{{unknown type}} \ + c99-modules-error{{unknown type}} c23-modules-error{{unknown type}} #define __need_wint_t #include @@ -162,7 +232,7 @@ size_t s10; rsize_t r10; wchar_t wc10; void *v10 = NULL; -nullptr_t n10; // c99-error{{unknown type}} +nullptr_t n10; // c99-error{{unknown type}} c99-modules-error{{unknown type}} static void f10(void) { unreachable(); } max_align_t m10; size_t o10 = offsetof(struct astruct, member); diff --git a/clang/test/Interpreter/const.cpp b/clang/test/Interpreter/const.cpp new file mode 100644 index 00000000000000..4b6ce65e3643e6 --- /dev/null +++ b/clang/test/Interpreter/const.cpp @@ -0,0 +1,32 @@ +// UNSUPPORTED: system-aix +// see https://github.com/llvm/llvm-project/issues/68092 +// XFAIL: system-windows + +// RUN: cat %s | clang-repl | FileCheck %s +// RUN: cat %s | clang-repl -Xcc -O2 | FileCheck %s + +extern "C" int printf(const char*, ...); + +struct A { int val; A(int v); ~A(); void f() const; }; +A::A(int v) : val(v) { printf("A(%d), this = %p\n", val, this); } +A::~A() { printf("~A, this = %p, val = %d\n", this, val); } +void A::f() const { printf("f: this = %p, val = %d\n", this, val); } + +const A a(1); +// CHECK: A(1), this = [[THIS:.+]] +// The constructor must only be called once! +// CHECK-NOT: A(1) + +a.f(); +// CHECK-NEXT: f: this = [[THIS]], val = 1 +a.f(); +// CHECK-NEXT: f: this = [[THIS]], val = 1 + +%quit +// There must still be no other constructor! +// CHECK-NOT: A(1) + +// At the end, we expect exactly one destructor call +// CHECK: ~A +// CHECK-SAME: this = [[THIS]], val = 1 +// CHECK-NOT: ~A diff --git a/clang/test/Lexer/cxx1z-trigraphs.cpp b/clang/test/Lexer/cxx1z-trigraphs.cpp index 2e47c05e9bd33b..6b39ff6716605b 100644 --- a/clang/test/Lexer/cxx1z-trigraphs.cpp +++ b/clang/test/Lexer/cxx1z-trigraphs.cpp @@ -21,7 +21,7 @@ error here; #if !ENABLED_TRIGRAPHS // expected-error@11 {{}} expected-warning@11 {{trigraph ignored}} -// expected-error@13 {{failed}} expected-warning@13 {{trigraph ignored}} expected-note@13 {{evaluates to ''?' == '#''}} +// expected-error@13 {{failed}} expected-warning@13 {{trigraph ignored}} expected-note@13 {{evaluates to ''?' (0x3F, 63) == '#' (0x23, 35)'}} // expected-error@16 {{}} // expected-error@20 {{}} #else diff --git a/clang/test/Misc/misc-source-ranges.cpp b/clang/test/Misc/misc-source-ranges.cpp new file mode 100644 index 00000000000000..7a9d9d057dac40 --- /dev/null +++ b/clang/test/Misc/misc-source-ranges.cpp @@ -0,0 +1,7 @@ +// RUN: not %clang_cc1 -fsyntax-only -fdiagnostics-print-source-range-info %s 2>&1 | FileCheck %s + +struct S { + char a : 12 - 12; +}; +// CHECK: misc-source-ranges.cpp:[[@LINE-2]]:8:{[[@LINE-2]]:12-[[@LINE-2]]:19} + diff --git a/clang/test/Misc/pragma-attribute-supported-attributes-list.test b/clang/test/Misc/pragma-attribute-supported-attributes-list.test index eaf6d34421bbe0..f48126775c8685 100644 --- a/clang/test/Misc/pragma-attribute-supported-attributes-list.test +++ b/clang/test/Misc/pragma-attribute-supported-attributes-list.test @@ -56,6 +56,7 @@ // CHECK-NEXT: ConsumableAutoCast (SubjectMatchRule_record) // CHECK-NEXT: ConsumableSetOnRead (SubjectMatchRule_record) // CHECK-NEXT: Convergent (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/builtin-headers/builtin-modules.modulemap b/clang/test/Modules/Inputs/builtin-headers/builtin-modules.modulemap new file mode 100644 index 00000000000000..0fbb454dbb0223 --- /dev/null +++ b/clang/test/Modules/Inputs/builtin-headers/builtin-modules.modulemap @@ -0,0 +1,29 @@ +module c_complex [system] { + header "complex.h" + export * +} + +module c_float [system] { + header "float.h" + export * +} + +module c_inttypes [system] { + header "inttypes.h" + export * +} + +module c_limits [system] { + header "limits.h" + export * +} + +module c_math [system] { + header "math.h" + export * +} + +module c_stdint [system] { + header "stdint.h" + export * +} diff --git a/clang/test/Modules/Inputs/builtin-headers/c++/module.modulemap b/clang/test/Modules/Inputs/builtin-headers/c++/module.modulemap new file mode 100644 index 00000000000000..c969f067a234f0 --- /dev/null +++ b/clang/test/Modules/Inputs/builtin-headers/c++/module.modulemap @@ -0,0 +1,4 @@ +module cpp_stdint [system] { + header "stdint.h" + export * +} diff --git a/clang/test/Modules/Inputs/builtin-headers/c++/stdint.h b/clang/test/Modules/Inputs/builtin-headers/c++/stdint.h new file mode 100644 index 00000000000000..22cebacfdb64e4 --- /dev/null +++ b/clang/test/Modules/Inputs/builtin-headers/c++/stdint.h @@ -0,0 +1,6 @@ +#ifndef CPP_STDINT_H +#define CPP_STDINT_H + +#include_next + +#endif diff --git a/clang/test/Modules/Inputs/builtin-headers/complex.h b/clang/test/Modules/Inputs/builtin-headers/complex.h new file mode 100644 index 00000000000000..b6ef3c5a35b450 --- /dev/null +++ b/clang/test/Modules/Inputs/builtin-headers/complex.h @@ -0,0 +1 @@ +// Required by tgmath.h diff --git a/clang/test/Modules/Inputs/builtin-headers/float.h b/clang/test/Modules/Inputs/builtin-headers/float.h new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/clang/test/Modules/Inputs/builtin-headers/inttypes.h b/clang/test/Modules/Inputs/builtin-headers/inttypes.h new file mode 100644 index 00000000000000..ddb6bb83b57238 --- /dev/null +++ b/clang/test/Modules/Inputs/builtin-headers/inttypes.h @@ -0,0 +1,12 @@ +#ifndef INTTYPES_H +#define INTTYPES_H + +// This creates an include cycle when inttypes.h and stdint.h +// are both part of the cstd module. This include will resolve +// to the C++ stdint.h, which will #include_next eventually to +// the stdint.h in this directory, and thus create the cycle +// cstd (inttypes.h) -> cpp_stdint (stdint.h) -> cstd (stdint.h). +// This cycle is worked around by cstd using [no_undeclared_includes]. +#include + +#endif diff --git a/clang/test/Modules/Inputs/builtin-headers/limits.h b/clang/test/Modules/Inputs/builtin-headers/limits.h new file mode 100644 index 00000000000000..8b137891791fe9 --- /dev/null +++ b/clang/test/Modules/Inputs/builtin-headers/limits.h @@ -0,0 +1 @@ + diff --git a/clang/test/Modules/Inputs/builtin-headers/math.h b/clang/test/Modules/Inputs/builtin-headers/math.h new file mode 100644 index 00000000000000..b6ef3c5a35b450 --- /dev/null +++ b/clang/test/Modules/Inputs/builtin-headers/math.h @@ -0,0 +1 @@ +// Required by tgmath.h diff --git a/clang/test/Modules/Inputs/builtin-headers/stdint.h b/clang/test/Modules/Inputs/builtin-headers/stdint.h new file mode 100644 index 00000000000000..8f233fd7f45d6d --- /dev/null +++ b/clang/test/Modules/Inputs/builtin-headers/stdint.h @@ -0,0 +1,34 @@ +#ifndef STDINT_H +#define STDINT_H + +// types needed by stdatomic.h + +typedef char int_least8_t; +typedef short int_least16_t; +typedef int int_least32_t; +typedef long long int int_least64_t; +typedef unsigned char uint_least8_t; +typedef unsigned short uint_least16_t; +typedef unsigned int uint_least32_t; +typedef unsigned long long uint_least64_t; + +typedef char int_fast8_t; +typedef short int_fast16_t; +typedef int int_fast32_t; +typedef long long int int_fast64_t; +typedef unsigned char uint_fast8_t; +typedef unsigned short uint_fast16_t; +typedef unsigned int uint_fast32_t; +typedef unsigned long long uint_fast64_t; + +typedef int intptr_t; +typedef unsigned int uintptr_t; +typedef int intmax_t; +typedef unsigned int uintmax_t; + +// additional types for unwind.h + +typedef unsigned int uint32_t; +typedef unsigned long long uint64_t; + +#endif diff --git a/clang/test/Modules/Inputs/builtin-headers/system-modules.modulemap b/clang/test/Modules/Inputs/builtin-headers/system-modules.modulemap new file mode 100644 index 00000000000000..0161ff80fe6189 --- /dev/null +++ b/clang/test/Modules/Inputs/builtin-headers/system-modules.modulemap @@ -0,0 +1,71 @@ +module cstd [system] [no_undeclared_includes] { + module complex { + header "complex.h" + export * + } + + module float { + header "float.h" + export * + } + + module inttypes { + header "inttypes.h" + export * + } + + module iso646 { + header "iso646.h" + export * + } + + module limits { + header "limits.h" + export * + } + + module math { + header "math.h" + export * + } + + module stdalign { + header "stdalign.h" + export * + } + + module stdarg { + header "stdarg.h" + export * + } + + module stdatomic { + header "stdatomic.h" + export * + } + + module stdbool { + header "stdbool.h" + export * + } + + module stddef { + header "stddef.h" + export * + } + + module stdint { + header "stdint.h" + export * + } + + module tgmath { + header "tgmath.h" + export * + } + + module unwind { + header "unwind.h" + export * + } +} diff --git a/clang/test/Modules/builtin-headers.mm b/clang/test/Modules/builtin-headers.mm new file mode 100644 index 00000000000000..4c9ddec4e99c28 --- /dev/null +++ b/clang/test/Modules/builtin-headers.mm @@ -0,0 +1,41 @@ +// RUN: rm -rf %t +// RUN: %clang_cc1 -cxx-isystem %S/Inputs/builtin-headers/c++ -internal-isystem %S/Inputs/builtin-headers -fsyntax-only -fmodules -fmodules-cache-path=%t -fmodule-map-file=%S/Inputs/builtin-headers/c++/module.modulemap -fmodule-map-file=%resource_dir/module.modulemap -fmodule-map-file=%S/Inputs/builtin-headers/system-modules.modulemap -fbuiltin-headers-in-system-modules -DSYSTEM_MODULES %s -verify +// RUN: rm -rf %t +// RUN: %clang_cc1 -cxx-isystem %S/Inputs/builtin-headers/c++ -internal-isystem %S/Inputs/builtin-headers -fsyntax-only -fmodules -fmodules-cache-path=%t -fmodule-map-file=%S/Inputs/builtin-headers/c++/module.modulemap -fmodule-map-file=%resource_dir/module.modulemap -fmodule-map-file=%S/Inputs/builtin-headers/builtin-modules.modulemap %s -verify + +// expected-no-diagnostics + +@import cpp_stdint; + +// The builtin modules are always available, though they're mostly +// empty if -fbuiltin-headers-in-system-modules is used. +@import _Builtin_float; +@import _Builtin_inttypes; +@import _Builtin_iso646; +@import _Builtin_limits; +@import _Builtin_stdalign; +@import _Builtin_stdarg; +@import _Builtin_stdatomic; +@import _Builtin_stdbool; +@import _Builtin_stddef; +@import _Builtin_stdint; +@import _Builtin_stdnoreturn; +@import _Builtin_tgmath; +@import _Builtin_unwind; + +#ifdef SYSTEM_MODULES +// system-modules.modulemap uses the "mega module" style with +// -fbuiltin-headers-in-system-modules, and its modules cover +// the clang builtin headers. +@import cstd; +#else +// builtin-modules.modulemap uses top level modules for each +// of its headers, which allows interleaving with the builtin +// modules and libc++ modules. +@import c_complex; +@import c_float; +@import c_inttypes; +@import c_limits; +@import c_math; +@import c_stdint; +#endif diff --git a/clang/test/Modules/module-init-duplicated-import.cppm b/clang/test/Modules/module-init-duplicated-import.cppm new file mode 100644 index 00000000000000..de0ce1962f1008 --- /dev/null +++ b/clang/test/Modules/module-init-duplicated-import.cppm @@ -0,0 +1,27 @@ +// RUN: rm -rf %t +// RUN: split-file %s %t +// RUN: cd %t +// +// 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: %clang_cc1 -triple %itanium_abi_triple -std=c++20 %t/m.pcm \ +// RUN: -S -emit-llvm -o - | FileCheck %t/m.cppm + +//--- a.cppm +export module a; +export struct A { + A(){}; +}; +export A __dynamic_inited_a; + +//--- m.cppm +export module m; +import a; +export import a; + + +// CHECK: define void @_ZGIW1m +// CHECK: store i8 1, ptr @_ZGIW1m__in_chrg +// CHECK: call{{.*}}@_ZGIW1a diff --git a/clang/test/Modules/pr67893.cppm b/clang/test/Modules/pr67893.cppm new file mode 100644 index 00000000000000..7d4e4c1dc5d843 --- /dev/null +++ b/clang/test/Modules/pr67893.cppm @@ -0,0 +1,29 @@ +// RUN: rm -rf %t +// RUN: split-file %s %t +// RUN: cd %t +// +// 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: %clang_cc1 -triple %itanium_abi_triple -std=c++20 %t/m.pcm \ +// RUN: -S -emit-llvm -o - | FileCheck %t/m.cppm + +//--- a.cppm +export module a; +export struct A { + A(){}; +}; +export A __dynamic_inited_a; + +//--- m.cppm +module; +import a; +export module m; +import a; +module :private; +import a; + +// CHECK: define void @_ZGIW1m +// CHECK: store i8 1, ptr @_ZGIW1m__in_chrg +// CHECK: call{{.*}}@_ZGIW1a diff --git a/clang/test/Modules/stddef.c b/clang/test/Modules/stddef.c index 6704abffbf0b7d..5bc0d1e44c8563 100644 --- a/clang/test/Modules/stddef.c +++ b/clang/test/Modules/stddef.c @@ -1,13 +1,29 @@ // RUN: rm -rf %t // RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fbuiltin-headers-in-system-modules -fmodules-cache-path=%t -I%S/Inputs/StdDef %s -verify -fno-modules-error-recovery +// RUN: rm -rf %t +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -I%S/Inputs/StdDef %s -verify -fno-modules-error-recovery #include "ptrdiff_t.h" ptrdiff_t pdt; -size_t st; // expected-error {{missing '#include "include_again.h"'; 'size_t' must be declared before it is used}} -// expected-note@__stddef_size_t.h:* {{here}} +// size_t is declared in both size_t.h and __stddef_size_t.h, both of which are +// modular headers. Regardless of whether stddef.h joins the StdDef test module +// or is in its _Builtin_stddef module, __stddef_size_t.h will be in +// _Builtin_stddef.size_t. It's not defined which module will win as the expected +// provider of size_t. For the purposes of this test it doesn't matter which header +// gets reported, just as long as it isn't other.h or include_again.h. +size_t st; // expected-error-re {{missing '#include "{{size_t|__stddef_size_t}}.h"'; 'size_t' must be declared before it is used}} +// expected-note@size_t.h:* 0+ {{here}} +// expected-note@__stddef_size_t.h:* 0+ {{here}} #include "include_again.h" +// Includes which includes <__stddef_size_t.h> which imports the +// _Builtin_stddef.size_t module. size_t st2; + +#include "size_t.h" +// Redeclares size_t, but the type merger should figure it out. + +size_t st3; diff --git a/clang/test/Modules/stddef.m b/clang/test/Modules/stddef.m index 1ff6ff73796abe..855464afe61af1 100644 --- a/clang/test/Modules/stddef.m +++ b/clang/test/Modules/stddef.m @@ -4,4 +4,6 @@ // RUN: rm -rf %t // RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fbuiltin-headers-in-system-modules -fmodules-cache-path=%t -I %S/Inputs/StdDef %s -verify +// RUN: rm -rf %t +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -I %S/Inputs/StdDef %s -verify // expected-no-diagnostics diff --git a/clang/test/OpenMP/declare_target_codegen.cpp b/clang/test/OpenMP/declare_target_codegen.cpp index 71c742198af6bf..225695feae9515 100644 --- a/clang/test/OpenMP/declare_target_codegen.cpp +++ b/clang/test/OpenMP/declare_target_codegen.cpp @@ -31,7 +31,7 @@ // CHECK-DAG: @dy = {{protected | }}global i32 0, // CHECK-DAG: @bbb = {{protected | }}global i32 0, // CHECK-DAG: weak constant %struct.__tgt_offload_entry { ptr @bbb, -// CHECK-DAG: @ccc = external global i32, +// CHECK-DAG: @ccc = external {{protected | }}global i32, // CHECK-DAG: @ddd = {{protected | }}global i32 0, // CHECK-DAG: @hhh_decl_tgt_ref_ptr = weak global ptr null // CHECK-DAG: @ggg_decl_tgt_ref_ptr = weak global ptr null diff --git a/clang/test/OpenMP/declare_target_constexpr_codegen.cpp b/clang/test/OpenMP/declare_target_constexpr_codegen.cpp index 0acd98129394b8..2b256cd6a4c7f0 100644 --- a/clang/test/OpenMP/declare_target_constexpr_codegen.cpp +++ b/clang/test/OpenMP/declare_target_constexpr_codegen.cpp @@ -16,7 +16,7 @@ class A { public: static constexpr double pi = 3.141592653589793116; //. -// CHECK: @_ZN1A2piE = linkonce_odr constant double 0x400921FB54442D18, comdat, align 8 +// CHECK: @_ZN1A2piE = linkonce_odr protected constant double 0x400921FB54442D18, comdat, align 8 // CHECK: @_ZL9anotherPi = internal constant double 3.140000e+00, align 8 // CHECK: @llvm.compiler.used = appending global [2 x ptr] [ptr @"__ZN1A2piE$ref", ptr @"__ZL9anotherPi$ref"], section "llvm.metadata" //. diff --git a/clang/test/OpenMP/nvptx_target_teams_ompx_bare_codegen.cpp b/clang/test/OpenMP/nvptx_target_teams_ompx_bare_codegen.cpp new file mode 100644 index 00000000000000..e0fe9eb76a6f17 --- /dev/null +++ b/clang/test/OpenMP/nvptx_target_teams_ompx_bare_codegen.cpp @@ -0,0 +1,56 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --function-signature --include-generated-funcs --replace-value-regex "__omp_offloading_[0-9a-z]+_[0-9a-z]+" "reduction_size[.].+[.]" "pl_cond[.].+[.|,]" --prefix-filecheck-ir-name _ +// Test target codegen - host bc file has to be created first. +// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm-bc %s -o %t-ppc-host.bc +// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple nvptx64-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-target-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s +// expected-no-diagnostics +#ifndef HEADER +#define HEADER + +template +tx ftemplate(int n) { + tx a = 0; + + #pragma omp target teams ompx_bare + { + a = 2; + } + + return a; +} + +int bar(int n){ + int a = 0; + + a += ftemplate(n); + + return a; +} + +#endif +// CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z9ftemplateIcET_i_l13 +// CHECK-SAME: (i64 noundef [[A:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i64, align 8 +// CHECK-NEXT: [[A_CASTED:%.*]] = alloca i64, align 8 +// CHECK-NEXT: [[DOTZERO_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: store i64 [[A]], ptr [[A_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[A_ADDR]], align 1 +// CHECK-NEXT: store i8 [[TMP0]], ptr [[A_CASTED]], align 1 +// CHECK-NEXT: [[TMP1:%.*]] = load i64, ptr [[A_CASTED]], align 8 +// CHECK-NEXT: store i32 0, ptr [[DOTZERO_ADDR]], align 4 +// CHECK-NEXT: call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z9ftemplateIcET_i_l13_omp_outlined(ptr null, ptr [[DOTZERO_ADDR]], i64 [[TMP1]]) #[[ATTR2:[0-9]+]] +// CHECK-NEXT: ret void +// +// +// CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z9ftemplateIcET_i_l13_omp_outlined +// CHECK-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], i64 noundef [[A:%.*]]) #[[ATTR1:[0-9]+]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i64, align 8 +// CHECK-NEXT: store ptr [[DOTGLOBAL_TID_]], ptr [[DOTGLOBAL_TID__ADDR]], align 8 +// CHECK-NEXT: store ptr [[DOTBOUND_TID_]], ptr [[DOTBOUND_TID__ADDR]], align 8 +// CHECK-NEXT: store i64 [[A]], ptr [[A_ADDR]], align 8 +// CHECK-NEXT: store i8 2, ptr [[A_ADDR]], align 1 +// CHECK-NEXT: ret void +// diff --git a/clang/test/OpenMP/ompx_bare_messages.c b/clang/test/OpenMP/ompx_bare_messages.c new file mode 100644 index 00000000000000..a1b3c380285287 --- /dev/null +++ b/clang/test/OpenMP/ompx_bare_messages.c @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -verify -fopenmp -triple x86_64-unknown-unknown %s + // RUN: %clang_cc1 -verify -fopenmp-simd -triple x86_64-unknown-unknown %s + // RUN: %clang_cc1 -verify -fopenmp -triple x86_64-unknown-unknown -fopenmp-targets=nvptx64 %s + +void foo() { +} + +void bar() { +#pragma omp target ompx_bare // expected-error {{unexpected OpenMP clause 'ompx_bare' in directive '#pragma omp target'}} expected-note {{OpenMP extension clause 'ompx_bare' only allowed with '#pragma omp target teams'}} + foo(); + +#pragma omp target teams distribute ompx_bare // expected-error {{unexpected OpenMP clause 'ompx_bare' in directive '#pragma omp target teams distribute'}} expected-note {{OpenMP extension clause 'ompx_bare' only allowed with '#pragma omp target teams'}} + for (int i = 0; i < 10; ++i) {} + +#pragma omp target teams distribute parallel for ompx_bare // expected-error {{unexpected OpenMP clause 'ompx_bare' in directive '#pragma omp target teams distribute parallel for'}} expected-note {{OpenMP extension clause 'ompx_bare' only allowed with '#pragma omp target teams'}} + for (int i = 0; i < 10; ++i) {} + +#pragma omp target +#pragma omp teams ompx_bare // expected-error {{unexpected OpenMP clause 'ompx_bare' in directive '#pragma omp teams'}} expected-note {{OpenMP extension clause 'ompx_bare' only allowed with '#pragma omp target teams'}} + foo(); +} diff --git a/clang/test/OpenMP/target_teams_ast_print.cpp b/clang/test/OpenMP/target_teams_ast_print.cpp index 19943a81eab8ef..5f1040be01a25f 100644 --- a/clang/test/OpenMP/target_teams_ast_print.cpp +++ b/clang/test/OpenMP/target_teams_ast_print.cpp @@ -111,6 +111,10 @@ int main (int argc, char **argv) { // CHECK-NEXT: #pragma omp target teams a=2; // CHECK-NEXT: a = 2; +#pragma omp target teams ompx_bare +// CHECK-NEXT: #pragma omp target teams ompx_bare + a=3; +// CHECK-NEXT: a = 3; #pragma omp target teams default(none), private(argc,b) num_teams(f) firstprivate(argv) reduction(| : c, d) reduction(* : e) thread_limit(f+g) // CHECK-NEXT: #pragma omp target teams default(none) private(argc,b) num_teams(f) firstprivate(argv) reduction(|: c,d) reduction(*: e) thread_limit(f + g) foo(); diff --git a/clang/test/OpenMP/target_teams_codegen.cpp b/clang/test/OpenMP/target_teams_codegen.cpp index 5c32a79bb64b04..3185d90b5ef14c 100644 --- a/clang/test/OpenMP/target_teams_codegen.cpp +++ b/clang/test/OpenMP/target_teams_codegen.cpp @@ -121,6 +121,12 @@ int foo(int n) { aa += 1; } + #pragma omp target teams ompx_bare + { + a += 1; + aa += 1; + } + // We capture 3 VLA sizes in this target region @@ -336,22 +342,28 @@ int bar(int n){ // CHECK1-NEXT: [[DOTOFFLOAD_MAPPERS12:%.*]] = alloca [2 x ptr], align 8 // CHECK1-NEXT: [[KERNEL_ARGS13:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK1-NEXT: [[A_CASTED16:%.*]] = alloca i64, align 8 -// CHECK1-NEXT: [[DOTOFFLOAD_BASEPTRS19:%.*]] = alloca [9 x ptr], align 8 -// CHECK1-NEXT: [[DOTOFFLOAD_PTRS20:%.*]] = alloca [9 x ptr], align 8 -// CHECK1-NEXT: [[DOTOFFLOAD_MAPPERS21:%.*]] = alloca [9 x ptr], align 8 +// CHECK1-NEXT: [[AA_CASTED17:%.*]] = alloca i64, align 8 +// CHECK1-NEXT: [[DOTOFFLOAD_BASEPTRS18:%.*]] = alloca [2 x ptr], align 8 +// CHECK1-NEXT: [[DOTOFFLOAD_PTRS19:%.*]] = alloca [2 x ptr], align 8 +// CHECK1-NEXT: [[DOTOFFLOAD_MAPPERS20:%.*]] = alloca [2 x ptr], align 8 +// CHECK1-NEXT: [[KERNEL_ARGS21:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 +// CHECK1-NEXT: [[A_CASTED24:%.*]] = alloca i64, align 8 +// CHECK1-NEXT: [[DOTOFFLOAD_BASEPTRS27:%.*]] = alloca [9 x ptr], align 8 +// CHECK1-NEXT: [[DOTOFFLOAD_PTRS28:%.*]] = alloca [9 x ptr], align 8 +// CHECK1-NEXT: [[DOTOFFLOAD_MAPPERS29:%.*]] = alloca [9 x ptr], align 8 // CHECK1-NEXT: [[DOTOFFLOAD_SIZES:%.*]] = alloca [9 x i64], align 8 -// CHECK1-NEXT: [[KERNEL_ARGS22:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 +// CHECK1-NEXT: [[KERNEL_ARGS30:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK1-NEXT: [[NN:%.*]] = alloca i32, align 4 // CHECK1-NEXT: [[NN_CASTED:%.*]] = alloca i64, align 8 -// CHECK1-NEXT: [[DOTOFFLOAD_BASEPTRS27:%.*]] = alloca [1 x ptr], align 8 -// CHECK1-NEXT: [[DOTOFFLOAD_PTRS28:%.*]] = alloca [1 x ptr], align 8 -// CHECK1-NEXT: [[DOTOFFLOAD_MAPPERS29:%.*]] = alloca [1 x ptr], align 8 -// CHECK1-NEXT: [[KERNEL_ARGS30:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 -// CHECK1-NEXT: [[NN_CASTED33:%.*]] = alloca i64, align 8 -// CHECK1-NEXT: [[DOTOFFLOAD_BASEPTRS34:%.*]] = alloca [1 x ptr], align 8 -// CHECK1-NEXT: [[DOTOFFLOAD_PTRS35:%.*]] = alloca [1 x ptr], align 8 -// CHECK1-NEXT: [[DOTOFFLOAD_MAPPERS36:%.*]] = alloca [1 x ptr], align 8 -// CHECK1-NEXT: [[KERNEL_ARGS37:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 +// CHECK1-NEXT: [[DOTOFFLOAD_BASEPTRS35:%.*]] = alloca [1 x ptr], align 8 +// CHECK1-NEXT: [[DOTOFFLOAD_PTRS36:%.*]] = alloca [1 x ptr], align 8 +// CHECK1-NEXT: [[DOTOFFLOAD_MAPPERS37:%.*]] = alloca [1 x ptr], align 8 +// CHECK1-NEXT: [[KERNEL_ARGS38:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 +// CHECK1-NEXT: [[NN_CASTED41:%.*]] = alloca i64, align 8 +// CHECK1-NEXT: [[DOTOFFLOAD_BASEPTRS42:%.*]] = alloca [1 x ptr], align 8 +// CHECK1-NEXT: [[DOTOFFLOAD_PTRS43:%.*]] = alloca [1 x ptr], align 8 +// CHECK1-NEXT: [[DOTOFFLOAD_MAPPERS44:%.*]] = alloca [1 x ptr], align 8 +// CHECK1-NEXT: [[KERNEL_ARGS45:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK1-NEXT: [[TMP0:%.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GLOB1:[0-9]+]]) // CHECK1-NEXT: store i32 [[N]], ptr [[N_ADDR]], align 4 // CHECK1-NEXT: store i32 0, ptr [[A]], align 4 @@ -538,206 +550,259 @@ int bar(int n){ // CHECK1-NEXT: [[TMP95:%.*]] = load i32, ptr [[A]], align 4 // CHECK1-NEXT: store i32 [[TMP95]], ptr [[A_CASTED16]], align 4 // CHECK1-NEXT: [[TMP96:%.*]] = load i64, ptr [[A_CASTED16]], align 8 -// CHECK1-NEXT: [[TMP97:%.*]] = load i32, ptr [[N_ADDR]], align 4 -// CHECK1-NEXT: [[CMP17:%.*]] = icmp sgt i32 [[TMP97]], 20 -// CHECK1-NEXT: br i1 [[CMP17]], label [[OMP_IF_THEN18:%.*]], label [[OMP_IF_ELSE25:%.*]] -// CHECK1: omp_if.then18: -// CHECK1-NEXT: [[TMP98:%.*]] = mul nuw i64 [[TMP2]], 4 -// CHECK1-NEXT: [[TMP99:%.*]] = mul nuw i64 5, [[TMP5]] -// CHECK1-NEXT: [[TMP100:%.*]] = mul nuw i64 [[TMP99]], 8 -// CHECK1-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[DOTOFFLOAD_SIZES]], ptr align 8 @.offload_sizes.5, i64 72, i1 false) -// CHECK1-NEXT: [[TMP101:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_BASEPTRS19]], i32 0, i32 0 -// CHECK1-NEXT: store i64 [[TMP96]], ptr [[TMP101]], align 8 -// CHECK1-NEXT: [[TMP102:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS20]], i32 0, i32 0 -// CHECK1-NEXT: store i64 [[TMP96]], ptr [[TMP102]], align 8 -// CHECK1-NEXT: [[TMP103:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_MAPPERS21]], i64 0, i64 0 -// CHECK1-NEXT: store ptr null, ptr [[TMP103]], align 8 -// CHECK1-NEXT: [[TMP104:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_BASEPTRS19]], i32 0, i32 1 -// CHECK1-NEXT: store ptr [[B]], ptr [[TMP104]], align 8 -// CHECK1-NEXT: [[TMP105:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS20]], i32 0, i32 1 -// CHECK1-NEXT: store ptr [[B]], ptr [[TMP105]], align 8 -// CHECK1-NEXT: [[TMP106:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_MAPPERS21]], i64 0, i64 1 -// CHECK1-NEXT: store ptr null, ptr [[TMP106]], align 8 -// CHECK1-NEXT: [[TMP107:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_BASEPTRS19]], i32 0, i32 2 -// CHECK1-NEXT: store i64 [[TMP2]], ptr [[TMP107]], align 8 -// CHECK1-NEXT: [[TMP108:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS20]], i32 0, i32 2 -// CHECK1-NEXT: store i64 [[TMP2]], ptr [[TMP108]], align 8 -// CHECK1-NEXT: [[TMP109:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_MAPPERS21]], i64 0, i64 2 -// CHECK1-NEXT: store ptr null, ptr [[TMP109]], align 8 -// CHECK1-NEXT: [[TMP110:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_BASEPTRS19]], i32 0, i32 3 -// CHECK1-NEXT: store ptr [[VLA]], ptr [[TMP110]], align 8 -// CHECK1-NEXT: [[TMP111:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS20]], i32 0, i32 3 -// CHECK1-NEXT: store ptr [[VLA]], ptr [[TMP111]], align 8 -// CHECK1-NEXT: [[TMP112:%.*]] = getelementptr inbounds [9 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 3 -// CHECK1-NEXT: store i64 [[TMP98]], ptr [[TMP112]], align 8 -// CHECK1-NEXT: [[TMP113:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_MAPPERS21]], i64 0, i64 3 +// CHECK1-NEXT: [[TMP97:%.*]] = load i16, ptr [[AA]], align 2 +// CHECK1-NEXT: store i16 [[TMP97]], ptr [[AA_CASTED17]], align 2 +// CHECK1-NEXT: [[TMP98:%.*]] = load i64, ptr [[AA_CASTED17]], align 8 +// CHECK1-NEXT: [[TMP99:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS18]], i32 0, i32 0 +// CHECK1-NEXT: store i64 [[TMP96]], ptr [[TMP99]], align 8 +// CHECK1-NEXT: [[TMP100:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS19]], i32 0, i32 0 +// CHECK1-NEXT: store i64 [[TMP96]], ptr [[TMP100]], align 8 +// CHECK1-NEXT: [[TMP101:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS20]], i64 0, i64 0 +// CHECK1-NEXT: store ptr null, ptr [[TMP101]], align 8 +// CHECK1-NEXT: [[TMP102:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS18]], i32 0, i32 1 +// CHECK1-NEXT: store i64 [[TMP98]], ptr [[TMP102]], align 8 +// CHECK1-NEXT: [[TMP103:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS19]], i32 0, i32 1 +// CHECK1-NEXT: store i64 [[TMP98]], ptr [[TMP103]], align 8 +// CHECK1-NEXT: [[TMP104:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS20]], i64 0, i64 1 +// CHECK1-NEXT: store ptr null, ptr [[TMP104]], align 8 +// CHECK1-NEXT: [[TMP105:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS18]], i32 0, i32 0 +// CHECK1-NEXT: [[TMP106:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS19]], i32 0, i32 0 +// CHECK1-NEXT: [[TMP107:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS21]], i32 0, i32 0 +// CHECK1-NEXT: store i32 2, ptr [[TMP107]], align 4 +// CHECK1-NEXT: [[TMP108:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS21]], i32 0, i32 1 +// CHECK1-NEXT: store i32 2, ptr [[TMP108]], align 4 +// CHECK1-NEXT: [[TMP109:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS21]], i32 0, i32 2 +// CHECK1-NEXT: store ptr [[TMP105]], ptr [[TMP109]], align 8 +// CHECK1-NEXT: [[TMP110:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS21]], i32 0, i32 3 +// CHECK1-NEXT: store ptr [[TMP106]], ptr [[TMP110]], align 8 +// CHECK1-NEXT: [[TMP111:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS21]], i32 0, i32 4 +// CHECK1-NEXT: store ptr @.offload_sizes.5, ptr [[TMP111]], align 8 +// CHECK1-NEXT: [[TMP112:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS21]], i32 0, i32 5 +// CHECK1-NEXT: store ptr @.offload_maptypes.6, ptr [[TMP112]], align 8 +// CHECK1-NEXT: [[TMP113:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS21]], i32 0, i32 6 // CHECK1-NEXT: store ptr null, ptr [[TMP113]], align 8 -// CHECK1-NEXT: [[TMP114:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_BASEPTRS19]], i32 0, i32 4 -// CHECK1-NEXT: store ptr [[C]], ptr [[TMP114]], align 8 -// CHECK1-NEXT: [[TMP115:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS20]], i32 0, i32 4 -// CHECK1-NEXT: store ptr [[C]], ptr [[TMP115]], align 8 -// CHECK1-NEXT: [[TMP116:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_MAPPERS21]], i64 0, i64 4 -// CHECK1-NEXT: store ptr null, ptr [[TMP116]], align 8 -// CHECK1-NEXT: [[TMP117:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_BASEPTRS19]], i32 0, i32 5 -// CHECK1-NEXT: store i64 5, ptr [[TMP117]], align 8 -// CHECK1-NEXT: [[TMP118:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS20]], i32 0, i32 5 -// CHECK1-NEXT: store i64 5, ptr [[TMP118]], align 8 -// CHECK1-NEXT: [[TMP119:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_MAPPERS21]], i64 0, i64 5 -// CHECK1-NEXT: store ptr null, ptr [[TMP119]], align 8 -// CHECK1-NEXT: [[TMP120:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_BASEPTRS19]], i32 0, i32 6 -// CHECK1-NEXT: store i64 [[TMP5]], ptr [[TMP120]], align 8 -// CHECK1-NEXT: [[TMP121:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS20]], i32 0, i32 6 -// CHECK1-NEXT: store i64 [[TMP5]], ptr [[TMP121]], align 8 -// CHECK1-NEXT: [[TMP122:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_MAPPERS21]], i64 0, i64 6 -// CHECK1-NEXT: store ptr null, ptr [[TMP122]], align 8 -// CHECK1-NEXT: [[TMP123:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_BASEPTRS19]], i32 0, i32 7 -// CHECK1-NEXT: store ptr [[VLA1]], ptr [[TMP123]], align 8 -// CHECK1-NEXT: [[TMP124:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS20]], i32 0, i32 7 -// CHECK1-NEXT: store ptr [[VLA1]], ptr [[TMP124]], align 8 -// CHECK1-NEXT: [[TMP125:%.*]] = getelementptr inbounds [9 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 7 -// CHECK1-NEXT: store i64 [[TMP100]], ptr [[TMP125]], align 8 -// CHECK1-NEXT: [[TMP126:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_MAPPERS21]], i64 0, i64 7 -// CHECK1-NEXT: store ptr null, ptr [[TMP126]], align 8 -// CHECK1-NEXT: [[TMP127:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_BASEPTRS19]], i32 0, i32 8 -// CHECK1-NEXT: store ptr [[D]], ptr [[TMP127]], align 8 -// CHECK1-NEXT: [[TMP128:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS20]], i32 0, i32 8 -// CHECK1-NEXT: store ptr [[D]], ptr [[TMP128]], align 8 -// CHECK1-NEXT: [[TMP129:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_MAPPERS21]], i64 0, i64 8 -// CHECK1-NEXT: store ptr null, ptr [[TMP129]], align 8 -// CHECK1-NEXT: [[TMP130:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_BASEPTRS19]], i32 0, i32 0 -// CHECK1-NEXT: [[TMP131:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS20]], i32 0, i32 0 -// CHECK1-NEXT: [[TMP132:%.*]] = getelementptr inbounds [9 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0 -// CHECK1-NEXT: [[TMP133:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS22]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP133]], align 4 -// CHECK1-NEXT: [[TMP134:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS22]], i32 0, i32 1 -// CHECK1-NEXT: store i32 9, ptr [[TMP134]], align 4 -// CHECK1-NEXT: [[TMP135:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS22]], i32 0, i32 2 -// CHECK1-NEXT: store ptr [[TMP130]], ptr [[TMP135]], align 8 -// CHECK1-NEXT: [[TMP136:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS22]], i32 0, i32 3 -// CHECK1-NEXT: store ptr [[TMP131]], ptr [[TMP136]], align 8 -// CHECK1-NEXT: [[TMP137:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS22]], i32 0, i32 4 -// CHECK1-NEXT: store ptr [[TMP132]], ptr [[TMP137]], align 8 -// CHECK1-NEXT: [[TMP138:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS22]], i32 0, i32 5 -// CHECK1-NEXT: store ptr @.offload_maptypes.6, ptr [[TMP138]], align 8 -// CHECK1-NEXT: [[TMP139:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS22]], i32 0, i32 6 -// CHECK1-NEXT: store ptr null, ptr [[TMP139]], align 8 -// CHECK1-NEXT: [[TMP140:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS22]], i32 0, i32 7 +// CHECK1-NEXT: [[TMP114:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS21]], i32 0, i32 7 +// CHECK1-NEXT: store ptr null, ptr [[TMP114]], align 8 +// CHECK1-NEXT: [[TMP115:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS21]], i32 0, i32 8 +// CHECK1-NEXT: store i64 0, ptr [[TMP115]], align 8 +// CHECK1-NEXT: [[TMP116:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS21]], i32 0, i32 9 +// CHECK1-NEXT: store i64 0, ptr [[TMP116]], align 8 +// CHECK1-NEXT: [[TMP117:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS21]], i32 0, i32 10 +// CHECK1-NEXT: store [3 x i32] zeroinitializer, ptr [[TMP117]], align 4 +// CHECK1-NEXT: [[TMP118:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS21]], i32 0, i32 11 +// CHECK1-NEXT: store [3 x i32] zeroinitializer, ptr [[TMP118]], align 4 +// CHECK1-NEXT: [[TMP119:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS21]], i32 0, i32 12 +// CHECK1-NEXT: store i32 0, ptr [[TMP119]], align 4 +// CHECK1-NEXT: [[TMP120:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB1]], i64 -1, i32 0, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l124.region_id, ptr [[KERNEL_ARGS21]]) +// CHECK1-NEXT: [[TMP121:%.*]] = icmp ne i32 [[TMP120]], 0 +// CHECK1-NEXT: br i1 [[TMP121]], label [[OMP_OFFLOAD_FAILED22:%.*]], label [[OMP_OFFLOAD_CONT23:%.*]] +// CHECK1: omp_offload.failed22: +// CHECK1-NEXT: call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l124(i64 [[TMP96]], i64 [[TMP98]]) #[[ATTR3]] +// CHECK1-NEXT: br label [[OMP_OFFLOAD_CONT23]] +// CHECK1: omp_offload.cont23: +// CHECK1-NEXT: [[TMP122:%.*]] = load i32, ptr [[A]], align 4 +// CHECK1-NEXT: store i32 [[TMP122]], ptr [[A_CASTED24]], align 4 +// CHECK1-NEXT: [[TMP123:%.*]] = load i64, ptr [[A_CASTED24]], align 8 +// CHECK1-NEXT: [[TMP124:%.*]] = load i32, ptr [[N_ADDR]], align 4 +// CHECK1-NEXT: [[CMP25:%.*]] = icmp sgt i32 [[TMP124]], 20 +// CHECK1-NEXT: br i1 [[CMP25]], label [[OMP_IF_THEN26:%.*]], label [[OMP_IF_ELSE33:%.*]] +// CHECK1: omp_if.then26: +// CHECK1-NEXT: [[TMP125:%.*]] = mul nuw i64 [[TMP2]], 4 +// CHECK1-NEXT: [[TMP126:%.*]] = mul nuw i64 5, [[TMP5]] +// CHECK1-NEXT: [[TMP127:%.*]] = mul nuw i64 [[TMP126]], 8 +// CHECK1-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[DOTOFFLOAD_SIZES]], ptr align 8 @.offload_sizes.7, i64 72, i1 false) +// CHECK1-NEXT: [[TMP128:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_BASEPTRS27]], i32 0, i32 0 +// CHECK1-NEXT: store i64 [[TMP123]], ptr [[TMP128]], align 8 +// CHECK1-NEXT: [[TMP129:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS28]], i32 0, i32 0 +// CHECK1-NEXT: store i64 [[TMP123]], ptr [[TMP129]], align 8 +// CHECK1-NEXT: [[TMP130:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_MAPPERS29]], i64 0, i64 0 +// CHECK1-NEXT: store ptr null, ptr [[TMP130]], align 8 +// CHECK1-NEXT: [[TMP131:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_BASEPTRS27]], i32 0, i32 1 +// CHECK1-NEXT: store ptr [[B]], ptr [[TMP131]], align 8 +// CHECK1-NEXT: [[TMP132:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS28]], i32 0, i32 1 +// CHECK1-NEXT: store ptr [[B]], ptr [[TMP132]], align 8 +// CHECK1-NEXT: [[TMP133:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_MAPPERS29]], i64 0, i64 1 +// CHECK1-NEXT: store ptr null, ptr [[TMP133]], align 8 +// CHECK1-NEXT: [[TMP134:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_BASEPTRS27]], i32 0, i32 2 +// CHECK1-NEXT: store i64 [[TMP2]], ptr [[TMP134]], align 8 +// CHECK1-NEXT: [[TMP135:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS28]], i32 0, i32 2 +// CHECK1-NEXT: store i64 [[TMP2]], ptr [[TMP135]], align 8 +// CHECK1-NEXT: [[TMP136:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_MAPPERS29]], i64 0, i64 2 +// CHECK1-NEXT: store ptr null, ptr [[TMP136]], align 8 +// CHECK1-NEXT: [[TMP137:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_BASEPTRS27]], i32 0, i32 3 +// CHECK1-NEXT: store ptr [[VLA]], ptr [[TMP137]], align 8 +// CHECK1-NEXT: [[TMP138:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS28]], i32 0, i32 3 +// CHECK1-NEXT: store ptr [[VLA]], ptr [[TMP138]], align 8 +// CHECK1-NEXT: [[TMP139:%.*]] = getelementptr inbounds [9 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 3 +// CHECK1-NEXT: store i64 [[TMP125]], ptr [[TMP139]], align 8 +// CHECK1-NEXT: [[TMP140:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_MAPPERS29]], i64 0, i64 3 // CHECK1-NEXT: store ptr null, ptr [[TMP140]], align 8 -// CHECK1-NEXT: [[TMP141:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS22]], i32 0, i32 8 -// CHECK1-NEXT: store i64 0, ptr [[TMP141]], align 8 -// CHECK1-NEXT: [[TMP142:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS22]], i32 0, i32 9 -// CHECK1-NEXT: store i64 0, ptr [[TMP142]], align 8 -// CHECK1-NEXT: [[TMP143:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS22]], i32 0, i32 10 -// CHECK1-NEXT: store [3 x i32] zeroinitializer, ptr [[TMP143]], align 4 -// CHECK1-NEXT: [[TMP144:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS22]], i32 0, i32 11 -// CHECK1-NEXT: store [3 x i32] zeroinitializer, ptr [[TMP144]], align 4 -// CHECK1-NEXT: [[TMP145:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS22]], i32 0, i32 12 -// CHECK1-NEXT: store i32 0, ptr [[TMP145]], align 4 -// CHECK1-NEXT: [[TMP146:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB1]], i64 -1, i32 0, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l142.region_id, ptr [[KERNEL_ARGS22]]) -// CHECK1-NEXT: [[TMP147:%.*]] = icmp ne i32 [[TMP146]], 0 -// CHECK1-NEXT: br i1 [[TMP147]], label [[OMP_OFFLOAD_FAILED23:%.*]], label [[OMP_OFFLOAD_CONT24:%.*]] -// CHECK1: omp_offload.failed23: -// CHECK1-NEXT: call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l142(i64 [[TMP96]], ptr [[B]], i64 [[TMP2]], ptr [[VLA]], ptr [[C]], i64 5, i64 [[TMP5]], ptr [[VLA1]], ptr [[D]]) #[[ATTR3]] -// CHECK1-NEXT: br label [[OMP_OFFLOAD_CONT24]] -// CHECK1: omp_offload.cont24: -// CHECK1-NEXT: br label [[OMP_IF_END26:%.*]] -// CHECK1: omp_if.else25: -// CHECK1-NEXT: call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l142(i64 [[TMP96]], ptr [[B]], i64 [[TMP2]], ptr [[VLA]], ptr [[C]], i64 5, i64 [[TMP5]], ptr [[VLA1]], ptr [[D]]) #[[ATTR3]] -// CHECK1-NEXT: br label [[OMP_IF_END26]] -// CHECK1: omp_if.end26: -// CHECK1-NEXT: store i32 0, ptr [[NN]], align 4 -// CHECK1-NEXT: [[TMP148:%.*]] = load i32, ptr [[NN]], align 4 -// CHECK1-NEXT: store i32 [[TMP148]], ptr [[NN_CASTED]], align 4 -// CHECK1-NEXT: [[TMP149:%.*]] = load i64, ptr [[NN_CASTED]], align 8 -// CHECK1-NEXT: [[TMP150:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS27]], i32 0, i32 0 -// CHECK1-NEXT: store i64 [[TMP149]], ptr [[TMP150]], align 8 -// CHECK1-NEXT: [[TMP151:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS28]], i32 0, i32 0 -// CHECK1-NEXT: store i64 [[TMP149]], ptr [[TMP151]], align 8 -// CHECK1-NEXT: [[TMP152:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_MAPPERS29]], i64 0, i64 0 -// CHECK1-NEXT: store ptr null, ptr [[TMP152]], align 8 -// CHECK1-NEXT: [[TMP153:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS27]], i32 0, i32 0 -// CHECK1-NEXT: [[TMP154:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS28]], i32 0, i32 0 -// CHECK1-NEXT: [[TMP155:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP155]], align 4 -// CHECK1-NEXT: [[TMP156:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 1 -// CHECK1-NEXT: store i32 1, ptr [[TMP156]], align 4 -// CHECK1-NEXT: [[TMP157:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 2 -// CHECK1-NEXT: store ptr [[TMP153]], ptr [[TMP157]], align 8 -// CHECK1-NEXT: [[TMP158:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 3 -// CHECK1-NEXT: store ptr [[TMP154]], ptr [[TMP158]], align 8 -// CHECK1-NEXT: [[TMP159:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 4 -// CHECK1-NEXT: store ptr @.offload_sizes.7, ptr [[TMP159]], align 8 -// CHECK1-NEXT: [[TMP160:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 5 -// CHECK1-NEXT: store ptr @.offload_maptypes.8, ptr [[TMP160]], align 8 -// CHECK1-NEXT: [[TMP161:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 6 -// CHECK1-NEXT: store ptr null, ptr [[TMP161]], align 8 -// CHECK1-NEXT: [[TMP162:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 7 -// CHECK1-NEXT: store ptr null, ptr [[TMP162]], align 8 -// CHECK1-NEXT: [[TMP163:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 8 -// CHECK1-NEXT: store i64 0, ptr [[TMP163]], align 8 -// CHECK1-NEXT: [[TMP164:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 9 -// CHECK1-NEXT: store i64 0, ptr [[TMP164]], align 8 -// CHECK1-NEXT: [[TMP165:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 10 -// CHECK1-NEXT: store [3 x i32] zeroinitializer, ptr [[TMP165]], align 4 -// CHECK1-NEXT: [[TMP166:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 11 -// CHECK1-NEXT: store [3 x i32] zeroinitializer, ptr [[TMP166]], align 4 -// CHECK1-NEXT: [[TMP167:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 12 -// CHECK1-NEXT: store i32 0, ptr [[TMP167]], align 4 -// CHECK1-NEXT: [[TMP168:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB1]], i64 -1, i32 0, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l154.region_id, ptr [[KERNEL_ARGS30]]) -// CHECK1-NEXT: [[TMP169:%.*]] = icmp ne i32 [[TMP168]], 0 -// CHECK1-NEXT: br i1 [[TMP169]], label [[OMP_OFFLOAD_FAILED31:%.*]], label [[OMP_OFFLOAD_CONT32:%.*]] +// CHECK1-NEXT: [[TMP141:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_BASEPTRS27]], i32 0, i32 4 +// CHECK1-NEXT: store ptr [[C]], ptr [[TMP141]], align 8 +// CHECK1-NEXT: [[TMP142:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS28]], i32 0, i32 4 +// CHECK1-NEXT: store ptr [[C]], ptr [[TMP142]], align 8 +// CHECK1-NEXT: [[TMP143:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_MAPPERS29]], i64 0, i64 4 +// CHECK1-NEXT: store ptr null, ptr [[TMP143]], align 8 +// CHECK1-NEXT: [[TMP144:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_BASEPTRS27]], i32 0, i32 5 +// CHECK1-NEXT: store i64 5, ptr [[TMP144]], align 8 +// CHECK1-NEXT: [[TMP145:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS28]], i32 0, i32 5 +// CHECK1-NEXT: store i64 5, ptr [[TMP145]], align 8 +// CHECK1-NEXT: [[TMP146:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_MAPPERS29]], i64 0, i64 5 +// CHECK1-NEXT: store ptr null, ptr [[TMP146]], align 8 +// CHECK1-NEXT: [[TMP147:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_BASEPTRS27]], i32 0, i32 6 +// CHECK1-NEXT: store i64 [[TMP5]], ptr [[TMP147]], align 8 +// CHECK1-NEXT: [[TMP148:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS28]], i32 0, i32 6 +// CHECK1-NEXT: store i64 [[TMP5]], ptr [[TMP148]], align 8 +// CHECK1-NEXT: [[TMP149:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_MAPPERS29]], i64 0, i64 6 +// CHECK1-NEXT: store ptr null, ptr [[TMP149]], align 8 +// CHECK1-NEXT: [[TMP150:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_BASEPTRS27]], i32 0, i32 7 +// CHECK1-NEXT: store ptr [[VLA1]], ptr [[TMP150]], align 8 +// CHECK1-NEXT: [[TMP151:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS28]], i32 0, i32 7 +// CHECK1-NEXT: store ptr [[VLA1]], ptr [[TMP151]], align 8 +// CHECK1-NEXT: [[TMP152:%.*]] = getelementptr inbounds [9 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 7 +// CHECK1-NEXT: store i64 [[TMP127]], ptr [[TMP152]], align 8 +// CHECK1-NEXT: [[TMP153:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_MAPPERS29]], i64 0, i64 7 +// CHECK1-NEXT: store ptr null, ptr [[TMP153]], align 8 +// CHECK1-NEXT: [[TMP154:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_BASEPTRS27]], i32 0, i32 8 +// CHECK1-NEXT: store ptr [[D]], ptr [[TMP154]], align 8 +// CHECK1-NEXT: [[TMP155:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS28]], i32 0, i32 8 +// CHECK1-NEXT: store ptr [[D]], ptr [[TMP155]], align 8 +// CHECK1-NEXT: [[TMP156:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_MAPPERS29]], i64 0, i64 8 +// CHECK1-NEXT: store ptr null, ptr [[TMP156]], align 8 +// CHECK1-NEXT: [[TMP157:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_BASEPTRS27]], i32 0, i32 0 +// CHECK1-NEXT: [[TMP158:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS28]], i32 0, i32 0 +// CHECK1-NEXT: [[TMP159:%.*]] = getelementptr inbounds [9 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0 +// CHECK1-NEXT: [[TMP160:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 0 +// CHECK1-NEXT: store i32 2, ptr [[TMP160]], align 4 +// CHECK1-NEXT: [[TMP161:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 1 +// CHECK1-NEXT: store i32 9, ptr [[TMP161]], align 4 +// CHECK1-NEXT: [[TMP162:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 2 +// CHECK1-NEXT: store ptr [[TMP157]], ptr [[TMP162]], align 8 +// CHECK1-NEXT: [[TMP163:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 3 +// CHECK1-NEXT: store ptr [[TMP158]], ptr [[TMP163]], align 8 +// CHECK1-NEXT: [[TMP164:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 4 +// CHECK1-NEXT: store ptr [[TMP159]], ptr [[TMP164]], align 8 +// CHECK1-NEXT: [[TMP165:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 5 +// CHECK1-NEXT: store ptr @.offload_maptypes.8, ptr [[TMP165]], align 8 +// CHECK1-NEXT: [[TMP166:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 6 +// CHECK1-NEXT: store ptr null, ptr [[TMP166]], align 8 +// CHECK1-NEXT: [[TMP167:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 7 +// CHECK1-NEXT: store ptr null, ptr [[TMP167]], align 8 +// CHECK1-NEXT: [[TMP168:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 8 +// CHECK1-NEXT: store i64 0, ptr [[TMP168]], align 8 +// CHECK1-NEXT: [[TMP169:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 9 +// CHECK1-NEXT: store i64 0, ptr [[TMP169]], align 8 +// CHECK1-NEXT: [[TMP170:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 10 +// CHECK1-NEXT: store [3 x i32] zeroinitializer, ptr [[TMP170]], align 4 +// CHECK1-NEXT: [[TMP171:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 11 +// CHECK1-NEXT: store [3 x i32] zeroinitializer, ptr [[TMP171]], align 4 +// CHECK1-NEXT: [[TMP172:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 12 +// CHECK1-NEXT: store i32 0, ptr [[TMP172]], align 4 +// CHECK1-NEXT: [[TMP173:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB1]], i64 -1, i32 0, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l148.region_id, ptr [[KERNEL_ARGS30]]) +// CHECK1-NEXT: [[TMP174:%.*]] = icmp ne i32 [[TMP173]], 0 +// CHECK1-NEXT: br i1 [[TMP174]], label [[OMP_OFFLOAD_FAILED31:%.*]], label [[OMP_OFFLOAD_CONT32:%.*]] // CHECK1: omp_offload.failed31: -// CHECK1-NEXT: call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l154(i64 [[TMP149]]) #[[ATTR3]] +// CHECK1-NEXT: call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l148(i64 [[TMP123]], ptr [[B]], i64 [[TMP2]], ptr [[VLA]], ptr [[C]], i64 5, i64 [[TMP5]], ptr [[VLA1]], ptr [[D]]) #[[ATTR3]] // CHECK1-NEXT: br label [[OMP_OFFLOAD_CONT32]] // CHECK1: omp_offload.cont32: -// CHECK1-NEXT: [[TMP170:%.*]] = load i32, ptr [[NN]], align 4 -// CHECK1-NEXT: store i32 [[TMP170]], ptr [[NN_CASTED33]], align 4 -// CHECK1-NEXT: [[TMP171:%.*]] = load i64, ptr [[NN_CASTED33]], align 8 -// CHECK1-NEXT: [[TMP172:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS34]], i32 0, i32 0 -// CHECK1-NEXT: store i64 [[TMP171]], ptr [[TMP172]], align 8 -// CHECK1-NEXT: [[TMP173:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS35]], i32 0, i32 0 -// CHECK1-NEXT: store i64 [[TMP171]], ptr [[TMP173]], align 8 -// CHECK1-NEXT: [[TMP174:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_MAPPERS36]], i64 0, i64 0 -// CHECK1-NEXT: store ptr null, ptr [[TMP174]], align 8 -// CHECK1-NEXT: [[TMP175:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS34]], i32 0, i32 0 -// CHECK1-NEXT: [[TMP176:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS35]], i32 0, i32 0 -// CHECK1-NEXT: [[TMP177:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS37]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP177]], align 4 -// CHECK1-NEXT: [[TMP178:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS37]], i32 0, i32 1 -// CHECK1-NEXT: store i32 1, ptr [[TMP178]], align 4 -// CHECK1-NEXT: [[TMP179:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS37]], i32 0, i32 2 -// CHECK1-NEXT: store ptr [[TMP175]], ptr [[TMP179]], align 8 -// CHECK1-NEXT: [[TMP180:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS37]], i32 0, i32 3 -// CHECK1-NEXT: store ptr [[TMP176]], ptr [[TMP180]], align 8 -// CHECK1-NEXT: [[TMP181:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS37]], i32 0, i32 4 -// CHECK1-NEXT: store ptr @.offload_sizes.9, ptr [[TMP181]], align 8 -// CHECK1-NEXT: [[TMP182:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS37]], i32 0, i32 5 -// CHECK1-NEXT: store ptr @.offload_maptypes.10, ptr [[TMP182]], align 8 -// CHECK1-NEXT: [[TMP183:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS37]], i32 0, i32 6 -// CHECK1-NEXT: store ptr null, ptr [[TMP183]], align 8 -// CHECK1-NEXT: [[TMP184:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS37]], i32 0, i32 7 -// CHECK1-NEXT: store ptr null, ptr [[TMP184]], align 8 -// CHECK1-NEXT: [[TMP185:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS37]], i32 0, i32 8 -// CHECK1-NEXT: store i64 0, ptr [[TMP185]], align 8 -// CHECK1-NEXT: [[TMP186:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS37]], i32 0, i32 9 -// CHECK1-NEXT: store i64 0, ptr [[TMP186]], align 8 -// CHECK1-NEXT: [[TMP187:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS37]], i32 0, i32 10 -// CHECK1-NEXT: store [3 x i32] zeroinitializer, ptr [[TMP187]], align 4 -// CHECK1-NEXT: [[TMP188:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS37]], i32 0, i32 11 -// CHECK1-NEXT: store [3 x i32] zeroinitializer, ptr [[TMP188]], align 4 -// CHECK1-NEXT: [[TMP189:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS37]], i32 0, i32 12 -// CHECK1-NEXT: store i32 0, ptr [[TMP189]], align 4 -// CHECK1-NEXT: [[TMP190:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB1]], i64 -1, i32 0, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l157.region_id, ptr [[KERNEL_ARGS37]]) -// CHECK1-NEXT: [[TMP191:%.*]] = icmp ne i32 [[TMP190]], 0 -// CHECK1-NEXT: br i1 [[TMP191]], label [[OMP_OFFLOAD_FAILED38:%.*]], label [[OMP_OFFLOAD_CONT39:%.*]] -// CHECK1: omp_offload.failed38: -// CHECK1-NEXT: call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l157(i64 [[TMP171]]) #[[ATTR3]] -// CHECK1-NEXT: br label [[OMP_OFFLOAD_CONT39]] -// CHECK1: omp_offload.cont39: -// CHECK1-NEXT: [[TMP192:%.*]] = load i32, ptr [[A]], align 4 -// CHECK1-NEXT: [[TMP193:%.*]] = load ptr, ptr [[SAVED_STACK]], align 8 -// CHECK1-NEXT: call void @llvm.stackrestore.p0(ptr [[TMP193]]) -// CHECK1-NEXT: ret i32 [[TMP192]] +// CHECK1-NEXT: br label [[OMP_IF_END34:%.*]] +// CHECK1: omp_if.else33: +// CHECK1-NEXT: call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l148(i64 [[TMP123]], ptr [[B]], i64 [[TMP2]], ptr [[VLA]], ptr [[C]], i64 5, i64 [[TMP5]], ptr [[VLA1]], ptr [[D]]) #[[ATTR3]] +// CHECK1-NEXT: br label [[OMP_IF_END34]] +// CHECK1: omp_if.end34: +// CHECK1-NEXT: store i32 0, ptr [[NN]], align 4 +// CHECK1-NEXT: [[TMP175:%.*]] = load i32, ptr [[NN]], align 4 +// CHECK1-NEXT: store i32 [[TMP175]], ptr [[NN_CASTED]], align 4 +// CHECK1-NEXT: [[TMP176:%.*]] = load i64, ptr [[NN_CASTED]], align 8 +// CHECK1-NEXT: [[TMP177:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS35]], i32 0, i32 0 +// CHECK1-NEXT: store i64 [[TMP176]], ptr [[TMP177]], align 8 +// CHECK1-NEXT: [[TMP178:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS36]], i32 0, i32 0 +// CHECK1-NEXT: store i64 [[TMP176]], ptr [[TMP178]], align 8 +// CHECK1-NEXT: [[TMP179:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_MAPPERS37]], i64 0, i64 0 +// CHECK1-NEXT: store ptr null, ptr [[TMP179]], align 8 +// CHECK1-NEXT: [[TMP180:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS35]], i32 0, i32 0 +// CHECK1-NEXT: [[TMP181:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS36]], i32 0, i32 0 +// CHECK1-NEXT: [[TMP182:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS38]], i32 0, i32 0 +// CHECK1-NEXT: store i32 2, ptr [[TMP182]], align 4 +// CHECK1-NEXT: [[TMP183:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS38]], i32 0, i32 1 +// CHECK1-NEXT: store i32 1, ptr [[TMP183]], align 4 +// CHECK1-NEXT: [[TMP184:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS38]], i32 0, i32 2 +// CHECK1-NEXT: store ptr [[TMP180]], ptr [[TMP184]], align 8 +// CHECK1-NEXT: [[TMP185:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS38]], i32 0, i32 3 +// CHECK1-NEXT: store ptr [[TMP181]], ptr [[TMP185]], align 8 +// CHECK1-NEXT: [[TMP186:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS38]], i32 0, i32 4 +// CHECK1-NEXT: store ptr @.offload_sizes.9, ptr [[TMP186]], align 8 +// CHECK1-NEXT: [[TMP187:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS38]], i32 0, i32 5 +// CHECK1-NEXT: store ptr @.offload_maptypes.10, ptr [[TMP187]], align 8 +// CHECK1-NEXT: [[TMP188:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS38]], i32 0, i32 6 +// CHECK1-NEXT: store ptr null, ptr [[TMP188]], align 8 +// CHECK1-NEXT: [[TMP189:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS38]], i32 0, i32 7 +// CHECK1-NEXT: store ptr null, ptr [[TMP189]], align 8 +// CHECK1-NEXT: [[TMP190:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS38]], i32 0, i32 8 +// CHECK1-NEXT: store i64 0, ptr [[TMP190]], align 8 +// CHECK1-NEXT: [[TMP191:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS38]], i32 0, i32 9 +// CHECK1-NEXT: store i64 0, ptr [[TMP191]], align 8 +// CHECK1-NEXT: [[TMP192:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS38]], i32 0, i32 10 +// CHECK1-NEXT: store [3 x i32] zeroinitializer, ptr [[TMP192]], align 4 +// CHECK1-NEXT: [[TMP193:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS38]], i32 0, i32 11 +// CHECK1-NEXT: store [3 x i32] zeroinitializer, ptr [[TMP193]], align 4 +// CHECK1-NEXT: [[TMP194:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS38]], i32 0, i32 12 +// CHECK1-NEXT: store i32 0, ptr [[TMP194]], align 4 +// CHECK1-NEXT: [[TMP195:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB1]], i64 -1, i32 0, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l160.region_id, ptr [[KERNEL_ARGS38]]) +// CHECK1-NEXT: [[TMP196:%.*]] = icmp ne i32 [[TMP195]], 0 +// CHECK1-NEXT: br i1 [[TMP196]], label [[OMP_OFFLOAD_FAILED39:%.*]], label [[OMP_OFFLOAD_CONT40:%.*]] +// CHECK1: omp_offload.failed39: +// CHECK1-NEXT: call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l160(i64 [[TMP176]]) #[[ATTR3]] +// CHECK1-NEXT: br label [[OMP_OFFLOAD_CONT40]] +// CHECK1: omp_offload.cont40: +// CHECK1-NEXT: [[TMP197:%.*]] = load i32, ptr [[NN]], align 4 +// CHECK1-NEXT: store i32 [[TMP197]], ptr [[NN_CASTED41]], align 4 +// CHECK1-NEXT: [[TMP198:%.*]] = load i64, ptr [[NN_CASTED41]], align 8 +// CHECK1-NEXT: [[TMP199:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS42]], i32 0, i32 0 +// CHECK1-NEXT: store i64 [[TMP198]], ptr [[TMP199]], align 8 +// CHECK1-NEXT: [[TMP200:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS43]], i32 0, i32 0 +// CHECK1-NEXT: store i64 [[TMP198]], ptr [[TMP200]], align 8 +// CHECK1-NEXT: [[TMP201:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_MAPPERS44]], i64 0, i64 0 +// CHECK1-NEXT: store ptr null, ptr [[TMP201]], align 8 +// CHECK1-NEXT: [[TMP202:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS42]], i32 0, i32 0 +// CHECK1-NEXT: [[TMP203:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS43]], i32 0, i32 0 +// CHECK1-NEXT: [[TMP204:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS45]], i32 0, i32 0 +// CHECK1-NEXT: store i32 2, ptr [[TMP204]], align 4 +// CHECK1-NEXT: [[TMP205:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS45]], i32 0, i32 1 +// CHECK1-NEXT: store i32 1, ptr [[TMP205]], align 4 +// CHECK1-NEXT: [[TMP206:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS45]], i32 0, i32 2 +// CHECK1-NEXT: store ptr [[TMP202]], ptr [[TMP206]], align 8 +// CHECK1-NEXT: [[TMP207:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS45]], i32 0, i32 3 +// CHECK1-NEXT: store ptr [[TMP203]], ptr [[TMP207]], align 8 +// CHECK1-NEXT: [[TMP208:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS45]], i32 0, i32 4 +// CHECK1-NEXT: store ptr @.offload_sizes.11, ptr [[TMP208]], align 8 +// CHECK1-NEXT: [[TMP209:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS45]], i32 0, i32 5 +// CHECK1-NEXT: store ptr @.offload_maptypes.12, ptr [[TMP209]], align 8 +// CHECK1-NEXT: [[TMP210:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS45]], i32 0, i32 6 +// CHECK1-NEXT: store ptr null, ptr [[TMP210]], align 8 +// CHECK1-NEXT: [[TMP211:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS45]], i32 0, i32 7 +// CHECK1-NEXT: store ptr null, ptr [[TMP211]], align 8 +// CHECK1-NEXT: [[TMP212:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS45]], i32 0, i32 8 +// CHECK1-NEXT: store i64 0, ptr [[TMP212]], align 8 +// CHECK1-NEXT: [[TMP213:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS45]], i32 0, i32 9 +// CHECK1-NEXT: store i64 0, ptr [[TMP213]], align 8 +// CHECK1-NEXT: [[TMP214:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS45]], i32 0, i32 10 +// CHECK1-NEXT: store [3 x i32] zeroinitializer, ptr [[TMP214]], align 4 +// CHECK1-NEXT: [[TMP215:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS45]], i32 0, i32 11 +// CHECK1-NEXT: store [3 x i32] zeroinitializer, ptr [[TMP215]], align 4 +// CHECK1-NEXT: [[TMP216:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS45]], i32 0, i32 12 +// CHECK1-NEXT: store i32 0, ptr [[TMP216]], align 4 +// CHECK1-NEXT: [[TMP217:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB1]], i64 -1, i32 0, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l163.region_id, ptr [[KERNEL_ARGS45]]) +// CHECK1-NEXT: [[TMP218:%.*]] = icmp ne i32 [[TMP217]], 0 +// CHECK1-NEXT: br i1 [[TMP218]], label [[OMP_OFFLOAD_FAILED46:%.*]], label [[OMP_OFFLOAD_CONT47:%.*]] +// CHECK1: omp_offload.failed46: +// CHECK1-NEXT: call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l163(i64 [[TMP198]]) #[[ATTR3]] +// CHECK1-NEXT: br label [[OMP_OFFLOAD_CONT47]] +// CHECK1: omp_offload.cont47: +// CHECK1-NEXT: [[TMP219:%.*]] = load i32, ptr [[A]], align 4 +// CHECK1-NEXT: [[TMP220:%.*]] = load ptr, ptr [[SAVED_STACK]], align 8 +// CHECK1-NEXT: call void @llvm.stackrestore.p0(ptr [[TMP220]]) +// CHECK1-NEXT: ret i32 [[TMP219]] // // // CHECK1-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l101 @@ -830,68 +895,68 @@ int bar(int n){ // CHECK1-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP4]], i32 0, i32 0 // CHECK1-NEXT: [[TMP7:%.*]] = load ptr, ptr [[TMP6]], align 8 // CHECK1-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T_WITH_PRIVATES]], ptr [[TMP3]], i32 0, i32 1 -// CHECK1-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META15:![0-9]+]]) -// CHECK1-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META18:![0-9]+]]) -// CHECK1-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META20:![0-9]+]]) -// CHECK1-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META22:![0-9]+]]) -// CHECK1-NEXT: store i32 [[TMP2]], ptr [[DOTGLOBAL_TID__ADDR_I]], align 4, !noalias !24 -// CHECK1-NEXT: store ptr [[TMP5]], ptr [[DOTPART_ID__ADDR_I]], align 8, !noalias !24 -// CHECK1-NEXT: store ptr [[TMP8]], ptr [[DOTPRIVATES__ADDR_I]], align 8, !noalias !24 -// CHECK1-NEXT: store ptr @.omp_task_privates_map., ptr [[DOTCOPY_FN__ADDR_I]], align 8, !noalias !24 -// CHECK1-NEXT: store ptr [[TMP3]], ptr [[DOTTASK_T__ADDR_I]], align 8, !noalias !24 -// CHECK1-NEXT: store ptr [[TMP7]], ptr [[__CONTEXT_ADDR_I]], align 8, !noalias !24 -// CHECK1-NEXT: [[TMP9:%.*]] = load ptr, ptr [[__CONTEXT_ADDR_I]], align 8, !noalias !24 -// CHECK1-NEXT: [[TMP10:%.*]] = load ptr, ptr [[DOTCOPY_FN__ADDR_I]], align 8, !noalias !24 -// CHECK1-NEXT: [[TMP11:%.*]] = load ptr, ptr [[DOTPRIVATES__ADDR_I]], align 8, !noalias !24 +// CHECK1-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META16:![0-9]+]]) +// CHECK1-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META19:![0-9]+]]) +// CHECK1-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META21:![0-9]+]]) +// CHECK1-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META23:![0-9]+]]) +// CHECK1-NEXT: store i32 [[TMP2]], ptr [[DOTGLOBAL_TID__ADDR_I]], align 4, !noalias !25 +// CHECK1-NEXT: store ptr [[TMP5]], ptr [[DOTPART_ID__ADDR_I]], align 8, !noalias !25 +// CHECK1-NEXT: store ptr [[TMP8]], ptr [[DOTPRIVATES__ADDR_I]], align 8, !noalias !25 +// CHECK1-NEXT: store ptr @.omp_task_privates_map., ptr [[DOTCOPY_FN__ADDR_I]], align 8, !noalias !25 +// CHECK1-NEXT: store ptr [[TMP3]], ptr [[DOTTASK_T__ADDR_I]], align 8, !noalias !25 +// CHECK1-NEXT: store ptr [[TMP7]], ptr [[__CONTEXT_ADDR_I]], align 8, !noalias !25 +// CHECK1-NEXT: [[TMP9:%.*]] = load ptr, ptr [[__CONTEXT_ADDR_I]], align 8, !noalias !25 +// CHECK1-NEXT: [[TMP10:%.*]] = load ptr, ptr [[DOTCOPY_FN__ADDR_I]], align 8, !noalias !25 +// CHECK1-NEXT: [[TMP11:%.*]] = load ptr, ptr [[DOTPRIVATES__ADDR_I]], align 8, !noalias !25 // CHECK1-NEXT: call void [[TMP10]](ptr [[TMP11]], ptr [[DOTFIRSTPRIV_PTR_ADDR_I]], ptr [[DOTFIRSTPRIV_PTR_ADDR1_I]], ptr [[DOTFIRSTPRIV_PTR_ADDR2_I]], ptr [[DOTFIRSTPRIV_PTR_ADDR3_I]]) #[[ATTR3]] -// CHECK1-NEXT: [[TMP12:%.*]] = load ptr, ptr [[DOTFIRSTPRIV_PTR_ADDR_I]], align 8, !noalias !24 -// CHECK1-NEXT: [[TMP13:%.*]] = load ptr, ptr [[DOTFIRSTPRIV_PTR_ADDR1_I]], align 8, !noalias !24 -// CHECK1-NEXT: [[TMP14:%.*]] = load ptr, ptr [[DOTFIRSTPRIV_PTR_ADDR2_I]], align 8, !noalias !24 -// CHECK1-NEXT: [[TMP15:%.*]] = load ptr, ptr [[DOTFIRSTPRIV_PTR_ADDR3_I]], align 8, !noalias !24 +// CHECK1-NEXT: [[TMP12:%.*]] = load ptr, ptr [[DOTFIRSTPRIV_PTR_ADDR_I]], align 8, !noalias !25 +// CHECK1-NEXT: [[TMP13:%.*]] = load ptr, ptr [[DOTFIRSTPRIV_PTR_ADDR1_I]], align 8, !noalias !25 +// CHECK1-NEXT: [[TMP14:%.*]] = load ptr, ptr [[DOTFIRSTPRIV_PTR_ADDR2_I]], align 8, !noalias !25 +// CHECK1-NEXT: [[TMP15:%.*]] = load ptr, ptr [[DOTFIRSTPRIV_PTR_ADDR3_I]], align 8, !noalias !25 // CHECK1-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT_ANON:%.*]], ptr [[TMP9]], i32 0, i32 1 // CHECK1-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT_ANON]], ptr [[TMP9]], i32 0, i32 2 // CHECK1-NEXT: [[TMP18:%.*]] = load i32, ptr [[TMP16]], align 4 // CHECK1-NEXT: [[TMP19:%.*]] = load i32, ptr [[TMP17]], align 4 // CHECK1-NEXT: [[TMP20:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP18]], 0 // CHECK1-NEXT: [[TMP21:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP19]], 0 -// CHECK1-NEXT: store i32 2, ptr [[KERNEL_ARGS_I]], align 4, !noalias !24 +// CHECK1-NEXT: store i32 2, ptr [[KERNEL_ARGS_I]], align 4, !noalias !25 // CHECK1-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS_I]], i32 0, i32 1 -// CHECK1-NEXT: store i32 3, ptr [[TMP22]], align 4, !noalias !24 +// CHECK1-NEXT: store i32 3, ptr [[TMP22]], align 4, !noalias !25 // CHECK1-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS_I]], i32 0, i32 2 -// CHECK1-NEXT: store ptr [[TMP13]], ptr [[TMP23]], align 8, !noalias !24 +// CHECK1-NEXT: store ptr [[TMP13]], ptr [[TMP23]], align 8, !noalias !25 // CHECK1-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS_I]], i32 0, i32 3 -// CHECK1-NEXT: store ptr [[TMP14]], ptr [[TMP24]], align 8, !noalias !24 +// CHECK1-NEXT: store ptr [[TMP14]], ptr [[TMP24]], align 8, !noalias !25 // CHECK1-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS_I]], i32 0, i32 4 -// CHECK1-NEXT: store ptr [[TMP15]], ptr [[TMP25]], align 8, !noalias !24 +// CHECK1-NEXT: store ptr [[TMP15]], ptr [[TMP25]], align 8, !noalias !25 // CHECK1-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS_I]], i32 0, i32 5 -// CHECK1-NEXT: store ptr @.offload_maptypes, ptr [[TMP26]], align 8, !noalias !24 +// CHECK1-NEXT: store ptr @.offload_maptypes, ptr [[TMP26]], align 8, !noalias !25 // CHECK1-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS_I]], i32 0, i32 6 -// CHECK1-NEXT: store ptr null, ptr [[TMP27]], align 8, !noalias !24 +// CHECK1-NEXT: store ptr null, ptr [[TMP27]], align 8, !noalias !25 // CHECK1-NEXT: [[TMP28:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS_I]], i32 0, i32 7 -// CHECK1-NEXT: store ptr null, ptr [[TMP28]], align 8, !noalias !24 +// CHECK1-NEXT: store ptr null, ptr [[TMP28]], align 8, !noalias !25 // CHECK1-NEXT: [[TMP29:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS_I]], i32 0, i32 8 -// CHECK1-NEXT: store i64 0, ptr [[TMP29]], align 8, !noalias !24 +// CHECK1-NEXT: store i64 0, ptr [[TMP29]], align 8, !noalias !25 // CHECK1-NEXT: [[TMP30:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS_I]], i32 0, i32 9 -// CHECK1-NEXT: store i64 1, ptr [[TMP30]], align 8, !noalias !24 +// CHECK1-NEXT: store i64 1, ptr [[TMP30]], align 8, !noalias !25 // CHECK1-NEXT: [[TMP31:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS_I]], i32 0, i32 10 -// CHECK1-NEXT: store [3 x i32] [[TMP20]], ptr [[TMP31]], align 4, !noalias !24 +// CHECK1-NEXT: store [3 x i32] [[TMP20]], ptr [[TMP31]], align 4, !noalias !25 // CHECK1-NEXT: [[TMP32:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS_I]], i32 0, i32 11 -// CHECK1-NEXT: store [3 x i32] [[TMP21]], ptr [[TMP32]], align 4, !noalias !24 +// CHECK1-NEXT: store [3 x i32] [[TMP21]], ptr [[TMP32]], align 4, !noalias !25 // CHECK1-NEXT: [[TMP33:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS_I]], i32 0, i32 12 -// CHECK1-NEXT: store i32 0, ptr [[TMP33]], align 4, !noalias !24 +// CHECK1-NEXT: store i32 0, ptr [[TMP33]], align 4, !noalias !25 // CHECK1-NEXT: [[TMP34:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB1]], i64 -1, i32 [[TMP18]], i32 [[TMP19]], ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l101.region_id, ptr [[KERNEL_ARGS_I]]) // CHECK1-NEXT: [[TMP35:%.*]] = icmp ne i32 [[TMP34]], 0 // CHECK1-NEXT: br i1 [[TMP35]], label [[OMP_OFFLOAD_FAILED_I:%.*]], label [[DOTOMP_OUTLINED__EXIT:%.*]] // CHECK1: omp_offload.failed.i: // CHECK1-NEXT: [[TMP36:%.*]] = load i16, ptr [[TMP12]], align 2 -// CHECK1-NEXT: store i16 [[TMP36]], ptr [[AA_CASTED_I]], align 2, !noalias !24 -// CHECK1-NEXT: [[TMP37:%.*]] = load i64, ptr [[AA_CASTED_I]], align 8, !noalias !24 +// CHECK1-NEXT: store i16 [[TMP36]], ptr [[AA_CASTED_I]], align 2, !noalias !25 +// CHECK1-NEXT: [[TMP37:%.*]] = load i64, ptr [[AA_CASTED_I]], align 8, !noalias !25 // CHECK1-NEXT: [[TMP38:%.*]] = load i32, ptr [[TMP16]], align 4 -// CHECK1-NEXT: store i32 [[TMP38]], ptr [[DOTCAPTURE_EXPR__CASTED_I]], align 4, !noalias !24 -// CHECK1-NEXT: [[TMP39:%.*]] = load i64, ptr [[DOTCAPTURE_EXPR__CASTED_I]], align 8, !noalias !24 +// CHECK1-NEXT: store i32 [[TMP38]], ptr [[DOTCAPTURE_EXPR__CASTED_I]], align 4, !noalias !25 +// CHECK1-NEXT: [[TMP39:%.*]] = load i64, ptr [[DOTCAPTURE_EXPR__CASTED_I]], align 8, !noalias !25 // CHECK1-NEXT: [[TMP40:%.*]] = load i32, ptr [[TMP17]], align 4 -// CHECK1-NEXT: store i32 [[TMP40]], ptr [[DOTCAPTURE_EXPR__CASTED4_I]], align 4, !noalias !24 -// CHECK1-NEXT: [[TMP41:%.*]] = load i64, ptr [[DOTCAPTURE_EXPR__CASTED4_I]], align 8, !noalias !24 +// CHECK1-NEXT: store i32 [[TMP40]], ptr [[DOTCAPTURE_EXPR__CASTED4_I]], align 4, !noalias !25 +// CHECK1-NEXT: [[TMP41:%.*]] = load i64, ptr [[DOTCAPTURE_EXPR__CASTED4_I]], align 8, !noalias !25 // CHECK1-NEXT: call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l101(i64 [[TMP37]], i64 [[TMP39]], i64 [[TMP41]]) #[[ATTR3]] // CHECK1-NEXT: br label [[DOTOMP_OUTLINED__EXIT]] // CHECK1: .omp_outlined..exit: @@ -997,7 +1062,48 @@ int bar(int n){ // CHECK1-NEXT: ret void // // -// CHECK1-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l142 +// CHECK1-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l124 +// CHECK1-SAME: (i64 noundef [[A:%.*]], i64 noundef [[AA:%.*]]) #[[ATTR2]] { +// CHECK1-NEXT: entry: +// CHECK1-NEXT: [[A_ADDR:%.*]] = alloca i64, align 8 +// CHECK1-NEXT: [[AA_ADDR:%.*]] = alloca i64, align 8 +// CHECK1-NEXT: [[A_CASTED:%.*]] = alloca i64, align 8 +// CHECK1-NEXT: [[AA_CASTED:%.*]] = alloca i64, align 8 +// CHECK1-NEXT: store i64 [[A]], ptr [[A_ADDR]], align 8 +// CHECK1-NEXT: store i64 [[AA]], ptr [[AA_ADDR]], align 8 +// CHECK1-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4 +// CHECK1-NEXT: store i32 [[TMP0]], ptr [[A_CASTED]], align 4 +// CHECK1-NEXT: [[TMP1:%.*]] = load i64, ptr [[A_CASTED]], align 8 +// CHECK1-NEXT: [[TMP2:%.*]] = load i16, ptr [[AA_ADDR]], align 2 +// CHECK1-NEXT: store i16 [[TMP2]], ptr [[AA_CASTED]], align 2 +// CHECK1-NEXT: [[TMP3:%.*]] = load i64, ptr [[AA_CASTED]], align 8 +// CHECK1-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB1]], i32 2, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l124.omp_outlined, i64 [[TMP1]], i64 [[TMP3]]) +// CHECK1-NEXT: ret void +// +// +// CHECK1-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l124.omp_outlined +// CHECK1-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], i64 noundef [[A:%.*]], i64 noundef [[AA:%.*]]) #[[ATTR2]] { +// CHECK1-NEXT: entry: +// CHECK1-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 8 +// CHECK1-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca ptr, align 8 +// CHECK1-NEXT: [[A_ADDR:%.*]] = alloca i64, align 8 +// CHECK1-NEXT: [[AA_ADDR:%.*]] = alloca i64, align 8 +// CHECK1-NEXT: store ptr [[DOTGLOBAL_TID_]], ptr [[DOTGLOBAL_TID__ADDR]], align 8 +// CHECK1-NEXT: store ptr [[DOTBOUND_TID_]], ptr [[DOTBOUND_TID__ADDR]], align 8 +// CHECK1-NEXT: store i64 [[A]], ptr [[A_ADDR]], align 8 +// CHECK1-NEXT: store i64 [[AA]], ptr [[AA_ADDR]], align 8 +// CHECK1-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4 +// CHECK1-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP0]], 1 +// CHECK1-NEXT: store i32 [[ADD]], ptr [[A_ADDR]], align 4 +// CHECK1-NEXT: [[TMP1:%.*]] = load i16, ptr [[AA_ADDR]], align 2 +// CHECK1-NEXT: [[CONV:%.*]] = sext i16 [[TMP1]] to i32 +// CHECK1-NEXT: [[ADD1:%.*]] = add nsw i32 [[CONV]], 1 +// CHECK1-NEXT: [[CONV2:%.*]] = trunc i32 [[ADD1]] to i16 +// CHECK1-NEXT: store i16 [[CONV2]], ptr [[AA_ADDR]], align 2 +// CHECK1-NEXT: ret void +// +// +// CHECK1-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l148 // CHECK1-SAME: (i64 noundef [[A:%.*]], ptr noundef nonnull align 4 dereferenceable(40) [[B:%.*]], i64 noundef [[VLA:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[BN:%.*]], ptr noundef nonnull align 8 dereferenceable(400) [[C:%.*]], i64 noundef [[VLA1:%.*]], i64 noundef [[VLA3:%.*]], ptr noundef nonnull align 8 dereferenceable(8) [[CN:%.*]], ptr noundef nonnull align 8 dereferenceable(16) [[D:%.*]]) #[[ATTR2]] { // CHECK1-NEXT: entry: // CHECK1-NEXT: [[A_ADDR:%.*]] = alloca i64, align 8 @@ -1030,11 +1136,11 @@ int bar(int n){ // CHECK1-NEXT: [[TMP8:%.*]] = load i32, ptr [[A_ADDR]], align 4 // CHECK1-NEXT: store i32 [[TMP8]], ptr [[A_CASTED]], align 4 // CHECK1-NEXT: [[TMP9:%.*]] = load i64, ptr [[A_CASTED]], align 8 -// CHECK1-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB1]], i32 9, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l142.omp_outlined, i64 [[TMP9]], ptr [[TMP0]], i64 [[TMP1]], ptr [[TMP2]], ptr [[TMP3]], i64 [[TMP4]], i64 [[TMP5]], ptr [[TMP6]], ptr [[TMP7]]) +// CHECK1-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB1]], i32 9, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l148.omp_outlined, i64 [[TMP9]], ptr [[TMP0]], i64 [[TMP1]], ptr [[TMP2]], ptr [[TMP3]], i64 [[TMP4]], i64 [[TMP5]], ptr [[TMP6]], ptr [[TMP7]]) // CHECK1-NEXT: ret void // // -// CHECK1-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l142.omp_outlined +// CHECK1-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l148.omp_outlined // CHECK1-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], i64 noundef [[A:%.*]], ptr noundef nonnull align 4 dereferenceable(40) [[B:%.*]], i64 noundef [[VLA:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[BN:%.*]], ptr noundef nonnull align 8 dereferenceable(400) [[C:%.*]], i64 noundef [[VLA1:%.*]], i64 noundef [[VLA3:%.*]], ptr noundef nonnull align 8 dereferenceable(8) [[CN:%.*]], ptr noundef nonnull align 8 dereferenceable(16) [[D:%.*]]) #[[ATTR2]] { // CHECK1-NEXT: entry: // CHECK1-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 8 @@ -1106,7 +1212,7 @@ int bar(int n){ // CHECK1-NEXT: ret void // // -// CHECK1-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l154 +// CHECK1-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l160 // CHECK1-SAME: (i64 noundef [[NN:%.*]]) #[[ATTR2]] { // CHECK1-NEXT: entry: // CHECK1-NEXT: [[NN_ADDR:%.*]] = alloca i64, align 8 @@ -1115,11 +1221,11 @@ int bar(int n){ // CHECK1-NEXT: [[TMP0:%.*]] = load i32, ptr [[NN_ADDR]], align 4 // CHECK1-NEXT: store i32 [[TMP0]], ptr [[NN_CASTED]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = load i64, ptr [[NN_CASTED]], align 8 -// CHECK1-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB1]], i32 1, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l154.omp_outlined, i64 [[TMP1]]) +// CHECK1-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB1]], i32 1, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l160.omp_outlined, i64 [[TMP1]]) // CHECK1-NEXT: ret void // // -// CHECK1-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l154.omp_outlined +// CHECK1-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l160.omp_outlined // CHECK1-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], i64 noundef [[NN:%.*]]) #[[ATTR2]] { // CHECK1-NEXT: entry: // CHECK1-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 8 @@ -1132,11 +1238,11 @@ int bar(int n){ // CHECK1-NEXT: [[TMP0:%.*]] = load i32, ptr [[NN_ADDR]], align 4 // CHECK1-NEXT: store i32 [[TMP0]], ptr [[NN_CASTED]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = load i64, ptr [[NN_CASTED]], align 8 -// CHECK1-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @[[GLOB1]], i32 1, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l154.omp_outlined.omp_outlined, i64 [[TMP1]]) +// CHECK1-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @[[GLOB1]], i32 1, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l160.omp_outlined.omp_outlined, i64 [[TMP1]]) // CHECK1-NEXT: ret void // // -// CHECK1-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l154.omp_outlined.omp_outlined +// CHECK1-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l160.omp_outlined.omp_outlined // CHECK1-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], i64 noundef [[NN:%.*]]) #[[ATTR2]] { // CHECK1-NEXT: entry: // CHECK1-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 8 @@ -1148,7 +1254,7 @@ int bar(int n){ // CHECK1-NEXT: ret void // // -// CHECK1-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l157 +// CHECK1-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l163 // CHECK1-SAME: (i64 noundef [[NN:%.*]]) #[[ATTR2]] { // CHECK1-NEXT: entry: // CHECK1-NEXT: [[NN_ADDR:%.*]] = alloca i64, align 8 @@ -1157,11 +1263,11 @@ int bar(int n){ // CHECK1-NEXT: [[TMP0:%.*]] = load i32, ptr [[NN_ADDR]], align 4 // CHECK1-NEXT: store i32 [[TMP0]], ptr [[NN_CASTED]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = load i64, ptr [[NN_CASTED]], align 8 -// CHECK1-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB1]], i32 1, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l157.omp_outlined, i64 [[TMP1]]) +// CHECK1-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB1]], i32 1, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l163.omp_outlined, i64 [[TMP1]]) // CHECK1-NEXT: ret void // // -// CHECK1-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l157.omp_outlined +// CHECK1-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l163.omp_outlined // CHECK1-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], i64 noundef [[NN:%.*]]) #[[ATTR2]] { // CHECK1-NEXT: entry: // CHECK1-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 8 @@ -1170,11 +1276,11 @@ int bar(int n){ // CHECK1-NEXT: store ptr [[DOTGLOBAL_TID_]], ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: store ptr [[DOTBOUND_TID_]], ptr [[DOTBOUND_TID__ADDR]], align 8 // CHECK1-NEXT: store i64 [[NN]], ptr [[NN_ADDR]], align 8 -// CHECK1-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @[[GLOB1]], i32 1, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l157.omp_outlined.omp_outlined, ptr [[NN_ADDR]]) +// CHECK1-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @[[GLOB1]], i32 1, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l163.omp_outlined.omp_outlined, ptr [[NN_ADDR]]) // CHECK1-NEXT: ret void // // -// CHECK1-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l157.omp_outlined.omp_outlined +// CHECK1-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l163.omp_outlined.omp_outlined // CHECK1-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[NN:%.*]]) #[[ATTR2]] { // CHECK1-NEXT: entry: // CHECK1-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 8 @@ -1217,9 +1323,9 @@ int bar(int n){ // CHECK1-NEXT: [[TMP10:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 3 // CHECK1-NEXT: store ptr [[TMP6]], ptr [[TMP10]], align 8 // CHECK1-NEXT: [[TMP11:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 4 -// CHECK1-NEXT: store ptr @.offload_sizes.11, ptr [[TMP11]], align 8 +// CHECK1-NEXT: store ptr @.offload_sizes.13, ptr [[TMP11]], align 8 // CHECK1-NEXT: [[TMP12:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 5 -// CHECK1-NEXT: store ptr @.offload_maptypes.12, ptr [[TMP12]], align 8 +// CHECK1-NEXT: store ptr @.offload_maptypes.14, ptr [[TMP12]], align 8 // CHECK1-NEXT: [[TMP13:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 6 // CHECK1-NEXT: store ptr null, ptr [[TMP13]], align 8 // CHECK1-NEXT: [[TMP14:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 7 @@ -1234,27 +1340,27 @@ int bar(int n){ // CHECK1-NEXT: store [3 x i32] zeroinitializer, ptr [[TMP18]], align 4 // CHECK1-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 12 // CHECK1-NEXT: store i32 0, ptr [[TMP19]], align 4 -// CHECK1-NEXT: [[TMP20:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB1]], i64 -1, i32 0, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z6bazzzziPi_l182.region_id, ptr [[KERNEL_ARGS]]) +// CHECK1-NEXT: [[TMP20:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB1]], i64 -1, i32 0, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z6bazzzziPi_l188.region_id, ptr [[KERNEL_ARGS]]) // CHECK1-NEXT: [[TMP21:%.*]] = icmp ne i32 [[TMP20]], 0 // CHECK1-NEXT: br i1 [[TMP21]], label [[OMP_OFFLOAD_FAILED:%.*]], label [[OMP_OFFLOAD_CONT:%.*]] // CHECK1: omp_offload.failed: -// CHECK1-NEXT: call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z6bazzzziPi_l182(i64 [[TMP1]]) #[[ATTR3]] +// CHECK1-NEXT: call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z6bazzzziPi_l188(i64 [[TMP1]]) #[[ATTR3]] // CHECK1-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK1: omp_offload.cont: // CHECK1-NEXT: ret void // // -// CHECK1-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z6bazzzziPi_l182 +// CHECK1-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z6bazzzziPi_l188 // CHECK1-SAME: (i64 noundef [[VLA:%.*]]) #[[ATTR2]] { // CHECK1-NEXT: entry: // CHECK1-NEXT: [[VLA_ADDR:%.*]] = alloca i64, align 8 // CHECK1-NEXT: store i64 [[VLA]], ptr [[VLA_ADDR]], align 8 // CHECK1-NEXT: [[TMP0:%.*]] = load i64, ptr [[VLA_ADDR]], align 8 -// CHECK1-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB1]], i32 1, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z6bazzzziPi_l182.omp_outlined, i64 [[TMP0]]) +// CHECK1-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB1]], i32 1, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z6bazzzziPi_l188.omp_outlined, i64 [[TMP0]]) // CHECK1-NEXT: ret void // // -// CHECK1-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z6bazzzziPi_l182.omp_outlined +// CHECK1-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z6bazzzziPi_l188.omp_outlined // CHECK1-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], i64 noundef [[VLA:%.*]]) #[[ATTR2]] { // CHECK1-NEXT: entry: // CHECK1-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 8 @@ -1337,7 +1443,7 @@ int bar(int n){ // CHECK1-NEXT: [[A:%.*]] = getelementptr inbounds [[STRUCT_S1:%.*]], ptr [[THIS1]], i32 0, i32 0 // CHECK1-NEXT: [[TMP8:%.*]] = mul nuw i64 2, [[TMP2]] // CHECK1-NEXT: [[TMP9:%.*]] = mul nuw i64 [[TMP8]], 2 -// CHECK1-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[DOTOFFLOAD_SIZES]], ptr align 8 @.offload_sizes.13, i64 40, i1 false) +// CHECK1-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[DOTOFFLOAD_SIZES]], ptr align 8 @.offload_sizes.15, i64 40, i1 false) // CHECK1-NEXT: [[TMP10:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: store ptr [[THIS1]], ptr [[TMP10]], align 8 // CHECK1-NEXT: [[TMP11:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 @@ -1384,7 +1490,7 @@ int bar(int n){ // CHECK1-NEXT: [[TMP33:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 4 // CHECK1-NEXT: store ptr [[TMP28]], ptr [[TMP33]], align 8 // CHECK1-NEXT: [[TMP34:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 5 -// CHECK1-NEXT: store ptr @.offload_maptypes.14, ptr [[TMP34]], align 8 +// CHECK1-NEXT: store ptr @.offload_maptypes.16, ptr [[TMP34]], align 8 // CHECK1-NEXT: [[TMP35:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 6 // CHECK1-NEXT: store ptr null, ptr [[TMP35]], align 8 // CHECK1-NEXT: [[TMP36:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 7 @@ -1399,16 +1505,16 @@ int bar(int n){ // CHECK1-NEXT: store [3 x i32] zeroinitializer, ptr [[TMP40]], align 4 // CHECK1-NEXT: [[TMP41:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 12 // CHECK1-NEXT: store i32 0, ptr [[TMP41]], align 4 -// CHECK1-NEXT: [[TMP42:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB1]], i64 -1, i32 0, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN2S12r1Ei_l227.region_id, ptr [[KERNEL_ARGS]]) +// CHECK1-NEXT: [[TMP42:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB1]], i64 -1, i32 0, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN2S12r1Ei_l233.region_id, ptr [[KERNEL_ARGS]]) // CHECK1-NEXT: [[TMP43:%.*]] = icmp ne i32 [[TMP42]], 0 // CHECK1-NEXT: br i1 [[TMP43]], label [[OMP_OFFLOAD_FAILED:%.*]], label [[OMP_OFFLOAD_CONT:%.*]] // CHECK1: omp_offload.failed: -// CHECK1-NEXT: call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN2S12r1Ei_l227(ptr [[THIS1]], i64 [[TMP6]], i64 2, i64 [[TMP2]], ptr [[VLA]]) #[[ATTR3]] +// CHECK1-NEXT: call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN2S12r1Ei_l233(ptr [[THIS1]], i64 [[TMP6]], i64 2, i64 [[TMP2]], ptr [[VLA]]) #[[ATTR3]] // CHECK1-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK1: omp_offload.cont: // CHECK1-NEXT: br label [[OMP_IF_END:%.*]] // CHECK1: omp_if.else: -// CHECK1-NEXT: call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN2S12r1Ei_l227(ptr [[THIS1]], i64 [[TMP6]], i64 2, i64 [[TMP2]], ptr [[VLA]]) #[[ATTR3]] +// CHECK1-NEXT: call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN2S12r1Ei_l233(ptr [[THIS1]], i64 [[TMP6]], i64 2, i64 [[TMP2]], ptr [[VLA]]) #[[ATTR3]] // CHECK1-NEXT: br label [[OMP_IF_END]] // CHECK1: omp_if.end: // CHECK1-NEXT: [[TMP44:%.*]] = mul nsw i64 1, [[TMP2]] @@ -1490,9 +1596,9 @@ int bar(int n){ // CHECK1-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 3 // CHECK1-NEXT: store ptr [[TMP20]], ptr [[TMP24]], align 8 // CHECK1-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 4 -// CHECK1-NEXT: store ptr @.offload_sizes.15, ptr [[TMP25]], align 8 +// CHECK1-NEXT: store ptr @.offload_sizes.17, ptr [[TMP25]], align 8 // CHECK1-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 5 -// CHECK1-NEXT: store ptr @.offload_maptypes.16, ptr [[TMP26]], align 8 +// CHECK1-NEXT: store ptr @.offload_maptypes.18, ptr [[TMP26]], align 8 // CHECK1-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 6 // CHECK1-NEXT: store ptr null, ptr [[TMP27]], align 8 // CHECK1-NEXT: [[TMP28:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 7 @@ -1507,16 +1613,16 @@ int bar(int n){ // CHECK1-NEXT: store [3 x i32] zeroinitializer, ptr [[TMP32]], align 4 // CHECK1-NEXT: [[TMP33:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 12 // CHECK1-NEXT: store i32 0, ptr [[TMP33]], align 4 -// CHECK1-NEXT: [[TMP34:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB1]], i64 -1, i32 0, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZL7fstatici_l209.region_id, ptr [[KERNEL_ARGS]]) +// CHECK1-NEXT: [[TMP34:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB1]], i64 -1, i32 0, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZL7fstatici_l215.region_id, ptr [[KERNEL_ARGS]]) // CHECK1-NEXT: [[TMP35:%.*]] = icmp ne i32 [[TMP34]], 0 // CHECK1-NEXT: br i1 [[TMP35]], label [[OMP_OFFLOAD_FAILED:%.*]], label [[OMP_OFFLOAD_CONT:%.*]] // CHECK1: omp_offload.failed: -// CHECK1-NEXT: call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZL7fstatici_l209(i64 [[TMP1]], i64 [[TMP3]], i64 [[TMP5]], ptr [[B]]) #[[ATTR3]] +// CHECK1-NEXT: call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZL7fstatici_l215(i64 [[TMP1]], i64 [[TMP3]], i64 [[TMP5]], ptr [[B]]) #[[ATTR3]] // CHECK1-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK1: omp_offload.cont: // CHECK1-NEXT: br label [[OMP_IF_END:%.*]] // CHECK1: omp_if.else: -// CHECK1-NEXT: call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZL7fstatici_l209(i64 [[TMP1]], i64 [[TMP3]], i64 [[TMP5]], ptr [[B]]) #[[ATTR3]] +// CHECK1-NEXT: call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZL7fstatici_l215(i64 [[TMP1]], i64 [[TMP3]], i64 [[TMP5]], ptr [[B]]) #[[ATTR3]] // CHECK1-NEXT: br label [[OMP_IF_END]] // CHECK1: omp_if.end: // CHECK1-NEXT: [[TMP36:%.*]] = load i32, ptr [[A]], align 4 @@ -1578,9 +1684,9 @@ int bar(int n){ // CHECK1-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 3 // CHECK1-NEXT: store ptr [[TMP15]], ptr [[TMP19]], align 8 // CHECK1-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 4 -// CHECK1-NEXT: store ptr @.offload_sizes.17, ptr [[TMP20]], align 8 +// CHECK1-NEXT: store ptr @.offload_sizes.19, ptr [[TMP20]], align 8 // CHECK1-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 5 -// CHECK1-NEXT: store ptr @.offload_maptypes.18, ptr [[TMP21]], align 8 +// CHECK1-NEXT: store ptr @.offload_maptypes.20, ptr [[TMP21]], align 8 // CHECK1-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 6 // CHECK1-NEXT: store ptr null, ptr [[TMP22]], align 8 // CHECK1-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 7 @@ -1595,23 +1701,23 @@ int bar(int n){ // CHECK1-NEXT: store [3 x i32] zeroinitializer, ptr [[TMP27]], align 4 // CHECK1-NEXT: [[TMP28:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 12 // CHECK1-NEXT: store i32 0, ptr [[TMP28]], align 4 -// CHECK1-NEXT: [[TMP29:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB1]], i64 -1, i32 0, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z9ftemplateIiET_i_l192.region_id, ptr [[KERNEL_ARGS]]) +// CHECK1-NEXT: [[TMP29:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB1]], i64 -1, i32 0, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z9ftemplateIiET_i_l198.region_id, ptr [[KERNEL_ARGS]]) // CHECK1-NEXT: [[TMP30:%.*]] = icmp ne i32 [[TMP29]], 0 // CHECK1-NEXT: br i1 [[TMP30]], label [[OMP_OFFLOAD_FAILED:%.*]], label [[OMP_OFFLOAD_CONT:%.*]] // CHECK1: omp_offload.failed: -// CHECK1-NEXT: call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z9ftemplateIiET_i_l192(i64 [[TMP1]], i64 [[TMP3]], ptr [[B]]) #[[ATTR3]] +// CHECK1-NEXT: call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z9ftemplateIiET_i_l198(i64 [[TMP1]], i64 [[TMP3]], ptr [[B]]) #[[ATTR3]] // CHECK1-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK1: omp_offload.cont: // CHECK1-NEXT: br label [[OMP_IF_END:%.*]] // CHECK1: omp_if.else: -// CHECK1-NEXT: call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z9ftemplateIiET_i_l192(i64 [[TMP1]], i64 [[TMP3]], ptr [[B]]) #[[ATTR3]] +// CHECK1-NEXT: call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z9ftemplateIiET_i_l198(i64 [[TMP1]], i64 [[TMP3]], ptr [[B]]) #[[ATTR3]] // CHECK1-NEXT: br label [[OMP_IF_END]] // CHECK1: omp_if.end: // CHECK1-NEXT: [[TMP31:%.*]] = load i32, ptr [[A]], align 4 // CHECK1-NEXT: ret i32 [[TMP31]] // // -// CHECK1-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN2S12r1Ei_l227 +// CHECK1-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN2S12r1Ei_l233 // CHECK1-SAME: (ptr noundef [[THIS:%.*]], i64 noundef [[B:%.*]], i64 noundef [[VLA:%.*]], i64 noundef [[VLA1:%.*]], ptr noundef nonnull align 2 dereferenceable(2) [[C:%.*]]) #[[ATTR2]] { // CHECK1-NEXT: entry: // CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 @@ -1632,11 +1738,11 @@ int bar(int n){ // CHECK1-NEXT: [[TMP4:%.*]] = load i32, ptr [[B_ADDR]], align 4 // CHECK1-NEXT: store i32 [[TMP4]], ptr [[B_CASTED]], align 4 // CHECK1-NEXT: [[TMP5:%.*]] = load i64, ptr [[B_CASTED]], align 8 -// CHECK1-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB1]], i32 5, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN2S12r1Ei_l227.omp_outlined, ptr [[TMP0]], i64 [[TMP5]], i64 [[TMP1]], i64 [[TMP2]], ptr [[TMP3]]) +// CHECK1-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB1]], i32 5, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN2S12r1Ei_l233.omp_outlined, ptr [[TMP0]], i64 [[TMP5]], i64 [[TMP1]], i64 [[TMP2]], ptr [[TMP3]]) // CHECK1-NEXT: ret void // // -// CHECK1-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN2S12r1Ei_l227.omp_outlined +// CHECK1-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN2S12r1Ei_l233.omp_outlined // CHECK1-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], ptr noundef [[THIS:%.*]], i64 noundef [[B:%.*]], i64 noundef [[VLA:%.*]], i64 noundef [[VLA1:%.*]], ptr noundef nonnull align 2 dereferenceable(2) [[C:%.*]]) #[[ATTR2]] { // CHECK1-NEXT: entry: // CHECK1-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 8 @@ -1674,7 +1780,7 @@ int bar(int n){ // CHECK1-NEXT: ret void // // -// CHECK1-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZL7fstatici_l209 +// CHECK1-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZL7fstatici_l215 // CHECK1-SAME: (i64 noundef [[A:%.*]], i64 noundef [[AA:%.*]], i64 noundef [[AAA:%.*]], ptr noundef nonnull align 4 dereferenceable(40) [[B:%.*]]) #[[ATTR2]] { // CHECK1-NEXT: entry: // CHECK1-NEXT: [[A_ADDR:%.*]] = alloca i64, align 8 @@ -1698,11 +1804,11 @@ int bar(int n){ // CHECK1-NEXT: [[TMP5:%.*]] = load i8, ptr [[AAA_ADDR]], align 1 // CHECK1-NEXT: store i8 [[TMP5]], ptr [[AAA_CASTED]], align 1 // CHECK1-NEXT: [[TMP6:%.*]] = load i64, ptr [[AAA_CASTED]], align 8 -// CHECK1-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB1]], i32 4, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZL7fstatici_l209.omp_outlined, i64 [[TMP2]], i64 [[TMP4]], i64 [[TMP6]], ptr [[TMP0]]) +// CHECK1-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB1]], i32 4, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZL7fstatici_l215.omp_outlined, i64 [[TMP2]], i64 [[TMP4]], i64 [[TMP6]], ptr [[TMP0]]) // CHECK1-NEXT: ret void // // -// CHECK1-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZL7fstatici_l209.omp_outlined +// CHECK1-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZL7fstatici_l215.omp_outlined // CHECK1-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], i64 noundef [[A:%.*]], i64 noundef [[AA:%.*]], i64 noundef [[AAA:%.*]], ptr noundef nonnull align 4 dereferenceable(40) [[B:%.*]]) #[[ATTR2]] { // CHECK1-NEXT: entry: // CHECK1-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 8 @@ -1738,7 +1844,7 @@ int bar(int n){ // CHECK1-NEXT: ret void // // -// CHECK1-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z9ftemplateIiET_i_l192 +// CHECK1-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z9ftemplateIiET_i_l198 // CHECK1-SAME: (i64 noundef [[A:%.*]], i64 noundef [[AA:%.*]], ptr noundef nonnull align 4 dereferenceable(40) [[B:%.*]]) #[[ATTR2]] { // CHECK1-NEXT: entry: // CHECK1-NEXT: [[A_ADDR:%.*]] = alloca i64, align 8 @@ -1756,11 +1862,11 @@ int bar(int n){ // CHECK1-NEXT: [[TMP3:%.*]] = load i16, ptr [[AA_ADDR]], align 2 // CHECK1-NEXT: store i16 [[TMP3]], ptr [[AA_CASTED]], align 2 // CHECK1-NEXT: [[TMP4:%.*]] = load i64, ptr [[AA_CASTED]], align 8 -// CHECK1-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB1]], i32 3, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z9ftemplateIiET_i_l192.omp_outlined, i64 [[TMP2]], i64 [[TMP4]], ptr [[TMP0]]) +// CHECK1-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB1]], i32 3, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z9ftemplateIiET_i_l198.omp_outlined, i64 [[TMP2]], i64 [[TMP4]], ptr [[TMP0]]) // CHECK1-NEXT: ret void // // -// CHECK1-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z9ftemplateIiET_i_l192.omp_outlined +// CHECK1-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z9ftemplateIiET_i_l198.omp_outlined // CHECK1-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], i64 noundef [[A:%.*]], i64 noundef [[AA:%.*]], ptr noundef nonnull align 4 dereferenceable(40) [[B:%.*]]) #[[ATTR2]] { // CHECK1-NEXT: entry: // CHECK1-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 8 @@ -1830,22 +1936,28 @@ int bar(int n){ // CHECK3-NEXT: [[DOTOFFLOAD_MAPPERS12:%.*]] = alloca [2 x ptr], align 4 // CHECK3-NEXT: [[KERNEL_ARGS13:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK3-NEXT: [[A_CASTED16:%.*]] = alloca i32, align 4 -// CHECK3-NEXT: [[DOTOFFLOAD_BASEPTRS19:%.*]] = alloca [9 x ptr], align 4 -// CHECK3-NEXT: [[DOTOFFLOAD_PTRS20:%.*]] = alloca [9 x ptr], align 4 -// CHECK3-NEXT: [[DOTOFFLOAD_MAPPERS21:%.*]] = alloca [9 x ptr], align 4 +// CHECK3-NEXT: [[AA_CASTED17:%.*]] = alloca i32, align 4 +// CHECK3-NEXT: [[DOTOFFLOAD_BASEPTRS18:%.*]] = alloca [2 x ptr], align 4 +// CHECK3-NEXT: [[DOTOFFLOAD_PTRS19:%.*]] = alloca [2 x ptr], align 4 +// CHECK3-NEXT: [[DOTOFFLOAD_MAPPERS20:%.*]] = alloca [2 x ptr], align 4 +// CHECK3-NEXT: [[KERNEL_ARGS21:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 +// CHECK3-NEXT: [[A_CASTED24:%.*]] = alloca i32, align 4 +// CHECK3-NEXT: [[DOTOFFLOAD_BASEPTRS27:%.*]] = alloca [9 x ptr], align 4 +// CHECK3-NEXT: [[DOTOFFLOAD_PTRS28:%.*]] = alloca [9 x ptr], align 4 +// CHECK3-NEXT: [[DOTOFFLOAD_MAPPERS29:%.*]] = alloca [9 x ptr], align 4 // CHECK3-NEXT: [[DOTOFFLOAD_SIZES:%.*]] = alloca [9 x i64], align 4 -// CHECK3-NEXT: [[KERNEL_ARGS22:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 +// CHECK3-NEXT: [[KERNEL_ARGS30:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK3-NEXT: [[NN:%.*]] = alloca i32, align 4 // CHECK3-NEXT: [[NN_CASTED:%.*]] = alloca i32, align 4 -// CHECK3-NEXT: [[DOTOFFLOAD_BASEPTRS27:%.*]] = alloca [1 x ptr], align 4 -// CHECK3-NEXT: [[DOTOFFLOAD_PTRS28:%.*]] = alloca [1 x ptr], align 4 -// CHECK3-NEXT: [[DOTOFFLOAD_MAPPERS29:%.*]] = alloca [1 x ptr], align 4 -// CHECK3-NEXT: [[KERNEL_ARGS30:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 -// CHECK3-NEXT: [[NN_CASTED33:%.*]] = alloca i32, align 4 -// CHECK3-NEXT: [[DOTOFFLOAD_BASEPTRS34:%.*]] = alloca [1 x ptr], align 4 -// CHECK3-NEXT: [[DOTOFFLOAD_PTRS35:%.*]] = alloca [1 x ptr], align 4 -// CHECK3-NEXT: [[DOTOFFLOAD_MAPPERS36:%.*]] = alloca [1 x ptr], align 4 -// CHECK3-NEXT: [[KERNEL_ARGS37:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 +// CHECK3-NEXT: [[DOTOFFLOAD_BASEPTRS35:%.*]] = alloca [1 x ptr], align 4 +// CHECK3-NEXT: [[DOTOFFLOAD_PTRS36:%.*]] = alloca [1 x ptr], align 4 +// CHECK3-NEXT: [[DOTOFFLOAD_MAPPERS37:%.*]] = alloca [1 x ptr], align 4 +// CHECK3-NEXT: [[KERNEL_ARGS38:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 +// CHECK3-NEXT: [[NN_CASTED41:%.*]] = alloca i32, align 4 +// CHECK3-NEXT: [[DOTOFFLOAD_BASEPTRS42:%.*]] = alloca [1 x ptr], align 4 +// CHECK3-NEXT: [[DOTOFFLOAD_PTRS43:%.*]] = alloca [1 x ptr], align 4 +// CHECK3-NEXT: [[DOTOFFLOAD_MAPPERS44:%.*]] = alloca [1 x ptr], align 4 +// CHECK3-NEXT: [[KERNEL_ARGS45:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK3-NEXT: [[TMP0:%.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GLOB1:[0-9]+]]) // CHECK3-NEXT: store i32 [[N]], ptr [[N_ADDR]], align 4 // CHECK3-NEXT: store i32 0, ptr [[A]], align 4 @@ -2030,208 +2142,261 @@ int bar(int n){ // CHECK3-NEXT: [[TMP93:%.*]] = load i32, ptr [[A]], align 4 // CHECK3-NEXT: store i32 [[TMP93]], ptr [[A_CASTED16]], align 4 // CHECK3-NEXT: [[TMP94:%.*]] = load i32, ptr [[A_CASTED16]], align 4 -// CHECK3-NEXT: [[TMP95:%.*]] = load i32, ptr [[N_ADDR]], align 4 -// CHECK3-NEXT: [[CMP17:%.*]] = icmp sgt i32 [[TMP95]], 20 -// CHECK3-NEXT: br i1 [[CMP17]], label [[OMP_IF_THEN18:%.*]], label [[OMP_IF_ELSE25:%.*]] -// CHECK3: omp_if.then18: -// CHECK3-NEXT: [[TMP96:%.*]] = mul nuw i32 [[TMP1]], 4 -// CHECK3-NEXT: [[TMP97:%.*]] = sext i32 [[TMP96]] to i64 -// CHECK3-NEXT: [[TMP98:%.*]] = mul nuw i32 5, [[TMP3]] -// CHECK3-NEXT: [[TMP99:%.*]] = mul nuw i32 [[TMP98]], 8 -// CHECK3-NEXT: [[TMP100:%.*]] = sext i32 [[TMP99]] to i64 -// CHECK3-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[DOTOFFLOAD_SIZES]], ptr align 4 @.offload_sizes.5, i32 72, i1 false) -// CHECK3-NEXT: [[TMP101:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_BASEPTRS19]], i32 0, i32 0 -// CHECK3-NEXT: store i32 [[TMP94]], ptr [[TMP101]], align 4 -// CHECK3-NEXT: [[TMP102:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS20]], i32 0, i32 0 -// CHECK3-NEXT: store i32 [[TMP94]], ptr [[TMP102]], align 4 -// CHECK3-NEXT: [[TMP103:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_MAPPERS21]], i32 0, i32 0 -// CHECK3-NEXT: store ptr null, ptr [[TMP103]], align 4 -// CHECK3-NEXT: [[TMP104:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_BASEPTRS19]], i32 0, i32 1 -// CHECK3-NEXT: store ptr [[B]], ptr [[TMP104]], align 4 -// CHECK3-NEXT: [[TMP105:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS20]], i32 0, i32 1 -// CHECK3-NEXT: store ptr [[B]], ptr [[TMP105]], align 4 -// CHECK3-NEXT: [[TMP106:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_MAPPERS21]], i32 0, i32 1 -// CHECK3-NEXT: store ptr null, ptr [[TMP106]], align 4 -// CHECK3-NEXT: [[TMP107:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_BASEPTRS19]], i32 0, i32 2 -// CHECK3-NEXT: store i32 [[TMP1]], ptr [[TMP107]], align 4 -// CHECK3-NEXT: [[TMP108:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS20]], i32 0, i32 2 -// CHECK3-NEXT: store i32 [[TMP1]], ptr [[TMP108]], align 4 -// CHECK3-NEXT: [[TMP109:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_MAPPERS21]], i32 0, i32 2 -// CHECK3-NEXT: store ptr null, ptr [[TMP109]], align 4 -// CHECK3-NEXT: [[TMP110:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_BASEPTRS19]], i32 0, i32 3 -// CHECK3-NEXT: store ptr [[VLA]], ptr [[TMP110]], align 4 -// CHECK3-NEXT: [[TMP111:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS20]], i32 0, i32 3 -// CHECK3-NEXT: store ptr [[VLA]], ptr [[TMP111]], align 4 -// CHECK3-NEXT: [[TMP112:%.*]] = getelementptr inbounds [9 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 3 -// CHECK3-NEXT: store i64 [[TMP97]], ptr [[TMP112]], align 4 -// CHECK3-NEXT: [[TMP113:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_MAPPERS21]], i32 0, i32 3 -// CHECK3-NEXT: store ptr null, ptr [[TMP113]], align 4 -// CHECK3-NEXT: [[TMP114:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_BASEPTRS19]], i32 0, i32 4 -// CHECK3-NEXT: store ptr [[C]], ptr [[TMP114]], align 4 -// CHECK3-NEXT: [[TMP115:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS20]], i32 0, i32 4 -// CHECK3-NEXT: store ptr [[C]], ptr [[TMP115]], align 4 -// CHECK3-NEXT: [[TMP116:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_MAPPERS21]], i32 0, i32 4 -// CHECK3-NEXT: store ptr null, ptr [[TMP116]], align 4 -// CHECK3-NEXT: [[TMP117:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_BASEPTRS19]], i32 0, i32 5 -// CHECK3-NEXT: store i32 5, ptr [[TMP117]], align 4 -// CHECK3-NEXT: [[TMP118:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS20]], i32 0, i32 5 -// CHECK3-NEXT: store i32 5, ptr [[TMP118]], align 4 -// CHECK3-NEXT: [[TMP119:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_MAPPERS21]], i32 0, i32 5 -// CHECK3-NEXT: store ptr null, ptr [[TMP119]], align 4 -// CHECK3-NEXT: [[TMP120:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_BASEPTRS19]], i32 0, i32 6 -// CHECK3-NEXT: store i32 [[TMP3]], ptr [[TMP120]], align 4 -// CHECK3-NEXT: [[TMP121:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS20]], i32 0, i32 6 -// CHECK3-NEXT: store i32 [[TMP3]], ptr [[TMP121]], align 4 -// CHECK3-NEXT: [[TMP122:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_MAPPERS21]], i32 0, i32 6 -// CHECK3-NEXT: store ptr null, ptr [[TMP122]], align 4 -// CHECK3-NEXT: [[TMP123:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_BASEPTRS19]], i32 0, i32 7 -// CHECK3-NEXT: store ptr [[VLA1]], ptr [[TMP123]], align 4 -// CHECK3-NEXT: [[TMP124:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS20]], i32 0, i32 7 -// CHECK3-NEXT: store ptr [[VLA1]], ptr [[TMP124]], align 4 -// CHECK3-NEXT: [[TMP125:%.*]] = getelementptr inbounds [9 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 7 -// CHECK3-NEXT: store i64 [[TMP100]], ptr [[TMP125]], align 4 -// CHECK3-NEXT: [[TMP126:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_MAPPERS21]], i32 0, i32 7 -// CHECK3-NEXT: store ptr null, ptr [[TMP126]], align 4 -// CHECK3-NEXT: [[TMP127:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_BASEPTRS19]], i32 0, i32 8 -// CHECK3-NEXT: store ptr [[D]], ptr [[TMP127]], align 4 -// CHECK3-NEXT: [[TMP128:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS20]], i32 0, i32 8 -// CHECK3-NEXT: store ptr [[D]], ptr [[TMP128]], align 4 -// CHECK3-NEXT: [[TMP129:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_MAPPERS21]], i32 0, i32 8 -// CHECK3-NEXT: store ptr null, ptr [[TMP129]], align 4 -// CHECK3-NEXT: [[TMP130:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_BASEPTRS19]], i32 0, i32 0 -// CHECK3-NEXT: [[TMP131:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS20]], i32 0, i32 0 -// CHECK3-NEXT: [[TMP132:%.*]] = getelementptr inbounds [9 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0 -// CHECK3-NEXT: [[TMP133:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS22]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP133]], align 4 -// CHECK3-NEXT: [[TMP134:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS22]], i32 0, i32 1 -// CHECK3-NEXT: store i32 9, ptr [[TMP134]], align 4 -// CHECK3-NEXT: [[TMP135:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS22]], i32 0, i32 2 -// CHECK3-NEXT: store ptr [[TMP130]], ptr [[TMP135]], align 4 -// CHECK3-NEXT: [[TMP136:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS22]], i32 0, i32 3 -// CHECK3-NEXT: store ptr [[TMP131]], ptr [[TMP136]], align 4 -// CHECK3-NEXT: [[TMP137:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS22]], i32 0, i32 4 -// CHECK3-NEXT: store ptr [[TMP132]], ptr [[TMP137]], align 4 -// CHECK3-NEXT: [[TMP138:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS22]], i32 0, i32 5 -// CHECK3-NEXT: store ptr @.offload_maptypes.6, ptr [[TMP138]], align 4 -// CHECK3-NEXT: [[TMP139:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS22]], i32 0, i32 6 -// CHECK3-NEXT: store ptr null, ptr [[TMP139]], align 4 -// CHECK3-NEXT: [[TMP140:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS22]], i32 0, i32 7 +// CHECK3-NEXT: [[TMP95:%.*]] = load i16, ptr [[AA]], align 2 +// CHECK3-NEXT: store i16 [[TMP95]], ptr [[AA_CASTED17]], align 2 +// CHECK3-NEXT: [[TMP96:%.*]] = load i32, ptr [[AA_CASTED17]], align 4 +// CHECK3-NEXT: [[TMP97:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS18]], i32 0, i32 0 +// CHECK3-NEXT: store i32 [[TMP94]], ptr [[TMP97]], align 4 +// CHECK3-NEXT: [[TMP98:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS19]], i32 0, i32 0 +// CHECK3-NEXT: store i32 [[TMP94]], ptr [[TMP98]], align 4 +// CHECK3-NEXT: [[TMP99:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS20]], i32 0, i32 0 +// CHECK3-NEXT: store ptr null, ptr [[TMP99]], align 4 +// CHECK3-NEXT: [[TMP100:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS18]], i32 0, i32 1 +// CHECK3-NEXT: store i32 [[TMP96]], ptr [[TMP100]], align 4 +// CHECK3-NEXT: [[TMP101:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS19]], i32 0, i32 1 +// CHECK3-NEXT: store i32 [[TMP96]], ptr [[TMP101]], align 4 +// CHECK3-NEXT: [[TMP102:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS20]], i32 0, i32 1 +// CHECK3-NEXT: store ptr null, ptr [[TMP102]], align 4 +// CHECK3-NEXT: [[TMP103:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS18]], i32 0, i32 0 +// CHECK3-NEXT: [[TMP104:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS19]], i32 0, i32 0 +// CHECK3-NEXT: [[TMP105:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS21]], i32 0, i32 0 +// CHECK3-NEXT: store i32 2, ptr [[TMP105]], align 4 +// CHECK3-NEXT: [[TMP106:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS21]], i32 0, i32 1 +// CHECK3-NEXT: store i32 2, ptr [[TMP106]], align 4 +// CHECK3-NEXT: [[TMP107:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS21]], i32 0, i32 2 +// CHECK3-NEXT: store ptr [[TMP103]], ptr [[TMP107]], align 4 +// CHECK3-NEXT: [[TMP108:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS21]], i32 0, i32 3 +// CHECK3-NEXT: store ptr [[TMP104]], ptr [[TMP108]], align 4 +// CHECK3-NEXT: [[TMP109:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS21]], i32 0, i32 4 +// CHECK3-NEXT: store ptr @.offload_sizes.5, ptr [[TMP109]], align 4 +// CHECK3-NEXT: [[TMP110:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS21]], i32 0, i32 5 +// CHECK3-NEXT: store ptr @.offload_maptypes.6, ptr [[TMP110]], align 4 +// CHECK3-NEXT: [[TMP111:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS21]], i32 0, i32 6 +// CHECK3-NEXT: store ptr null, ptr [[TMP111]], align 4 +// CHECK3-NEXT: [[TMP112:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS21]], i32 0, i32 7 +// CHECK3-NEXT: store ptr null, ptr [[TMP112]], align 4 +// CHECK3-NEXT: [[TMP113:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS21]], i32 0, i32 8 +// CHECK3-NEXT: store i64 0, ptr [[TMP113]], align 8 +// CHECK3-NEXT: [[TMP114:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS21]], i32 0, i32 9 +// CHECK3-NEXT: store i64 0, ptr [[TMP114]], align 8 +// CHECK3-NEXT: [[TMP115:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS21]], i32 0, i32 10 +// CHECK3-NEXT: store [3 x i32] zeroinitializer, ptr [[TMP115]], align 4 +// CHECK3-NEXT: [[TMP116:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS21]], i32 0, i32 11 +// CHECK3-NEXT: store [3 x i32] zeroinitializer, ptr [[TMP116]], align 4 +// CHECK3-NEXT: [[TMP117:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS21]], i32 0, i32 12 +// CHECK3-NEXT: store i32 0, ptr [[TMP117]], align 4 +// CHECK3-NEXT: [[TMP118:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB1]], i64 -1, i32 0, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l124.region_id, ptr [[KERNEL_ARGS21]]) +// CHECK3-NEXT: [[TMP119:%.*]] = icmp ne i32 [[TMP118]], 0 +// CHECK3-NEXT: br i1 [[TMP119]], label [[OMP_OFFLOAD_FAILED22:%.*]], label [[OMP_OFFLOAD_CONT23:%.*]] +// CHECK3: omp_offload.failed22: +// CHECK3-NEXT: call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l124(i32 [[TMP94]], i32 [[TMP96]]) #[[ATTR3]] +// CHECK3-NEXT: br label [[OMP_OFFLOAD_CONT23]] +// CHECK3: omp_offload.cont23: +// CHECK3-NEXT: [[TMP120:%.*]] = load i32, ptr [[A]], align 4 +// CHECK3-NEXT: store i32 [[TMP120]], ptr [[A_CASTED24]], align 4 +// CHECK3-NEXT: [[TMP121:%.*]] = load i32, ptr [[A_CASTED24]], align 4 +// CHECK3-NEXT: [[TMP122:%.*]] = load i32, ptr [[N_ADDR]], align 4 +// CHECK3-NEXT: [[CMP25:%.*]] = icmp sgt i32 [[TMP122]], 20 +// CHECK3-NEXT: br i1 [[CMP25]], label [[OMP_IF_THEN26:%.*]], label [[OMP_IF_ELSE33:%.*]] +// CHECK3: omp_if.then26: +// CHECK3-NEXT: [[TMP123:%.*]] = mul nuw i32 [[TMP1]], 4 +// CHECK3-NEXT: [[TMP124:%.*]] = sext i32 [[TMP123]] to i64 +// CHECK3-NEXT: [[TMP125:%.*]] = mul nuw i32 5, [[TMP3]] +// CHECK3-NEXT: [[TMP126:%.*]] = mul nuw i32 [[TMP125]], 8 +// CHECK3-NEXT: [[TMP127:%.*]] = sext i32 [[TMP126]] to i64 +// CHECK3-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[DOTOFFLOAD_SIZES]], ptr align 4 @.offload_sizes.7, i32 72, i1 false) +// CHECK3-NEXT: [[TMP128:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_BASEPTRS27]], i32 0, i32 0 +// CHECK3-NEXT: store i32 [[TMP121]], ptr [[TMP128]], align 4 +// CHECK3-NEXT: [[TMP129:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS28]], i32 0, i32 0 +// CHECK3-NEXT: store i32 [[TMP121]], ptr [[TMP129]], align 4 +// CHECK3-NEXT: [[TMP130:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_MAPPERS29]], i32 0, i32 0 +// CHECK3-NEXT: store ptr null, ptr [[TMP130]], align 4 +// CHECK3-NEXT: [[TMP131:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_BASEPTRS27]], i32 0, i32 1 +// CHECK3-NEXT: store ptr [[B]], ptr [[TMP131]], align 4 +// CHECK3-NEXT: [[TMP132:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS28]], i32 0, i32 1 +// CHECK3-NEXT: store ptr [[B]], ptr [[TMP132]], align 4 +// CHECK3-NEXT: [[TMP133:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_MAPPERS29]], i32 0, i32 1 +// CHECK3-NEXT: store ptr null, ptr [[TMP133]], align 4 +// CHECK3-NEXT: [[TMP134:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_BASEPTRS27]], i32 0, i32 2 +// CHECK3-NEXT: store i32 [[TMP1]], ptr [[TMP134]], align 4 +// CHECK3-NEXT: [[TMP135:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS28]], i32 0, i32 2 +// CHECK3-NEXT: store i32 [[TMP1]], ptr [[TMP135]], align 4 +// CHECK3-NEXT: [[TMP136:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_MAPPERS29]], i32 0, i32 2 +// CHECK3-NEXT: store ptr null, ptr [[TMP136]], align 4 +// CHECK3-NEXT: [[TMP137:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_BASEPTRS27]], i32 0, i32 3 +// CHECK3-NEXT: store ptr [[VLA]], ptr [[TMP137]], align 4 +// CHECK3-NEXT: [[TMP138:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS28]], i32 0, i32 3 +// CHECK3-NEXT: store ptr [[VLA]], ptr [[TMP138]], align 4 +// CHECK3-NEXT: [[TMP139:%.*]] = getelementptr inbounds [9 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 3 +// CHECK3-NEXT: store i64 [[TMP124]], ptr [[TMP139]], align 4 +// CHECK3-NEXT: [[TMP140:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_MAPPERS29]], i32 0, i32 3 // CHECK3-NEXT: store ptr null, ptr [[TMP140]], align 4 -// CHECK3-NEXT: [[TMP141:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS22]], i32 0, i32 8 -// CHECK3-NEXT: store i64 0, ptr [[TMP141]], align 8 -// CHECK3-NEXT: [[TMP142:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS22]], i32 0, i32 9 -// CHECK3-NEXT: store i64 0, ptr [[TMP142]], align 8 -// CHECK3-NEXT: [[TMP143:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS22]], i32 0, i32 10 -// CHECK3-NEXT: store [3 x i32] zeroinitializer, ptr [[TMP143]], align 4 -// CHECK3-NEXT: [[TMP144:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS22]], i32 0, i32 11 -// CHECK3-NEXT: store [3 x i32] zeroinitializer, ptr [[TMP144]], align 4 -// CHECK3-NEXT: [[TMP145:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS22]], i32 0, i32 12 -// CHECK3-NEXT: store i32 0, ptr [[TMP145]], align 4 -// CHECK3-NEXT: [[TMP146:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB1]], i64 -1, i32 0, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l142.region_id, ptr [[KERNEL_ARGS22]]) -// CHECK3-NEXT: [[TMP147:%.*]] = icmp ne i32 [[TMP146]], 0 -// CHECK3-NEXT: br i1 [[TMP147]], label [[OMP_OFFLOAD_FAILED23:%.*]], label [[OMP_OFFLOAD_CONT24:%.*]] -// CHECK3: omp_offload.failed23: -// CHECK3-NEXT: call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l142(i32 [[TMP94]], ptr [[B]], i32 [[TMP1]], ptr [[VLA]], ptr [[C]], i32 5, i32 [[TMP3]], ptr [[VLA1]], ptr [[D]]) #[[ATTR3]] -// CHECK3-NEXT: br label [[OMP_OFFLOAD_CONT24]] -// CHECK3: omp_offload.cont24: -// CHECK3-NEXT: br label [[OMP_IF_END26:%.*]] -// CHECK3: omp_if.else25: -// CHECK3-NEXT: call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l142(i32 [[TMP94]], ptr [[B]], i32 [[TMP1]], ptr [[VLA]], ptr [[C]], i32 5, i32 [[TMP3]], ptr [[VLA1]], ptr [[D]]) #[[ATTR3]] -// CHECK3-NEXT: br label [[OMP_IF_END26]] -// CHECK3: omp_if.end26: -// CHECK3-NEXT: store i32 0, ptr [[NN]], align 4 -// CHECK3-NEXT: [[TMP148:%.*]] = load i32, ptr [[NN]], align 4 -// CHECK3-NEXT: store i32 [[TMP148]], ptr [[NN_CASTED]], align 4 -// CHECK3-NEXT: [[TMP149:%.*]] = load i32, ptr [[NN_CASTED]], align 4 -// CHECK3-NEXT: [[TMP150:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS27]], i32 0, i32 0 -// CHECK3-NEXT: store i32 [[TMP149]], ptr [[TMP150]], align 4 -// CHECK3-NEXT: [[TMP151:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS28]], i32 0, i32 0 -// CHECK3-NEXT: store i32 [[TMP149]], ptr [[TMP151]], align 4 -// CHECK3-NEXT: [[TMP152:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_MAPPERS29]], i32 0, i32 0 -// CHECK3-NEXT: store ptr null, ptr [[TMP152]], align 4 -// CHECK3-NEXT: [[TMP153:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS27]], i32 0, i32 0 -// CHECK3-NEXT: [[TMP154:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS28]], i32 0, i32 0 -// CHECK3-NEXT: [[TMP155:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP155]], align 4 -// CHECK3-NEXT: [[TMP156:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 1 -// CHECK3-NEXT: store i32 1, ptr [[TMP156]], align 4 -// CHECK3-NEXT: [[TMP157:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 2 -// CHECK3-NEXT: store ptr [[TMP153]], ptr [[TMP157]], align 4 -// CHECK3-NEXT: [[TMP158:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 3 -// CHECK3-NEXT: store ptr [[TMP154]], ptr [[TMP158]], align 4 -// CHECK3-NEXT: [[TMP159:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 4 -// CHECK3-NEXT: store ptr @.offload_sizes.7, ptr [[TMP159]], align 4 -// CHECK3-NEXT: [[TMP160:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 5 -// CHECK3-NEXT: store ptr @.offload_maptypes.8, ptr [[TMP160]], align 4 -// CHECK3-NEXT: [[TMP161:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 6 -// CHECK3-NEXT: store ptr null, ptr [[TMP161]], align 4 -// CHECK3-NEXT: [[TMP162:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 7 -// CHECK3-NEXT: store ptr null, ptr [[TMP162]], align 4 -// CHECK3-NEXT: [[TMP163:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 8 -// CHECK3-NEXT: store i64 0, ptr [[TMP163]], align 8 -// CHECK3-NEXT: [[TMP164:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 9 -// CHECK3-NEXT: store i64 0, ptr [[TMP164]], align 8 -// CHECK3-NEXT: [[TMP165:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 10 -// CHECK3-NEXT: store [3 x i32] zeroinitializer, ptr [[TMP165]], align 4 -// CHECK3-NEXT: [[TMP166:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 11 -// CHECK3-NEXT: store [3 x i32] zeroinitializer, ptr [[TMP166]], align 4 -// CHECK3-NEXT: [[TMP167:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 12 -// CHECK3-NEXT: store i32 0, ptr [[TMP167]], align 4 -// CHECK3-NEXT: [[TMP168:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB1]], i64 -1, i32 0, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l154.region_id, ptr [[KERNEL_ARGS30]]) -// CHECK3-NEXT: [[TMP169:%.*]] = icmp ne i32 [[TMP168]], 0 -// CHECK3-NEXT: br i1 [[TMP169]], label [[OMP_OFFLOAD_FAILED31:%.*]], label [[OMP_OFFLOAD_CONT32:%.*]] +// CHECK3-NEXT: [[TMP141:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_BASEPTRS27]], i32 0, i32 4 +// CHECK3-NEXT: store ptr [[C]], ptr [[TMP141]], align 4 +// CHECK3-NEXT: [[TMP142:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS28]], i32 0, i32 4 +// CHECK3-NEXT: store ptr [[C]], ptr [[TMP142]], align 4 +// CHECK3-NEXT: [[TMP143:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_MAPPERS29]], i32 0, i32 4 +// CHECK3-NEXT: store ptr null, ptr [[TMP143]], align 4 +// CHECK3-NEXT: [[TMP144:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_BASEPTRS27]], i32 0, i32 5 +// CHECK3-NEXT: store i32 5, ptr [[TMP144]], align 4 +// CHECK3-NEXT: [[TMP145:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS28]], i32 0, i32 5 +// CHECK3-NEXT: store i32 5, ptr [[TMP145]], align 4 +// CHECK3-NEXT: [[TMP146:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_MAPPERS29]], i32 0, i32 5 +// CHECK3-NEXT: store ptr null, ptr [[TMP146]], align 4 +// CHECK3-NEXT: [[TMP147:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_BASEPTRS27]], i32 0, i32 6 +// CHECK3-NEXT: store i32 [[TMP3]], ptr [[TMP147]], align 4 +// CHECK3-NEXT: [[TMP148:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS28]], i32 0, i32 6 +// CHECK3-NEXT: store i32 [[TMP3]], ptr [[TMP148]], align 4 +// CHECK3-NEXT: [[TMP149:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_MAPPERS29]], i32 0, i32 6 +// CHECK3-NEXT: store ptr null, ptr [[TMP149]], align 4 +// CHECK3-NEXT: [[TMP150:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_BASEPTRS27]], i32 0, i32 7 +// CHECK3-NEXT: store ptr [[VLA1]], ptr [[TMP150]], align 4 +// CHECK3-NEXT: [[TMP151:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS28]], i32 0, i32 7 +// CHECK3-NEXT: store ptr [[VLA1]], ptr [[TMP151]], align 4 +// CHECK3-NEXT: [[TMP152:%.*]] = getelementptr inbounds [9 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 7 +// CHECK3-NEXT: store i64 [[TMP127]], ptr [[TMP152]], align 4 +// CHECK3-NEXT: [[TMP153:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_MAPPERS29]], i32 0, i32 7 +// CHECK3-NEXT: store ptr null, ptr [[TMP153]], align 4 +// CHECK3-NEXT: [[TMP154:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_BASEPTRS27]], i32 0, i32 8 +// CHECK3-NEXT: store ptr [[D]], ptr [[TMP154]], align 4 +// CHECK3-NEXT: [[TMP155:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS28]], i32 0, i32 8 +// CHECK3-NEXT: store ptr [[D]], ptr [[TMP155]], align 4 +// CHECK3-NEXT: [[TMP156:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_MAPPERS29]], i32 0, i32 8 +// CHECK3-NEXT: store ptr null, ptr [[TMP156]], align 4 +// CHECK3-NEXT: [[TMP157:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_BASEPTRS27]], i32 0, i32 0 +// CHECK3-NEXT: [[TMP158:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS28]], i32 0, i32 0 +// CHECK3-NEXT: [[TMP159:%.*]] = getelementptr inbounds [9 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0 +// CHECK3-NEXT: [[TMP160:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 0 +// CHECK3-NEXT: store i32 2, ptr [[TMP160]], align 4 +// CHECK3-NEXT: [[TMP161:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 1 +// CHECK3-NEXT: store i32 9, ptr [[TMP161]], align 4 +// CHECK3-NEXT: [[TMP162:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 2 +// CHECK3-NEXT: store ptr [[TMP157]], ptr [[TMP162]], align 4 +// CHECK3-NEXT: [[TMP163:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 3 +// CHECK3-NEXT: store ptr [[TMP158]], ptr [[TMP163]], align 4 +// CHECK3-NEXT: [[TMP164:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 4 +// CHECK3-NEXT: store ptr [[TMP159]], ptr [[TMP164]], align 4 +// CHECK3-NEXT: [[TMP165:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 5 +// CHECK3-NEXT: store ptr @.offload_maptypes.8, ptr [[TMP165]], align 4 +// CHECK3-NEXT: [[TMP166:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 6 +// CHECK3-NEXT: store ptr null, ptr [[TMP166]], align 4 +// CHECK3-NEXT: [[TMP167:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 7 +// CHECK3-NEXT: store ptr null, ptr [[TMP167]], align 4 +// CHECK3-NEXT: [[TMP168:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 8 +// CHECK3-NEXT: store i64 0, ptr [[TMP168]], align 8 +// CHECK3-NEXT: [[TMP169:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 9 +// CHECK3-NEXT: store i64 0, ptr [[TMP169]], align 8 +// CHECK3-NEXT: [[TMP170:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 10 +// CHECK3-NEXT: store [3 x i32] zeroinitializer, ptr [[TMP170]], align 4 +// CHECK3-NEXT: [[TMP171:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 11 +// CHECK3-NEXT: store [3 x i32] zeroinitializer, ptr [[TMP171]], align 4 +// CHECK3-NEXT: [[TMP172:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 12 +// CHECK3-NEXT: store i32 0, ptr [[TMP172]], align 4 +// CHECK3-NEXT: [[TMP173:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB1]], i64 -1, i32 0, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l148.region_id, ptr [[KERNEL_ARGS30]]) +// CHECK3-NEXT: [[TMP174:%.*]] = icmp ne i32 [[TMP173]], 0 +// CHECK3-NEXT: br i1 [[TMP174]], label [[OMP_OFFLOAD_FAILED31:%.*]], label [[OMP_OFFLOAD_CONT32:%.*]] // CHECK3: omp_offload.failed31: -// CHECK3-NEXT: call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l154(i32 [[TMP149]]) #[[ATTR3]] +// CHECK3-NEXT: call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l148(i32 [[TMP121]], ptr [[B]], i32 [[TMP1]], ptr [[VLA]], ptr [[C]], i32 5, i32 [[TMP3]], ptr [[VLA1]], ptr [[D]]) #[[ATTR3]] // CHECK3-NEXT: br label [[OMP_OFFLOAD_CONT32]] // CHECK3: omp_offload.cont32: -// CHECK3-NEXT: [[TMP170:%.*]] = load i32, ptr [[NN]], align 4 -// CHECK3-NEXT: store i32 [[TMP170]], ptr [[NN_CASTED33]], align 4 -// CHECK3-NEXT: [[TMP171:%.*]] = load i32, ptr [[NN_CASTED33]], align 4 -// CHECK3-NEXT: [[TMP172:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS34]], i32 0, i32 0 -// CHECK3-NEXT: store i32 [[TMP171]], ptr [[TMP172]], align 4 -// CHECK3-NEXT: [[TMP173:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS35]], i32 0, i32 0 -// CHECK3-NEXT: store i32 [[TMP171]], ptr [[TMP173]], align 4 -// CHECK3-NEXT: [[TMP174:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_MAPPERS36]], i32 0, i32 0 -// CHECK3-NEXT: store ptr null, ptr [[TMP174]], align 4 -// CHECK3-NEXT: [[TMP175:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS34]], i32 0, i32 0 -// CHECK3-NEXT: [[TMP176:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS35]], i32 0, i32 0 -// CHECK3-NEXT: [[TMP177:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS37]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP177]], align 4 -// CHECK3-NEXT: [[TMP178:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS37]], i32 0, i32 1 -// CHECK3-NEXT: store i32 1, ptr [[TMP178]], align 4 -// CHECK3-NEXT: [[TMP179:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS37]], i32 0, i32 2 -// CHECK3-NEXT: store ptr [[TMP175]], ptr [[TMP179]], align 4 -// CHECK3-NEXT: [[TMP180:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS37]], i32 0, i32 3 -// CHECK3-NEXT: store ptr [[TMP176]], ptr [[TMP180]], align 4 -// CHECK3-NEXT: [[TMP181:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS37]], i32 0, i32 4 -// CHECK3-NEXT: store ptr @.offload_sizes.9, ptr [[TMP181]], align 4 -// CHECK3-NEXT: [[TMP182:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS37]], i32 0, i32 5 -// CHECK3-NEXT: store ptr @.offload_maptypes.10, ptr [[TMP182]], align 4 -// CHECK3-NEXT: [[TMP183:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS37]], i32 0, i32 6 -// CHECK3-NEXT: store ptr null, ptr [[TMP183]], align 4 -// CHECK3-NEXT: [[TMP184:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS37]], i32 0, i32 7 -// CHECK3-NEXT: store ptr null, ptr [[TMP184]], align 4 -// CHECK3-NEXT: [[TMP185:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS37]], i32 0, i32 8 -// CHECK3-NEXT: store i64 0, ptr [[TMP185]], align 8 -// CHECK3-NEXT: [[TMP186:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS37]], i32 0, i32 9 -// CHECK3-NEXT: store i64 0, ptr [[TMP186]], align 8 -// CHECK3-NEXT: [[TMP187:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS37]], i32 0, i32 10 -// CHECK3-NEXT: store [3 x i32] zeroinitializer, ptr [[TMP187]], align 4 -// CHECK3-NEXT: [[TMP188:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS37]], i32 0, i32 11 -// CHECK3-NEXT: store [3 x i32] zeroinitializer, ptr [[TMP188]], align 4 -// CHECK3-NEXT: [[TMP189:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS37]], i32 0, i32 12 -// CHECK3-NEXT: store i32 0, ptr [[TMP189]], align 4 -// CHECK3-NEXT: [[TMP190:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB1]], i64 -1, i32 0, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l157.region_id, ptr [[KERNEL_ARGS37]]) -// CHECK3-NEXT: [[TMP191:%.*]] = icmp ne i32 [[TMP190]], 0 -// CHECK3-NEXT: br i1 [[TMP191]], label [[OMP_OFFLOAD_FAILED38:%.*]], label [[OMP_OFFLOAD_CONT39:%.*]] -// CHECK3: omp_offload.failed38: -// CHECK3-NEXT: call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l157(i32 [[TMP171]]) #[[ATTR3]] -// CHECK3-NEXT: br label [[OMP_OFFLOAD_CONT39]] -// CHECK3: omp_offload.cont39: -// CHECK3-NEXT: [[TMP192:%.*]] = load i32, ptr [[A]], align 4 -// CHECK3-NEXT: [[TMP193:%.*]] = load ptr, ptr [[SAVED_STACK]], align 4 -// CHECK3-NEXT: call void @llvm.stackrestore.p0(ptr [[TMP193]]) -// CHECK3-NEXT: ret i32 [[TMP192]] +// CHECK3-NEXT: br label [[OMP_IF_END34:%.*]] +// CHECK3: omp_if.else33: +// CHECK3-NEXT: call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l148(i32 [[TMP121]], ptr [[B]], i32 [[TMP1]], ptr [[VLA]], ptr [[C]], i32 5, i32 [[TMP3]], ptr [[VLA1]], ptr [[D]]) #[[ATTR3]] +// CHECK3-NEXT: br label [[OMP_IF_END34]] +// CHECK3: omp_if.end34: +// CHECK3-NEXT: store i32 0, ptr [[NN]], align 4 +// CHECK3-NEXT: [[TMP175:%.*]] = load i32, ptr [[NN]], align 4 +// CHECK3-NEXT: store i32 [[TMP175]], ptr [[NN_CASTED]], align 4 +// CHECK3-NEXT: [[TMP176:%.*]] = load i32, ptr [[NN_CASTED]], align 4 +// CHECK3-NEXT: [[TMP177:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS35]], i32 0, i32 0 +// CHECK3-NEXT: store i32 [[TMP176]], ptr [[TMP177]], align 4 +// CHECK3-NEXT: [[TMP178:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS36]], i32 0, i32 0 +// CHECK3-NEXT: store i32 [[TMP176]], ptr [[TMP178]], align 4 +// CHECK3-NEXT: [[TMP179:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_MAPPERS37]], i32 0, i32 0 +// CHECK3-NEXT: store ptr null, ptr [[TMP179]], align 4 +// CHECK3-NEXT: [[TMP180:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS35]], i32 0, i32 0 +// CHECK3-NEXT: [[TMP181:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS36]], i32 0, i32 0 +// CHECK3-NEXT: [[TMP182:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS38]], i32 0, i32 0 +// CHECK3-NEXT: store i32 2, ptr [[TMP182]], align 4 +// CHECK3-NEXT: [[TMP183:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS38]], i32 0, i32 1 +// CHECK3-NEXT: store i32 1, ptr [[TMP183]], align 4 +// CHECK3-NEXT: [[TMP184:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS38]], i32 0, i32 2 +// CHECK3-NEXT: store ptr [[TMP180]], ptr [[TMP184]], align 4 +// CHECK3-NEXT: [[TMP185:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS38]], i32 0, i32 3 +// CHECK3-NEXT: store ptr [[TMP181]], ptr [[TMP185]], align 4 +// CHECK3-NEXT: [[TMP186:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS38]], i32 0, i32 4 +// CHECK3-NEXT: store ptr @.offload_sizes.9, ptr [[TMP186]], align 4 +// CHECK3-NEXT: [[TMP187:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS38]], i32 0, i32 5 +// CHECK3-NEXT: store ptr @.offload_maptypes.10, ptr [[TMP187]], align 4 +// CHECK3-NEXT: [[TMP188:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS38]], i32 0, i32 6 +// CHECK3-NEXT: store ptr null, ptr [[TMP188]], align 4 +// CHECK3-NEXT: [[TMP189:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS38]], i32 0, i32 7 +// CHECK3-NEXT: store ptr null, ptr [[TMP189]], align 4 +// CHECK3-NEXT: [[TMP190:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS38]], i32 0, i32 8 +// CHECK3-NEXT: store i64 0, ptr [[TMP190]], align 8 +// CHECK3-NEXT: [[TMP191:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS38]], i32 0, i32 9 +// CHECK3-NEXT: store i64 0, ptr [[TMP191]], align 8 +// CHECK3-NEXT: [[TMP192:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS38]], i32 0, i32 10 +// CHECK3-NEXT: store [3 x i32] zeroinitializer, ptr [[TMP192]], align 4 +// CHECK3-NEXT: [[TMP193:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS38]], i32 0, i32 11 +// CHECK3-NEXT: store [3 x i32] zeroinitializer, ptr [[TMP193]], align 4 +// CHECK3-NEXT: [[TMP194:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS38]], i32 0, i32 12 +// CHECK3-NEXT: store i32 0, ptr [[TMP194]], align 4 +// CHECK3-NEXT: [[TMP195:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB1]], i64 -1, i32 0, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l160.region_id, ptr [[KERNEL_ARGS38]]) +// CHECK3-NEXT: [[TMP196:%.*]] = icmp ne i32 [[TMP195]], 0 +// CHECK3-NEXT: br i1 [[TMP196]], label [[OMP_OFFLOAD_FAILED39:%.*]], label [[OMP_OFFLOAD_CONT40:%.*]] +// CHECK3: omp_offload.failed39: +// CHECK3-NEXT: call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l160(i32 [[TMP176]]) #[[ATTR3]] +// CHECK3-NEXT: br label [[OMP_OFFLOAD_CONT40]] +// CHECK3: omp_offload.cont40: +// CHECK3-NEXT: [[TMP197:%.*]] = load i32, ptr [[NN]], align 4 +// CHECK3-NEXT: store i32 [[TMP197]], ptr [[NN_CASTED41]], align 4 +// CHECK3-NEXT: [[TMP198:%.*]] = load i32, ptr [[NN_CASTED41]], align 4 +// CHECK3-NEXT: [[TMP199:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS42]], i32 0, i32 0 +// CHECK3-NEXT: store i32 [[TMP198]], ptr [[TMP199]], align 4 +// CHECK3-NEXT: [[TMP200:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS43]], i32 0, i32 0 +// CHECK3-NEXT: store i32 [[TMP198]], ptr [[TMP200]], align 4 +// CHECK3-NEXT: [[TMP201:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_MAPPERS44]], i32 0, i32 0 +// CHECK3-NEXT: store ptr null, ptr [[TMP201]], align 4 +// CHECK3-NEXT: [[TMP202:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS42]], i32 0, i32 0 +// CHECK3-NEXT: [[TMP203:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS43]], i32 0, i32 0 +// CHECK3-NEXT: [[TMP204:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS45]], i32 0, i32 0 +// CHECK3-NEXT: store i32 2, ptr [[TMP204]], align 4 +// CHECK3-NEXT: [[TMP205:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS45]], i32 0, i32 1 +// CHECK3-NEXT: store i32 1, ptr [[TMP205]], align 4 +// CHECK3-NEXT: [[TMP206:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS45]], i32 0, i32 2 +// CHECK3-NEXT: store ptr [[TMP202]], ptr [[TMP206]], align 4 +// CHECK3-NEXT: [[TMP207:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS45]], i32 0, i32 3 +// CHECK3-NEXT: store ptr [[TMP203]], ptr [[TMP207]], align 4 +// CHECK3-NEXT: [[TMP208:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS45]], i32 0, i32 4 +// CHECK3-NEXT: store ptr @.offload_sizes.11, ptr [[TMP208]], align 4 +// CHECK3-NEXT: [[TMP209:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS45]], i32 0, i32 5 +// CHECK3-NEXT: store ptr @.offload_maptypes.12, ptr [[TMP209]], align 4 +// CHECK3-NEXT: [[TMP210:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS45]], i32 0, i32 6 +// CHECK3-NEXT: store ptr null, ptr [[TMP210]], align 4 +// CHECK3-NEXT: [[TMP211:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS45]], i32 0, i32 7 +// CHECK3-NEXT: store ptr null, ptr [[TMP211]], align 4 +// CHECK3-NEXT: [[TMP212:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS45]], i32 0, i32 8 +// CHECK3-NEXT: store i64 0, ptr [[TMP212]], align 8 +// CHECK3-NEXT: [[TMP213:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS45]], i32 0, i32 9 +// CHECK3-NEXT: store i64 0, ptr [[TMP213]], align 8 +// CHECK3-NEXT: [[TMP214:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS45]], i32 0, i32 10 +// CHECK3-NEXT: store [3 x i32] zeroinitializer, ptr [[TMP214]], align 4 +// CHECK3-NEXT: [[TMP215:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS45]], i32 0, i32 11 +// CHECK3-NEXT: store [3 x i32] zeroinitializer, ptr [[TMP215]], align 4 +// CHECK3-NEXT: [[TMP216:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS45]], i32 0, i32 12 +// CHECK3-NEXT: store i32 0, ptr [[TMP216]], align 4 +// CHECK3-NEXT: [[TMP217:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB1]], i64 -1, i32 0, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l163.region_id, ptr [[KERNEL_ARGS45]]) +// CHECK3-NEXT: [[TMP218:%.*]] = icmp ne i32 [[TMP217]], 0 +// CHECK3-NEXT: br i1 [[TMP218]], label [[OMP_OFFLOAD_FAILED46:%.*]], label [[OMP_OFFLOAD_CONT47:%.*]] +// CHECK3: omp_offload.failed46: +// CHECK3-NEXT: call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l163(i32 [[TMP198]]) #[[ATTR3]] +// CHECK3-NEXT: br label [[OMP_OFFLOAD_CONT47]] +// CHECK3: omp_offload.cont47: +// CHECK3-NEXT: [[TMP219:%.*]] = load i32, ptr [[A]], align 4 +// CHECK3-NEXT: [[TMP220:%.*]] = load ptr, ptr [[SAVED_STACK]], align 4 +// CHECK3-NEXT: call void @llvm.stackrestore.p0(ptr [[TMP220]]) +// CHECK3-NEXT: ret i32 [[TMP219]] // // // CHECK3-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l101 @@ -2324,68 +2489,68 @@ int bar(int n){ // CHECK3-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP4]], i32 0, i32 0 // CHECK3-NEXT: [[TMP7:%.*]] = load ptr, ptr [[TMP6]], align 4 // CHECK3-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T_WITH_PRIVATES]], ptr [[TMP3]], i32 0, i32 1 -// CHECK3-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META16:![0-9]+]]) -// CHECK3-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META19:![0-9]+]]) -// CHECK3-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META21:![0-9]+]]) -// CHECK3-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META23:![0-9]+]]) -// CHECK3-NEXT: store i32 [[TMP2]], ptr [[DOTGLOBAL_TID__ADDR_I]], align 4, !noalias !25 -// CHECK3-NEXT: store ptr [[TMP5]], ptr [[DOTPART_ID__ADDR_I]], align 4, !noalias !25 -// CHECK3-NEXT: store ptr [[TMP8]], ptr [[DOTPRIVATES__ADDR_I]], align 4, !noalias !25 -// CHECK3-NEXT: store ptr @.omp_task_privates_map., ptr [[DOTCOPY_FN__ADDR_I]], align 4, !noalias !25 -// CHECK3-NEXT: store ptr [[TMP3]], ptr [[DOTTASK_T__ADDR_I]], align 4, !noalias !25 -// CHECK3-NEXT: store ptr [[TMP7]], ptr [[__CONTEXT_ADDR_I]], align 4, !noalias !25 -// CHECK3-NEXT: [[TMP9:%.*]] = load ptr, ptr [[__CONTEXT_ADDR_I]], align 4, !noalias !25 -// CHECK3-NEXT: [[TMP10:%.*]] = load ptr, ptr [[DOTCOPY_FN__ADDR_I]], align 4, !noalias !25 -// CHECK3-NEXT: [[TMP11:%.*]] = load ptr, ptr [[DOTPRIVATES__ADDR_I]], align 4, !noalias !25 +// CHECK3-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META17:![0-9]+]]) +// CHECK3-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META20:![0-9]+]]) +// CHECK3-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META22:![0-9]+]]) +// CHECK3-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META24:![0-9]+]]) +// CHECK3-NEXT: store i32 [[TMP2]], ptr [[DOTGLOBAL_TID__ADDR_I]], align 4, !noalias !26 +// CHECK3-NEXT: store ptr [[TMP5]], ptr [[DOTPART_ID__ADDR_I]], align 4, !noalias !26 +// CHECK3-NEXT: store ptr [[TMP8]], ptr [[DOTPRIVATES__ADDR_I]], align 4, !noalias !26 +// CHECK3-NEXT: store ptr @.omp_task_privates_map., ptr [[DOTCOPY_FN__ADDR_I]], align 4, !noalias !26 +// CHECK3-NEXT: store ptr [[TMP3]], ptr [[DOTTASK_T__ADDR_I]], align 4, !noalias !26 +// CHECK3-NEXT: store ptr [[TMP7]], ptr [[__CONTEXT_ADDR_I]], align 4, !noalias !26 +// CHECK3-NEXT: [[TMP9:%.*]] = load ptr, ptr [[__CONTEXT_ADDR_I]], align 4, !noalias !26 +// CHECK3-NEXT: [[TMP10:%.*]] = load ptr, ptr [[DOTCOPY_FN__ADDR_I]], align 4, !noalias !26 +// CHECK3-NEXT: [[TMP11:%.*]] = load ptr, ptr [[DOTPRIVATES__ADDR_I]], align 4, !noalias !26 // CHECK3-NEXT: call void [[TMP10]](ptr [[TMP11]], ptr [[DOTFIRSTPRIV_PTR_ADDR_I]], ptr [[DOTFIRSTPRIV_PTR_ADDR1_I]], ptr [[DOTFIRSTPRIV_PTR_ADDR2_I]], ptr [[DOTFIRSTPRIV_PTR_ADDR3_I]]) #[[ATTR3]] -// CHECK3-NEXT: [[TMP12:%.*]] = load ptr, ptr [[DOTFIRSTPRIV_PTR_ADDR_I]], align 4, !noalias !25 -// CHECK3-NEXT: [[TMP13:%.*]] = load ptr, ptr [[DOTFIRSTPRIV_PTR_ADDR1_I]], align 4, !noalias !25 -// CHECK3-NEXT: [[TMP14:%.*]] = load ptr, ptr [[DOTFIRSTPRIV_PTR_ADDR2_I]], align 4, !noalias !25 -// CHECK3-NEXT: [[TMP15:%.*]] = load ptr, ptr [[DOTFIRSTPRIV_PTR_ADDR3_I]], align 4, !noalias !25 +// CHECK3-NEXT: [[TMP12:%.*]] = load ptr, ptr [[DOTFIRSTPRIV_PTR_ADDR_I]], align 4, !noalias !26 +// CHECK3-NEXT: [[TMP13:%.*]] = load ptr, ptr [[DOTFIRSTPRIV_PTR_ADDR1_I]], align 4, !noalias !26 +// CHECK3-NEXT: [[TMP14:%.*]] = load ptr, ptr [[DOTFIRSTPRIV_PTR_ADDR2_I]], align 4, !noalias !26 +// CHECK3-NEXT: [[TMP15:%.*]] = load ptr, ptr [[DOTFIRSTPRIV_PTR_ADDR3_I]], align 4, !noalias !26 // CHECK3-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT_ANON:%.*]], ptr [[TMP9]], i32 0, i32 1 // CHECK3-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT_ANON]], ptr [[TMP9]], i32 0, i32 2 // CHECK3-NEXT: [[TMP18:%.*]] = load i32, ptr [[TMP16]], align 4 // CHECK3-NEXT: [[TMP19:%.*]] = load i32, ptr [[TMP17]], align 4 // CHECK3-NEXT: [[TMP20:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP18]], 0 // CHECK3-NEXT: [[TMP21:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP19]], 0 -// CHECK3-NEXT: store i32 2, ptr [[KERNEL_ARGS_I]], align 4, !noalias !25 +// CHECK3-NEXT: store i32 2, ptr [[KERNEL_ARGS_I]], align 4, !noalias !26 // CHECK3-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS_I]], i32 0, i32 1 -// CHECK3-NEXT: store i32 3, ptr [[TMP22]], align 4, !noalias !25 +// CHECK3-NEXT: store i32 3, ptr [[TMP22]], align 4, !noalias !26 // CHECK3-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS_I]], i32 0, i32 2 -// CHECK3-NEXT: store ptr [[TMP13]], ptr [[TMP23]], align 4, !noalias !25 +// CHECK3-NEXT: store ptr [[TMP13]], ptr [[TMP23]], align 4, !noalias !26 // CHECK3-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS_I]], i32 0, i32 3 -// CHECK3-NEXT: store ptr [[TMP14]], ptr [[TMP24]], align 4, !noalias !25 +// CHECK3-NEXT: store ptr [[TMP14]], ptr [[TMP24]], align 4, !noalias !26 // CHECK3-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS_I]], i32 0, i32 4 -// CHECK3-NEXT: store ptr [[TMP15]], ptr [[TMP25]], align 4, !noalias !25 +// CHECK3-NEXT: store ptr [[TMP15]], ptr [[TMP25]], align 4, !noalias !26 // CHECK3-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS_I]], i32 0, i32 5 -// CHECK3-NEXT: store ptr @.offload_maptypes, ptr [[TMP26]], align 4, !noalias !25 +// CHECK3-NEXT: store ptr @.offload_maptypes, ptr [[TMP26]], align 4, !noalias !26 // CHECK3-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS_I]], i32 0, i32 6 -// CHECK3-NEXT: store ptr null, ptr [[TMP27]], align 4, !noalias !25 +// CHECK3-NEXT: store ptr null, ptr [[TMP27]], align 4, !noalias !26 // CHECK3-NEXT: [[TMP28:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS_I]], i32 0, i32 7 -// CHECK3-NEXT: store ptr null, ptr [[TMP28]], align 4, !noalias !25 +// CHECK3-NEXT: store ptr null, ptr [[TMP28]], align 4, !noalias !26 // CHECK3-NEXT: [[TMP29:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS_I]], i32 0, i32 8 -// CHECK3-NEXT: store i64 0, ptr [[TMP29]], align 8, !noalias !25 +// CHECK3-NEXT: store i64 0, ptr [[TMP29]], align 8, !noalias !26 // CHECK3-NEXT: [[TMP30:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS_I]], i32 0, i32 9 -// CHECK3-NEXT: store i64 1, ptr [[TMP30]], align 8, !noalias !25 +// CHECK3-NEXT: store i64 1, ptr [[TMP30]], align 8, !noalias !26 // CHECK3-NEXT: [[TMP31:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS_I]], i32 0, i32 10 -// CHECK3-NEXT: store [3 x i32] [[TMP20]], ptr [[TMP31]], align 4, !noalias !25 +// CHECK3-NEXT: store [3 x i32] [[TMP20]], ptr [[TMP31]], align 4, !noalias !26 // CHECK3-NEXT: [[TMP32:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS_I]], i32 0, i32 11 -// CHECK3-NEXT: store [3 x i32] [[TMP21]], ptr [[TMP32]], align 4, !noalias !25 +// CHECK3-NEXT: store [3 x i32] [[TMP21]], ptr [[TMP32]], align 4, !noalias !26 // CHECK3-NEXT: [[TMP33:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS_I]], i32 0, i32 12 -// CHECK3-NEXT: store i32 0, ptr [[TMP33]], align 4, !noalias !25 +// CHECK3-NEXT: store i32 0, ptr [[TMP33]], align 4, !noalias !26 // CHECK3-NEXT: [[TMP34:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB1]], i64 -1, i32 [[TMP18]], i32 [[TMP19]], ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l101.region_id, ptr [[KERNEL_ARGS_I]]) // CHECK3-NEXT: [[TMP35:%.*]] = icmp ne i32 [[TMP34]], 0 // CHECK3-NEXT: br i1 [[TMP35]], label [[OMP_OFFLOAD_FAILED_I:%.*]], label [[DOTOMP_OUTLINED__EXIT:%.*]] // CHECK3: omp_offload.failed.i: // CHECK3-NEXT: [[TMP36:%.*]] = load i16, ptr [[TMP12]], align 2 -// CHECK3-NEXT: store i16 [[TMP36]], ptr [[AA_CASTED_I]], align 2, !noalias !25 -// CHECK3-NEXT: [[TMP37:%.*]] = load i32, ptr [[AA_CASTED_I]], align 4, !noalias !25 +// CHECK3-NEXT: store i16 [[TMP36]], ptr [[AA_CASTED_I]], align 2, !noalias !26 +// CHECK3-NEXT: [[TMP37:%.*]] = load i32, ptr [[AA_CASTED_I]], align 4, !noalias !26 // CHECK3-NEXT: [[TMP38:%.*]] = load i32, ptr [[TMP16]], align 4 -// CHECK3-NEXT: store i32 [[TMP38]], ptr [[DOTCAPTURE_EXPR__CASTED_I]], align 4, !noalias !25 -// CHECK3-NEXT: [[TMP39:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR__CASTED_I]], align 4, !noalias !25 +// CHECK3-NEXT: store i32 [[TMP38]], ptr [[DOTCAPTURE_EXPR__CASTED_I]], align 4, !noalias !26 +// CHECK3-NEXT: [[TMP39:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR__CASTED_I]], align 4, !noalias !26 // CHECK3-NEXT: [[TMP40:%.*]] = load i32, ptr [[TMP17]], align 4 -// CHECK3-NEXT: store i32 [[TMP40]], ptr [[DOTCAPTURE_EXPR__CASTED4_I]], align 4, !noalias !25 -// CHECK3-NEXT: [[TMP41:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR__CASTED4_I]], align 4, !noalias !25 +// CHECK3-NEXT: store i32 [[TMP40]], ptr [[DOTCAPTURE_EXPR__CASTED4_I]], align 4, !noalias !26 +// CHECK3-NEXT: [[TMP41:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR__CASTED4_I]], align 4, !noalias !26 // CHECK3-NEXT: call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l101(i32 [[TMP37]], i32 [[TMP39]], i32 [[TMP41]]) #[[ATTR3]] // CHECK3-NEXT: br label [[DOTOMP_OUTLINED__EXIT]] // CHECK3: .omp_outlined..exit: @@ -2491,7 +2656,48 @@ int bar(int n){ // CHECK3-NEXT: ret void // // -// CHECK3-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l142 +// CHECK3-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l124 +// CHECK3-SAME: (i32 noundef [[A:%.*]], i32 noundef [[AA:%.*]]) #[[ATTR2]] { +// CHECK3-NEXT: entry: +// CHECK3-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 +// CHECK3-NEXT: [[AA_ADDR:%.*]] = alloca i32, align 4 +// CHECK3-NEXT: [[A_CASTED:%.*]] = alloca i32, align 4 +// CHECK3-NEXT: [[AA_CASTED:%.*]] = alloca i32, align 4 +// CHECK3-NEXT: store i32 [[A]], ptr [[A_ADDR]], align 4 +// CHECK3-NEXT: store i32 [[AA]], ptr [[AA_ADDR]], align 4 +// CHECK3-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4 +// CHECK3-NEXT: store i32 [[TMP0]], ptr [[A_CASTED]], align 4 +// CHECK3-NEXT: [[TMP1:%.*]] = load i32, ptr [[A_CASTED]], align 4 +// CHECK3-NEXT: [[TMP2:%.*]] = load i16, ptr [[AA_ADDR]], align 2 +// CHECK3-NEXT: store i16 [[TMP2]], ptr [[AA_CASTED]], align 2 +// CHECK3-NEXT: [[TMP3:%.*]] = load i32, ptr [[AA_CASTED]], align 4 +// CHECK3-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB1]], i32 2, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l124.omp_outlined, i32 [[TMP1]], i32 [[TMP3]]) +// CHECK3-NEXT: ret void +// +// +// CHECK3-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l124.omp_outlined +// CHECK3-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], i32 noundef [[A:%.*]], i32 noundef [[AA:%.*]]) #[[ATTR2]] { +// CHECK3-NEXT: entry: +// CHECK3-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 4 +// CHECK3-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca ptr, align 4 +// CHECK3-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 +// CHECK3-NEXT: [[AA_ADDR:%.*]] = alloca i32, align 4 +// CHECK3-NEXT: store ptr [[DOTGLOBAL_TID_]], ptr [[DOTGLOBAL_TID__ADDR]], align 4 +// CHECK3-NEXT: store ptr [[DOTBOUND_TID_]], ptr [[DOTBOUND_TID__ADDR]], align 4 +// CHECK3-NEXT: store i32 [[A]], ptr [[A_ADDR]], align 4 +// CHECK3-NEXT: store i32 [[AA]], ptr [[AA_ADDR]], align 4 +// CHECK3-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4 +// CHECK3-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP0]], 1 +// CHECK3-NEXT: store i32 [[ADD]], ptr [[A_ADDR]], align 4 +// CHECK3-NEXT: [[TMP1:%.*]] = load i16, ptr [[AA_ADDR]], align 2 +// CHECK3-NEXT: [[CONV:%.*]] = sext i16 [[TMP1]] to i32 +// CHECK3-NEXT: [[ADD1:%.*]] = add nsw i32 [[CONV]], 1 +// CHECK3-NEXT: [[CONV2:%.*]] = trunc i32 [[ADD1]] to i16 +// CHECK3-NEXT: store i16 [[CONV2]], ptr [[AA_ADDR]], align 2 +// CHECK3-NEXT: ret void +// +// +// CHECK3-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l148 // CHECK3-SAME: (i32 noundef [[A:%.*]], ptr noundef nonnull align 4 dereferenceable(40) [[B:%.*]], i32 noundef [[VLA:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[BN:%.*]], ptr noundef nonnull align 4 dereferenceable(400) [[C:%.*]], i32 noundef [[VLA1:%.*]], i32 noundef [[VLA3:%.*]], ptr noundef nonnull align 4 dereferenceable(8) [[CN:%.*]], ptr noundef nonnull align 4 dereferenceable(12) [[D:%.*]]) #[[ATTR2]] { // CHECK3-NEXT: entry: // CHECK3-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 @@ -2524,11 +2730,11 @@ int bar(int n){ // CHECK3-NEXT: [[TMP8:%.*]] = load i32, ptr [[A_ADDR]], align 4 // CHECK3-NEXT: store i32 [[TMP8]], ptr [[A_CASTED]], align 4 // CHECK3-NEXT: [[TMP9:%.*]] = load i32, ptr [[A_CASTED]], align 4 -// CHECK3-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB1]], i32 9, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l142.omp_outlined, i32 [[TMP9]], ptr [[TMP0]], i32 [[TMP1]], ptr [[TMP2]], ptr [[TMP3]], i32 [[TMP4]], i32 [[TMP5]], ptr [[TMP6]], ptr [[TMP7]]) +// CHECK3-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB1]], i32 9, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l148.omp_outlined, i32 [[TMP9]], ptr [[TMP0]], i32 [[TMP1]], ptr [[TMP2]], ptr [[TMP3]], i32 [[TMP4]], i32 [[TMP5]], ptr [[TMP6]], ptr [[TMP7]]) // CHECK3-NEXT: ret void // // -// CHECK3-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l142.omp_outlined +// CHECK3-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l148.omp_outlined // CHECK3-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], i32 noundef [[A:%.*]], ptr noundef nonnull align 4 dereferenceable(40) [[B:%.*]], i32 noundef [[VLA:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[BN:%.*]], ptr noundef nonnull align 4 dereferenceable(400) [[C:%.*]], i32 noundef [[VLA1:%.*]], i32 noundef [[VLA3:%.*]], ptr noundef nonnull align 4 dereferenceable(8) [[CN:%.*]], ptr noundef nonnull align 4 dereferenceable(12) [[D:%.*]]) #[[ATTR2]] { // CHECK3-NEXT: entry: // CHECK3-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 4 @@ -2600,7 +2806,7 @@ int bar(int n){ // CHECK3-NEXT: ret void // // -// CHECK3-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l154 +// CHECK3-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l160 // CHECK3-SAME: (i32 noundef [[NN:%.*]]) #[[ATTR2]] { // CHECK3-NEXT: entry: // CHECK3-NEXT: [[NN_ADDR:%.*]] = alloca i32, align 4 @@ -2609,11 +2815,11 @@ int bar(int n){ // CHECK3-NEXT: [[TMP0:%.*]] = load i32, ptr [[NN_ADDR]], align 4 // CHECK3-NEXT: store i32 [[TMP0]], ptr [[NN_CASTED]], align 4 // CHECK3-NEXT: [[TMP1:%.*]] = load i32, ptr [[NN_CASTED]], align 4 -// CHECK3-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB1]], i32 1, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l154.omp_outlined, i32 [[TMP1]]) +// CHECK3-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB1]], i32 1, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l160.omp_outlined, i32 [[TMP1]]) // CHECK3-NEXT: ret void // // -// CHECK3-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l154.omp_outlined +// CHECK3-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l160.omp_outlined // CHECK3-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], i32 noundef [[NN:%.*]]) #[[ATTR2]] { // CHECK3-NEXT: entry: // CHECK3-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 4 @@ -2626,11 +2832,11 @@ int bar(int n){ // CHECK3-NEXT: [[TMP0:%.*]] = load i32, ptr [[NN_ADDR]], align 4 // CHECK3-NEXT: store i32 [[TMP0]], ptr [[NN_CASTED]], align 4 // CHECK3-NEXT: [[TMP1:%.*]] = load i32, ptr [[NN_CASTED]], align 4 -// CHECK3-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @[[GLOB1]], i32 1, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l154.omp_outlined.omp_outlined, i32 [[TMP1]]) +// CHECK3-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @[[GLOB1]], i32 1, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l160.omp_outlined.omp_outlined, i32 [[TMP1]]) // CHECK3-NEXT: ret void // // -// CHECK3-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l154.omp_outlined.omp_outlined +// CHECK3-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l160.omp_outlined.omp_outlined // CHECK3-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], i32 noundef [[NN:%.*]]) #[[ATTR2]] { // CHECK3-NEXT: entry: // CHECK3-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 4 @@ -2642,7 +2848,7 @@ int bar(int n){ // CHECK3-NEXT: ret void // // -// CHECK3-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l157 +// CHECK3-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l163 // CHECK3-SAME: (i32 noundef [[NN:%.*]]) #[[ATTR2]] { // CHECK3-NEXT: entry: // CHECK3-NEXT: [[NN_ADDR:%.*]] = alloca i32, align 4 @@ -2651,11 +2857,11 @@ int bar(int n){ // CHECK3-NEXT: [[TMP0:%.*]] = load i32, ptr [[NN_ADDR]], align 4 // CHECK3-NEXT: store i32 [[TMP0]], ptr [[NN_CASTED]], align 4 // CHECK3-NEXT: [[TMP1:%.*]] = load i32, ptr [[NN_CASTED]], align 4 -// CHECK3-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB1]], i32 1, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l157.omp_outlined, i32 [[TMP1]]) +// CHECK3-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB1]], i32 1, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l163.omp_outlined, i32 [[TMP1]]) // CHECK3-NEXT: ret void // // -// CHECK3-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l157.omp_outlined +// CHECK3-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l163.omp_outlined // CHECK3-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], i32 noundef [[NN:%.*]]) #[[ATTR2]] { // CHECK3-NEXT: entry: // CHECK3-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 4 @@ -2664,11 +2870,11 @@ int bar(int n){ // CHECK3-NEXT: store ptr [[DOTGLOBAL_TID_]], ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK3-NEXT: store ptr [[DOTBOUND_TID_]], ptr [[DOTBOUND_TID__ADDR]], align 4 // CHECK3-NEXT: store i32 [[NN]], ptr [[NN_ADDR]], align 4 -// CHECK3-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @[[GLOB1]], i32 1, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l157.omp_outlined.omp_outlined, ptr [[NN_ADDR]]) +// CHECK3-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @[[GLOB1]], i32 1, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l163.omp_outlined.omp_outlined, ptr [[NN_ADDR]]) // CHECK3-NEXT: ret void // // -// CHECK3-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l157.omp_outlined.omp_outlined +// CHECK3-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l163.omp_outlined.omp_outlined // CHECK3-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[NN:%.*]]) #[[ATTR2]] { // CHECK3-NEXT: entry: // CHECK3-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 4 @@ -2710,9 +2916,9 @@ int bar(int n){ // CHECK3-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 3 // CHECK3-NEXT: store ptr [[TMP5]], ptr [[TMP9]], align 4 // CHECK3-NEXT: [[TMP10:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 4 -// CHECK3-NEXT: store ptr @.offload_sizes.11, ptr [[TMP10]], align 4 +// CHECK3-NEXT: store ptr @.offload_sizes.13, ptr [[TMP10]], align 4 // CHECK3-NEXT: [[TMP11:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 5 -// CHECK3-NEXT: store ptr @.offload_maptypes.12, ptr [[TMP11]], align 4 +// CHECK3-NEXT: store ptr @.offload_maptypes.14, ptr [[TMP11]], align 4 // CHECK3-NEXT: [[TMP12:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 6 // CHECK3-NEXT: store ptr null, ptr [[TMP12]], align 4 // CHECK3-NEXT: [[TMP13:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 7 @@ -2727,27 +2933,27 @@ int bar(int n){ // CHECK3-NEXT: store [3 x i32] zeroinitializer, ptr [[TMP17]], align 4 // CHECK3-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 12 // CHECK3-NEXT: store i32 0, ptr [[TMP18]], align 4 -// CHECK3-NEXT: [[TMP19:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB1]], i64 -1, i32 0, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z6bazzzziPi_l182.region_id, ptr [[KERNEL_ARGS]]) +// CHECK3-NEXT: [[TMP19:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB1]], i64 -1, i32 0, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z6bazzzziPi_l188.region_id, ptr [[KERNEL_ARGS]]) // CHECK3-NEXT: [[TMP20:%.*]] = icmp ne i32 [[TMP19]], 0 // CHECK3-NEXT: br i1 [[TMP20]], label [[OMP_OFFLOAD_FAILED:%.*]], label [[OMP_OFFLOAD_CONT:%.*]] // CHECK3: omp_offload.failed: -// CHECK3-NEXT: call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z6bazzzziPi_l182(i32 [[TMP0]]) #[[ATTR3]] +// CHECK3-NEXT: call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z6bazzzziPi_l188(i32 [[TMP0]]) #[[ATTR3]] // CHECK3-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK3: omp_offload.cont: // CHECK3-NEXT: ret void // // -// CHECK3-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z6bazzzziPi_l182 +// CHECK3-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z6bazzzziPi_l188 // CHECK3-SAME: (i32 noundef [[VLA:%.*]]) #[[ATTR2]] { // CHECK3-NEXT: entry: // CHECK3-NEXT: [[VLA_ADDR:%.*]] = alloca i32, align 4 // CHECK3-NEXT: store i32 [[VLA]], ptr [[VLA_ADDR]], align 4 // CHECK3-NEXT: [[TMP0:%.*]] = load i32, ptr [[VLA_ADDR]], align 4 -// CHECK3-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB1]], i32 1, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z6bazzzziPi_l182.omp_outlined, i32 [[TMP0]]) +// CHECK3-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB1]], i32 1, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z6bazzzziPi_l188.omp_outlined, i32 [[TMP0]]) // CHECK3-NEXT: ret void // // -// CHECK3-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z6bazzzziPi_l182.omp_outlined +// CHECK3-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z6bazzzziPi_l188.omp_outlined // CHECK3-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], i32 noundef [[VLA:%.*]]) #[[ATTR2]] { // CHECK3-NEXT: entry: // CHECK3-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 4 @@ -2830,7 +3036,7 @@ int bar(int n){ // CHECK3-NEXT: [[TMP7:%.*]] = mul nuw i32 2, [[TMP1]] // CHECK3-NEXT: [[TMP8:%.*]] = mul nuw i32 [[TMP7]], 2 // CHECK3-NEXT: [[TMP9:%.*]] = sext i32 [[TMP8]] to i64 -// CHECK3-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[DOTOFFLOAD_SIZES]], ptr align 4 @.offload_sizes.13, i32 40, i1 false) +// CHECK3-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[DOTOFFLOAD_SIZES]], ptr align 4 @.offload_sizes.15, i32 40, i1 false) // CHECK3-NEXT: [[TMP10:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: store ptr [[THIS1]], ptr [[TMP10]], align 4 // CHECK3-NEXT: [[TMP11:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 @@ -2877,7 +3083,7 @@ int bar(int n){ // CHECK3-NEXT: [[TMP33:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 4 // CHECK3-NEXT: store ptr [[TMP28]], ptr [[TMP33]], align 4 // CHECK3-NEXT: [[TMP34:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 5 -// CHECK3-NEXT: store ptr @.offload_maptypes.14, ptr [[TMP34]], align 4 +// CHECK3-NEXT: store ptr @.offload_maptypes.16, ptr [[TMP34]], align 4 // CHECK3-NEXT: [[TMP35:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 6 // CHECK3-NEXT: store ptr null, ptr [[TMP35]], align 4 // CHECK3-NEXT: [[TMP36:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 7 @@ -2892,16 +3098,16 @@ int bar(int n){ // CHECK3-NEXT: store [3 x i32] zeroinitializer, ptr [[TMP40]], align 4 // CHECK3-NEXT: [[TMP41:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 12 // CHECK3-NEXT: store i32 0, ptr [[TMP41]], align 4 -// CHECK3-NEXT: [[TMP42:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB1]], i64 -1, i32 0, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN2S12r1Ei_l227.region_id, ptr [[KERNEL_ARGS]]) +// CHECK3-NEXT: [[TMP42:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB1]], i64 -1, i32 0, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN2S12r1Ei_l233.region_id, ptr [[KERNEL_ARGS]]) // CHECK3-NEXT: [[TMP43:%.*]] = icmp ne i32 [[TMP42]], 0 // CHECK3-NEXT: br i1 [[TMP43]], label [[OMP_OFFLOAD_FAILED:%.*]], label [[OMP_OFFLOAD_CONT:%.*]] // CHECK3: omp_offload.failed: -// CHECK3-NEXT: call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN2S12r1Ei_l227(ptr [[THIS1]], i32 [[TMP5]], i32 2, i32 [[TMP1]], ptr [[VLA]]) #[[ATTR3]] +// CHECK3-NEXT: call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN2S12r1Ei_l233(ptr [[THIS1]], i32 [[TMP5]], i32 2, i32 [[TMP1]], ptr [[VLA]]) #[[ATTR3]] // CHECK3-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK3: omp_offload.cont: // CHECK3-NEXT: br label [[OMP_IF_END:%.*]] // CHECK3: omp_if.else: -// CHECK3-NEXT: call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN2S12r1Ei_l227(ptr [[THIS1]], i32 [[TMP5]], i32 2, i32 [[TMP1]], ptr [[VLA]]) #[[ATTR3]] +// CHECK3-NEXT: call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN2S12r1Ei_l233(ptr [[THIS1]], i32 [[TMP5]], i32 2, i32 [[TMP1]], ptr [[VLA]]) #[[ATTR3]] // CHECK3-NEXT: br label [[OMP_IF_END]] // CHECK3: omp_if.end: // CHECK3-NEXT: [[TMP44:%.*]] = mul nsw i32 1, [[TMP1]] @@ -2983,9 +3189,9 @@ int bar(int n){ // CHECK3-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 3 // CHECK3-NEXT: store ptr [[TMP20]], ptr [[TMP24]], align 4 // CHECK3-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 4 -// CHECK3-NEXT: store ptr @.offload_sizes.15, ptr [[TMP25]], align 4 +// CHECK3-NEXT: store ptr @.offload_sizes.17, ptr [[TMP25]], align 4 // CHECK3-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 5 -// CHECK3-NEXT: store ptr @.offload_maptypes.16, ptr [[TMP26]], align 4 +// CHECK3-NEXT: store ptr @.offload_maptypes.18, ptr [[TMP26]], align 4 // CHECK3-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 6 // CHECK3-NEXT: store ptr null, ptr [[TMP27]], align 4 // CHECK3-NEXT: [[TMP28:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 7 @@ -3000,16 +3206,16 @@ int bar(int n){ // CHECK3-NEXT: store [3 x i32] zeroinitializer, ptr [[TMP32]], align 4 // CHECK3-NEXT: [[TMP33:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 12 // CHECK3-NEXT: store i32 0, ptr [[TMP33]], align 4 -// CHECK3-NEXT: [[TMP34:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB1]], i64 -1, i32 0, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZL7fstatici_l209.region_id, ptr [[KERNEL_ARGS]]) +// CHECK3-NEXT: [[TMP34:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB1]], i64 -1, i32 0, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZL7fstatici_l215.region_id, ptr [[KERNEL_ARGS]]) // CHECK3-NEXT: [[TMP35:%.*]] = icmp ne i32 [[TMP34]], 0 // CHECK3-NEXT: br i1 [[TMP35]], label [[OMP_OFFLOAD_FAILED:%.*]], label [[OMP_OFFLOAD_CONT:%.*]] // CHECK3: omp_offload.failed: -// CHECK3-NEXT: call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZL7fstatici_l209(i32 [[TMP1]], i32 [[TMP3]], i32 [[TMP5]], ptr [[B]]) #[[ATTR3]] +// CHECK3-NEXT: call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZL7fstatici_l215(i32 [[TMP1]], i32 [[TMP3]], i32 [[TMP5]], ptr [[B]]) #[[ATTR3]] // CHECK3-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK3: omp_offload.cont: // CHECK3-NEXT: br label [[OMP_IF_END:%.*]] // CHECK3: omp_if.else: -// CHECK3-NEXT: call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZL7fstatici_l209(i32 [[TMP1]], i32 [[TMP3]], i32 [[TMP5]], ptr [[B]]) #[[ATTR3]] +// CHECK3-NEXT: call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZL7fstatici_l215(i32 [[TMP1]], i32 [[TMP3]], i32 [[TMP5]], ptr [[B]]) #[[ATTR3]] // CHECK3-NEXT: br label [[OMP_IF_END]] // CHECK3: omp_if.end: // CHECK3-NEXT: [[TMP36:%.*]] = load i32, ptr [[A]], align 4 @@ -3071,9 +3277,9 @@ int bar(int n){ // CHECK3-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 3 // CHECK3-NEXT: store ptr [[TMP15]], ptr [[TMP19]], align 4 // CHECK3-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 4 -// CHECK3-NEXT: store ptr @.offload_sizes.17, ptr [[TMP20]], align 4 +// CHECK3-NEXT: store ptr @.offload_sizes.19, ptr [[TMP20]], align 4 // CHECK3-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 5 -// CHECK3-NEXT: store ptr @.offload_maptypes.18, ptr [[TMP21]], align 4 +// CHECK3-NEXT: store ptr @.offload_maptypes.20, ptr [[TMP21]], align 4 // CHECK3-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 6 // CHECK3-NEXT: store ptr null, ptr [[TMP22]], align 4 // CHECK3-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 7 @@ -3088,23 +3294,23 @@ int bar(int n){ // CHECK3-NEXT: store [3 x i32] zeroinitializer, ptr [[TMP27]], align 4 // CHECK3-NEXT: [[TMP28:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 12 // CHECK3-NEXT: store i32 0, ptr [[TMP28]], align 4 -// CHECK3-NEXT: [[TMP29:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB1]], i64 -1, i32 0, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z9ftemplateIiET_i_l192.region_id, ptr [[KERNEL_ARGS]]) +// CHECK3-NEXT: [[TMP29:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB1]], i64 -1, i32 0, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z9ftemplateIiET_i_l198.region_id, ptr [[KERNEL_ARGS]]) // CHECK3-NEXT: [[TMP30:%.*]] = icmp ne i32 [[TMP29]], 0 // CHECK3-NEXT: br i1 [[TMP30]], label [[OMP_OFFLOAD_FAILED:%.*]], label [[OMP_OFFLOAD_CONT:%.*]] // CHECK3: omp_offload.failed: -// CHECK3-NEXT: call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z9ftemplateIiET_i_l192(i32 [[TMP1]], i32 [[TMP3]], ptr [[B]]) #[[ATTR3]] +// CHECK3-NEXT: call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z9ftemplateIiET_i_l198(i32 [[TMP1]], i32 [[TMP3]], ptr [[B]]) #[[ATTR3]] // CHECK3-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK3: omp_offload.cont: // CHECK3-NEXT: br label [[OMP_IF_END:%.*]] // CHECK3: omp_if.else: -// CHECK3-NEXT: call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z9ftemplateIiET_i_l192(i32 [[TMP1]], i32 [[TMP3]], ptr [[B]]) #[[ATTR3]] +// CHECK3-NEXT: call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z9ftemplateIiET_i_l198(i32 [[TMP1]], i32 [[TMP3]], ptr [[B]]) #[[ATTR3]] // CHECK3-NEXT: br label [[OMP_IF_END]] // CHECK3: omp_if.end: // CHECK3-NEXT: [[TMP31:%.*]] = load i32, ptr [[A]], align 4 // CHECK3-NEXT: ret i32 [[TMP31]] // // -// CHECK3-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN2S12r1Ei_l227 +// CHECK3-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN2S12r1Ei_l233 // CHECK3-SAME: (ptr noundef [[THIS:%.*]], i32 noundef [[B:%.*]], i32 noundef [[VLA:%.*]], i32 noundef [[VLA1:%.*]], ptr noundef nonnull align 2 dereferenceable(2) [[C:%.*]]) #[[ATTR2]] { // CHECK3-NEXT: entry: // CHECK3-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4 @@ -3125,11 +3331,11 @@ int bar(int n){ // CHECK3-NEXT: [[TMP4:%.*]] = load i32, ptr [[B_ADDR]], align 4 // CHECK3-NEXT: store i32 [[TMP4]], ptr [[B_CASTED]], align 4 // CHECK3-NEXT: [[TMP5:%.*]] = load i32, ptr [[B_CASTED]], align 4 -// CHECK3-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB1]], i32 5, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN2S12r1Ei_l227.omp_outlined, ptr [[TMP0]], i32 [[TMP5]], i32 [[TMP1]], i32 [[TMP2]], ptr [[TMP3]]) +// CHECK3-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB1]], i32 5, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN2S12r1Ei_l233.omp_outlined, ptr [[TMP0]], i32 [[TMP5]], i32 [[TMP1]], i32 [[TMP2]], ptr [[TMP3]]) // CHECK3-NEXT: ret void // // -// CHECK3-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN2S12r1Ei_l227.omp_outlined +// CHECK3-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN2S12r1Ei_l233.omp_outlined // CHECK3-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], ptr noundef [[THIS:%.*]], i32 noundef [[B:%.*]], i32 noundef [[VLA:%.*]], i32 noundef [[VLA1:%.*]], ptr noundef nonnull align 2 dereferenceable(2) [[C:%.*]]) #[[ATTR2]] { // CHECK3-NEXT: entry: // CHECK3-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 4 @@ -3167,7 +3373,7 @@ int bar(int n){ // CHECK3-NEXT: ret void // // -// CHECK3-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZL7fstatici_l209 +// CHECK3-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZL7fstatici_l215 // CHECK3-SAME: (i32 noundef [[A:%.*]], i32 noundef [[AA:%.*]], i32 noundef [[AAA:%.*]], ptr noundef nonnull align 4 dereferenceable(40) [[B:%.*]]) #[[ATTR2]] { // CHECK3-NEXT: entry: // CHECK3-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 @@ -3191,11 +3397,11 @@ int bar(int n){ // CHECK3-NEXT: [[TMP5:%.*]] = load i8, ptr [[AAA_ADDR]], align 1 // CHECK3-NEXT: store i8 [[TMP5]], ptr [[AAA_CASTED]], align 1 // CHECK3-NEXT: [[TMP6:%.*]] = load i32, ptr [[AAA_CASTED]], align 4 -// CHECK3-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB1]], i32 4, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZL7fstatici_l209.omp_outlined, i32 [[TMP2]], i32 [[TMP4]], i32 [[TMP6]], ptr [[TMP0]]) +// CHECK3-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB1]], i32 4, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZL7fstatici_l215.omp_outlined, i32 [[TMP2]], i32 [[TMP4]], i32 [[TMP6]], ptr [[TMP0]]) // CHECK3-NEXT: ret void // // -// CHECK3-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZL7fstatici_l209.omp_outlined +// CHECK3-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZL7fstatici_l215.omp_outlined // CHECK3-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], i32 noundef [[A:%.*]], i32 noundef [[AA:%.*]], i32 noundef [[AAA:%.*]], ptr noundef nonnull align 4 dereferenceable(40) [[B:%.*]]) #[[ATTR2]] { // CHECK3-NEXT: entry: // CHECK3-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 4 @@ -3231,7 +3437,7 @@ int bar(int n){ // CHECK3-NEXT: ret void // // -// CHECK3-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z9ftemplateIiET_i_l192 +// CHECK3-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z9ftemplateIiET_i_l198 // CHECK3-SAME: (i32 noundef [[A:%.*]], i32 noundef [[AA:%.*]], ptr noundef nonnull align 4 dereferenceable(40) [[B:%.*]]) #[[ATTR2]] { // CHECK3-NEXT: entry: // CHECK3-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 @@ -3249,11 +3455,11 @@ int bar(int n){ // CHECK3-NEXT: [[TMP3:%.*]] = load i16, ptr [[AA_ADDR]], align 2 // CHECK3-NEXT: store i16 [[TMP3]], ptr [[AA_CASTED]], align 2 // CHECK3-NEXT: [[TMP4:%.*]] = load i32, ptr [[AA_CASTED]], align 4 -// CHECK3-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB1]], i32 3, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z9ftemplateIiET_i_l192.omp_outlined, i32 [[TMP2]], i32 [[TMP4]], ptr [[TMP0]]) +// CHECK3-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB1]], i32 3, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z9ftemplateIiET_i_l198.omp_outlined, i32 [[TMP2]], i32 [[TMP4]], ptr [[TMP0]]) // CHECK3-NEXT: ret void // // -// CHECK3-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z9ftemplateIiET_i_l192.omp_outlined +// CHECK3-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z9ftemplateIiET_i_l198.omp_outlined // CHECK3-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], i32 noundef [[A:%.*]], i32 noundef [[AA:%.*]], ptr noundef nonnull align 4 dereferenceable(40) [[B:%.*]]) #[[ATTR2]] { // CHECK3-NEXT: entry: // CHECK3-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 4 @@ -3393,7 +3599,48 @@ int bar(int n){ // CHECK9-NEXT: ret void // // -// CHECK9-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l142 +// CHECK9-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l124 +// CHECK9-SAME: (i64 noundef [[A:%.*]], i64 noundef [[AA:%.*]]) #[[ATTR0]] { +// CHECK9-NEXT: entry: +// CHECK9-NEXT: [[A_ADDR:%.*]] = alloca i64, align 8 +// CHECK9-NEXT: [[AA_ADDR:%.*]] = alloca i64, align 8 +// CHECK9-NEXT: [[A_CASTED:%.*]] = alloca i64, align 8 +// CHECK9-NEXT: [[AA_CASTED:%.*]] = alloca i64, align 8 +// CHECK9-NEXT: store i64 [[A]], ptr [[A_ADDR]], align 8 +// CHECK9-NEXT: store i64 [[AA]], ptr [[AA_ADDR]], align 8 +// CHECK9-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4 +// CHECK9-NEXT: store i32 [[TMP0]], ptr [[A_CASTED]], align 4 +// CHECK9-NEXT: [[TMP1:%.*]] = load i64, ptr [[A_CASTED]], align 8 +// CHECK9-NEXT: [[TMP2:%.*]] = load i16, ptr [[AA_ADDR]], align 2 +// CHECK9-NEXT: store i16 [[TMP2]], ptr [[AA_CASTED]], align 2 +// CHECK9-NEXT: [[TMP3:%.*]] = load i64, ptr [[AA_CASTED]], align 8 +// CHECK9-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB1]], i32 2, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l124.omp_outlined, i64 [[TMP1]], i64 [[TMP3]]) +// CHECK9-NEXT: ret void +// +// +// CHECK9-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l124.omp_outlined +// CHECK9-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], i64 noundef [[A:%.*]], i64 noundef [[AA:%.*]]) #[[ATTR0]] { +// CHECK9-NEXT: entry: +// CHECK9-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 8 +// CHECK9-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca ptr, align 8 +// CHECK9-NEXT: [[A_ADDR:%.*]] = alloca i64, align 8 +// CHECK9-NEXT: [[AA_ADDR:%.*]] = alloca i64, align 8 +// CHECK9-NEXT: store ptr [[DOTGLOBAL_TID_]], ptr [[DOTGLOBAL_TID__ADDR]], align 8 +// CHECK9-NEXT: store ptr [[DOTBOUND_TID_]], ptr [[DOTBOUND_TID__ADDR]], align 8 +// CHECK9-NEXT: store i64 [[A]], ptr [[A_ADDR]], align 8 +// CHECK9-NEXT: store i64 [[AA]], ptr [[AA_ADDR]], align 8 +// CHECK9-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4 +// CHECK9-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP0]], 1 +// CHECK9-NEXT: store i32 [[ADD]], ptr [[A_ADDR]], align 4 +// CHECK9-NEXT: [[TMP1:%.*]] = load i16, ptr [[AA_ADDR]], align 2 +// CHECK9-NEXT: [[CONV:%.*]] = sext i16 [[TMP1]] to i32 +// CHECK9-NEXT: [[ADD1:%.*]] = add nsw i32 [[CONV]], 1 +// CHECK9-NEXT: [[CONV2:%.*]] = trunc i32 [[ADD1]] to i16 +// CHECK9-NEXT: store i16 [[CONV2]], ptr [[AA_ADDR]], align 2 +// CHECK9-NEXT: ret void +// +// +// CHECK9-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l148 // CHECK9-SAME: (i64 noundef [[A:%.*]], ptr noundef nonnull align 4 dereferenceable(40) [[B:%.*]], i64 noundef [[VLA:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[BN:%.*]], ptr noundef nonnull align 8 dereferenceable(400) [[C:%.*]], i64 noundef [[VLA1:%.*]], i64 noundef [[VLA3:%.*]], ptr noundef nonnull align 8 dereferenceable(8) [[CN:%.*]], ptr noundef nonnull align 8 dereferenceable(16) [[D:%.*]]) #[[ATTR0]] { // CHECK9-NEXT: entry: // CHECK9-NEXT: [[A_ADDR:%.*]] = alloca i64, align 8 @@ -3426,11 +3673,11 @@ int bar(int n){ // CHECK9-NEXT: [[TMP8:%.*]] = load i32, ptr [[A_ADDR]], align 4 // CHECK9-NEXT: store i32 [[TMP8]], ptr [[A_CASTED]], align 4 // CHECK9-NEXT: [[TMP9:%.*]] = load i64, ptr [[A_CASTED]], align 8 -// CHECK9-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB1]], i32 9, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l142.omp_outlined, i64 [[TMP9]], ptr [[TMP0]], i64 [[TMP1]], ptr [[TMP2]], ptr [[TMP3]], i64 [[TMP4]], i64 [[TMP5]], ptr [[TMP6]], ptr [[TMP7]]) +// CHECK9-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB1]], i32 9, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l148.omp_outlined, i64 [[TMP9]], ptr [[TMP0]], i64 [[TMP1]], ptr [[TMP2]], ptr [[TMP3]], i64 [[TMP4]], i64 [[TMP5]], ptr [[TMP6]], ptr [[TMP7]]) // CHECK9-NEXT: ret void // // -// CHECK9-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l142.omp_outlined +// CHECK9-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l148.omp_outlined // CHECK9-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], i64 noundef [[A:%.*]], ptr noundef nonnull align 4 dereferenceable(40) [[B:%.*]], i64 noundef [[VLA:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[BN:%.*]], ptr noundef nonnull align 8 dereferenceable(400) [[C:%.*]], i64 noundef [[VLA1:%.*]], i64 noundef [[VLA3:%.*]], ptr noundef nonnull align 8 dereferenceable(8) [[CN:%.*]], ptr noundef nonnull align 8 dereferenceable(16) [[D:%.*]]) #[[ATTR0]] { // CHECK9-NEXT: entry: // CHECK9-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 8 @@ -3502,7 +3749,7 @@ int bar(int n){ // CHECK9-NEXT: ret void // // -// CHECK9-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l154 +// CHECK9-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l160 // CHECK9-SAME: (i64 noundef [[NN:%.*]]) #[[ATTR0]] { // CHECK9-NEXT: entry: // CHECK9-NEXT: [[NN_ADDR:%.*]] = alloca i64, align 8 @@ -3511,11 +3758,11 @@ int bar(int n){ // CHECK9-NEXT: [[TMP0:%.*]] = load i32, ptr [[NN_ADDR]], align 4 // CHECK9-NEXT: store i32 [[TMP0]], ptr [[NN_CASTED]], align 4 // CHECK9-NEXT: [[TMP1:%.*]] = load i64, ptr [[NN_CASTED]], align 8 -// CHECK9-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB1]], i32 1, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l154.omp_outlined, i64 [[TMP1]]) +// CHECK9-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB1]], i32 1, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l160.omp_outlined, i64 [[TMP1]]) // CHECK9-NEXT: ret void // // -// CHECK9-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l154.omp_outlined +// CHECK9-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l160.omp_outlined // CHECK9-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], i64 noundef [[NN:%.*]]) #[[ATTR0]] { // CHECK9-NEXT: entry: // CHECK9-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 8 @@ -3528,11 +3775,11 @@ int bar(int n){ // CHECK9-NEXT: [[TMP0:%.*]] = load i32, ptr [[NN_ADDR]], align 4 // CHECK9-NEXT: store i32 [[TMP0]], ptr [[NN_CASTED]], align 4 // CHECK9-NEXT: [[TMP1:%.*]] = load i64, ptr [[NN_CASTED]], align 8 -// CHECK9-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @[[GLOB1]], i32 1, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l154.omp_outlined.omp_outlined, i64 [[TMP1]]) +// CHECK9-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @[[GLOB1]], i32 1, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l160.omp_outlined.omp_outlined, i64 [[TMP1]]) // CHECK9-NEXT: ret void // // -// CHECK9-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l154.omp_outlined.omp_outlined +// CHECK9-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l160.omp_outlined.omp_outlined // CHECK9-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], i64 noundef [[NN:%.*]]) #[[ATTR0]] { // CHECK9-NEXT: entry: // CHECK9-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 8 @@ -3544,7 +3791,7 @@ int bar(int n){ // CHECK9-NEXT: ret void // // -// CHECK9-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l157 +// CHECK9-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l163 // CHECK9-SAME: (i64 noundef [[NN:%.*]]) #[[ATTR0]] { // CHECK9-NEXT: entry: // CHECK9-NEXT: [[NN_ADDR:%.*]] = alloca i64, align 8 @@ -3553,11 +3800,11 @@ int bar(int n){ // CHECK9-NEXT: [[TMP0:%.*]] = load i32, ptr [[NN_ADDR]], align 4 // CHECK9-NEXT: store i32 [[TMP0]], ptr [[NN_CASTED]], align 4 // CHECK9-NEXT: [[TMP1:%.*]] = load i64, ptr [[NN_CASTED]], align 8 -// CHECK9-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB1]], i32 1, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l157.omp_outlined, i64 [[TMP1]]) +// CHECK9-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB1]], i32 1, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l163.omp_outlined, i64 [[TMP1]]) // CHECK9-NEXT: ret void // // -// CHECK9-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l157.omp_outlined +// CHECK9-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l163.omp_outlined // CHECK9-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], i64 noundef [[NN:%.*]]) #[[ATTR0]] { // CHECK9-NEXT: entry: // CHECK9-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 8 @@ -3566,11 +3813,11 @@ int bar(int n){ // CHECK9-NEXT: store ptr [[DOTGLOBAL_TID_]], ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK9-NEXT: store ptr [[DOTBOUND_TID_]], ptr [[DOTBOUND_TID__ADDR]], align 8 // CHECK9-NEXT: store i64 [[NN]], ptr [[NN_ADDR]], align 8 -// CHECK9-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @[[GLOB1]], i32 1, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l157.omp_outlined.omp_outlined, ptr [[NN_ADDR]]) +// CHECK9-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @[[GLOB1]], i32 1, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l163.omp_outlined.omp_outlined, ptr [[NN_ADDR]]) // CHECK9-NEXT: ret void // // -// CHECK9-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l157.omp_outlined.omp_outlined +// CHECK9-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l163.omp_outlined.omp_outlined // CHECK9-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[NN:%.*]]) #[[ATTR0]] { // CHECK9-NEXT: entry: // CHECK9-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 8 @@ -3583,17 +3830,17 @@ int bar(int n){ // CHECK9-NEXT: ret void // // -// CHECK9-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z6bazzzziPi_l182 +// CHECK9-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z6bazzzziPi_l188 // CHECK9-SAME: (i64 noundef [[VLA:%.*]]) #[[ATTR0]] { // CHECK9-NEXT: entry: // CHECK9-NEXT: [[VLA_ADDR:%.*]] = alloca i64, align 8 // CHECK9-NEXT: store i64 [[VLA]], ptr [[VLA_ADDR]], align 8 // CHECK9-NEXT: [[TMP0:%.*]] = load i64, ptr [[VLA_ADDR]], align 8 -// CHECK9-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB1]], i32 1, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z6bazzzziPi_l182.omp_outlined, i64 [[TMP0]]) +// CHECK9-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB1]], i32 1, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z6bazzzziPi_l188.omp_outlined, i64 [[TMP0]]) // CHECK9-NEXT: ret void // // -// CHECK9-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z6bazzzziPi_l182.omp_outlined +// CHECK9-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z6bazzzziPi_l188.omp_outlined // CHECK9-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], i64 noundef [[VLA:%.*]]) #[[ATTR0]] { // CHECK9-NEXT: entry: // CHECK9-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 8 @@ -3607,7 +3854,7 @@ int bar(int n){ // CHECK9-NEXT: ret void // // -// CHECK9-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZL7fstatici_l209 +// CHECK9-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZL7fstatici_l215 // CHECK9-SAME: (i64 noundef [[A:%.*]], i64 noundef [[AA:%.*]], i64 noundef [[AAA:%.*]], ptr noundef nonnull align 4 dereferenceable(40) [[B:%.*]]) #[[ATTR0]] { // CHECK9-NEXT: entry: // CHECK9-NEXT: [[A_ADDR:%.*]] = alloca i64, align 8 @@ -3631,11 +3878,11 @@ int bar(int n){ // CHECK9-NEXT: [[TMP5:%.*]] = load i8, ptr [[AAA_ADDR]], align 1 // CHECK9-NEXT: store i8 [[TMP5]], ptr [[AAA_CASTED]], align 1 // CHECK9-NEXT: [[TMP6:%.*]] = load i64, ptr [[AAA_CASTED]], align 8 -// CHECK9-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB1]], i32 4, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZL7fstatici_l209.omp_outlined, i64 [[TMP2]], i64 [[TMP4]], i64 [[TMP6]], ptr [[TMP0]]) +// CHECK9-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB1]], i32 4, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZL7fstatici_l215.omp_outlined, i64 [[TMP2]], i64 [[TMP4]], i64 [[TMP6]], ptr [[TMP0]]) // CHECK9-NEXT: ret void // // -// CHECK9-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZL7fstatici_l209.omp_outlined +// CHECK9-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZL7fstatici_l215.omp_outlined // CHECK9-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], i64 noundef [[A:%.*]], i64 noundef [[AA:%.*]], i64 noundef [[AAA:%.*]], ptr noundef nonnull align 4 dereferenceable(40) [[B:%.*]]) #[[ATTR0]] { // CHECK9-NEXT: entry: // CHECK9-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 8 @@ -3671,7 +3918,7 @@ int bar(int n){ // CHECK9-NEXT: ret void // // -// CHECK9-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN2S12r1Ei_l227 +// CHECK9-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN2S12r1Ei_l233 // CHECK9-SAME: (ptr noundef [[THIS:%.*]], i64 noundef [[B:%.*]], i64 noundef [[VLA:%.*]], i64 noundef [[VLA1:%.*]], ptr noundef nonnull align 2 dereferenceable(2) [[C:%.*]]) #[[ATTR0]] { // CHECK9-NEXT: entry: // CHECK9-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 @@ -3692,11 +3939,11 @@ int bar(int n){ // CHECK9-NEXT: [[TMP4:%.*]] = load i32, ptr [[B_ADDR]], align 4 // CHECK9-NEXT: store i32 [[TMP4]], ptr [[B_CASTED]], align 4 // CHECK9-NEXT: [[TMP5:%.*]] = load i64, ptr [[B_CASTED]], align 8 -// CHECK9-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB1]], i32 5, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN2S12r1Ei_l227.omp_outlined, ptr [[TMP0]], i64 [[TMP5]], i64 [[TMP1]], i64 [[TMP2]], ptr [[TMP3]]) +// CHECK9-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB1]], i32 5, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN2S12r1Ei_l233.omp_outlined, ptr [[TMP0]], i64 [[TMP5]], i64 [[TMP1]], i64 [[TMP2]], ptr [[TMP3]]) // CHECK9-NEXT: ret void // // -// CHECK9-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN2S12r1Ei_l227.omp_outlined +// CHECK9-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN2S12r1Ei_l233.omp_outlined // CHECK9-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], ptr noundef [[THIS:%.*]], i64 noundef [[B:%.*]], i64 noundef [[VLA:%.*]], i64 noundef [[VLA1:%.*]], ptr noundef nonnull align 2 dereferenceable(2) [[C:%.*]]) #[[ATTR0]] { // CHECK9-NEXT: entry: // CHECK9-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 8 @@ -3734,7 +3981,7 @@ int bar(int n){ // CHECK9-NEXT: ret void // // -// CHECK9-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z9ftemplateIiET_i_l192 +// CHECK9-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z9ftemplateIiET_i_l198 // CHECK9-SAME: (i64 noundef [[A:%.*]], i64 noundef [[AA:%.*]], ptr noundef nonnull align 4 dereferenceable(40) [[B:%.*]]) #[[ATTR0]] { // CHECK9-NEXT: entry: // CHECK9-NEXT: [[A_ADDR:%.*]] = alloca i64, align 8 @@ -3752,11 +3999,11 @@ int bar(int n){ // CHECK9-NEXT: [[TMP3:%.*]] = load i16, ptr [[AA_ADDR]], align 2 // CHECK9-NEXT: store i16 [[TMP3]], ptr [[AA_CASTED]], align 2 // CHECK9-NEXT: [[TMP4:%.*]] = load i64, ptr [[AA_CASTED]], align 8 -// CHECK9-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB1]], i32 3, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z9ftemplateIiET_i_l192.omp_outlined, i64 [[TMP2]], i64 [[TMP4]], ptr [[TMP0]]) +// CHECK9-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB1]], i32 3, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z9ftemplateIiET_i_l198.omp_outlined, i64 [[TMP2]], i64 [[TMP4]], ptr [[TMP0]]) // CHECK9-NEXT: ret void // // -// CHECK9-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z9ftemplateIiET_i_l192.omp_outlined +// CHECK9-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z9ftemplateIiET_i_l198.omp_outlined // CHECK9-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], i64 noundef [[A:%.*]], i64 noundef [[AA:%.*]], ptr noundef nonnull align 4 dereferenceable(40) [[B:%.*]]) #[[ATTR0]] { // CHECK9-NEXT: entry: // CHECK9-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 8 @@ -3889,7 +4136,48 @@ int bar(int n){ // CHECK11-NEXT: ret void // // -// CHECK11-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l142 +// CHECK11-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l124 +// CHECK11-SAME: (i32 noundef [[A:%.*]], i32 noundef [[AA:%.*]]) #[[ATTR0]] { +// CHECK11-NEXT: entry: +// CHECK11-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 +// CHECK11-NEXT: [[AA_ADDR:%.*]] = alloca i32, align 4 +// CHECK11-NEXT: [[A_CASTED:%.*]] = alloca i32, align 4 +// CHECK11-NEXT: [[AA_CASTED:%.*]] = alloca i32, align 4 +// CHECK11-NEXT: store i32 [[A]], ptr [[A_ADDR]], align 4 +// CHECK11-NEXT: store i32 [[AA]], ptr [[AA_ADDR]], align 4 +// CHECK11-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4 +// CHECK11-NEXT: store i32 [[TMP0]], ptr [[A_CASTED]], align 4 +// CHECK11-NEXT: [[TMP1:%.*]] = load i32, ptr [[A_CASTED]], align 4 +// CHECK11-NEXT: [[TMP2:%.*]] = load i16, ptr [[AA_ADDR]], align 2 +// CHECK11-NEXT: store i16 [[TMP2]], ptr [[AA_CASTED]], align 2 +// CHECK11-NEXT: [[TMP3:%.*]] = load i32, ptr [[AA_CASTED]], align 4 +// CHECK11-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB1]], i32 2, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l124.omp_outlined, i32 [[TMP1]], i32 [[TMP3]]) +// CHECK11-NEXT: ret void +// +// +// CHECK11-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l124.omp_outlined +// CHECK11-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], i32 noundef [[A:%.*]], i32 noundef [[AA:%.*]]) #[[ATTR0]] { +// CHECK11-NEXT: entry: +// CHECK11-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 4 +// CHECK11-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca ptr, align 4 +// CHECK11-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 +// CHECK11-NEXT: [[AA_ADDR:%.*]] = alloca i32, align 4 +// CHECK11-NEXT: store ptr [[DOTGLOBAL_TID_]], ptr [[DOTGLOBAL_TID__ADDR]], align 4 +// CHECK11-NEXT: store ptr [[DOTBOUND_TID_]], ptr [[DOTBOUND_TID__ADDR]], align 4 +// CHECK11-NEXT: store i32 [[A]], ptr [[A_ADDR]], align 4 +// CHECK11-NEXT: store i32 [[AA]], ptr [[AA_ADDR]], align 4 +// CHECK11-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4 +// CHECK11-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP0]], 1 +// CHECK11-NEXT: store i32 [[ADD]], ptr [[A_ADDR]], align 4 +// CHECK11-NEXT: [[TMP1:%.*]] = load i16, ptr [[AA_ADDR]], align 2 +// CHECK11-NEXT: [[CONV:%.*]] = sext i16 [[TMP1]] to i32 +// CHECK11-NEXT: [[ADD1:%.*]] = add nsw i32 [[CONV]], 1 +// CHECK11-NEXT: [[CONV2:%.*]] = trunc i32 [[ADD1]] to i16 +// CHECK11-NEXT: store i16 [[CONV2]], ptr [[AA_ADDR]], align 2 +// CHECK11-NEXT: ret void +// +// +// CHECK11-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l148 // CHECK11-SAME: (i32 noundef [[A:%.*]], ptr noundef nonnull align 4 dereferenceable(40) [[B:%.*]], i32 noundef [[VLA:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[BN:%.*]], ptr noundef nonnull align 4 dereferenceable(400) [[C:%.*]], i32 noundef [[VLA1:%.*]], i32 noundef [[VLA3:%.*]], ptr noundef nonnull align 4 dereferenceable(8) [[CN:%.*]], ptr noundef nonnull align 4 dereferenceable(12) [[D:%.*]]) #[[ATTR0]] { // CHECK11-NEXT: entry: // CHECK11-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 @@ -3922,11 +4210,11 @@ int bar(int n){ // CHECK11-NEXT: [[TMP8:%.*]] = load i32, ptr [[A_ADDR]], align 4 // CHECK11-NEXT: store i32 [[TMP8]], ptr [[A_CASTED]], align 4 // CHECK11-NEXT: [[TMP9:%.*]] = load i32, ptr [[A_CASTED]], align 4 -// CHECK11-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB1]], i32 9, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l142.omp_outlined, i32 [[TMP9]], ptr [[TMP0]], i32 [[TMP1]], ptr [[TMP2]], ptr [[TMP3]], i32 [[TMP4]], i32 [[TMP5]], ptr [[TMP6]], ptr [[TMP7]]) +// CHECK11-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB1]], i32 9, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l148.omp_outlined, i32 [[TMP9]], ptr [[TMP0]], i32 [[TMP1]], ptr [[TMP2]], ptr [[TMP3]], i32 [[TMP4]], i32 [[TMP5]], ptr [[TMP6]], ptr [[TMP7]]) // CHECK11-NEXT: ret void // // -// CHECK11-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l142.omp_outlined +// CHECK11-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l148.omp_outlined // CHECK11-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], i32 noundef [[A:%.*]], ptr noundef nonnull align 4 dereferenceable(40) [[B:%.*]], i32 noundef [[VLA:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[BN:%.*]], ptr noundef nonnull align 4 dereferenceable(400) [[C:%.*]], i32 noundef [[VLA1:%.*]], i32 noundef [[VLA3:%.*]], ptr noundef nonnull align 4 dereferenceable(8) [[CN:%.*]], ptr noundef nonnull align 4 dereferenceable(12) [[D:%.*]]) #[[ATTR0]] { // CHECK11-NEXT: entry: // CHECK11-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 4 @@ -3998,7 +4286,7 @@ int bar(int n){ // CHECK11-NEXT: ret void // // -// CHECK11-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l154 +// CHECK11-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l160 // CHECK11-SAME: (i32 noundef [[NN:%.*]]) #[[ATTR0]] { // CHECK11-NEXT: entry: // CHECK11-NEXT: [[NN_ADDR:%.*]] = alloca i32, align 4 @@ -4007,11 +4295,11 @@ int bar(int n){ // CHECK11-NEXT: [[TMP0:%.*]] = load i32, ptr [[NN_ADDR]], align 4 // CHECK11-NEXT: store i32 [[TMP0]], ptr [[NN_CASTED]], align 4 // CHECK11-NEXT: [[TMP1:%.*]] = load i32, ptr [[NN_CASTED]], align 4 -// CHECK11-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB1]], i32 1, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l154.omp_outlined, i32 [[TMP1]]) +// CHECK11-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB1]], i32 1, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l160.omp_outlined, i32 [[TMP1]]) // CHECK11-NEXT: ret void // // -// CHECK11-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l154.omp_outlined +// CHECK11-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l160.omp_outlined // CHECK11-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], i32 noundef [[NN:%.*]]) #[[ATTR0]] { // CHECK11-NEXT: entry: // CHECK11-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 4 @@ -4024,11 +4312,11 @@ int bar(int n){ // CHECK11-NEXT: [[TMP0:%.*]] = load i32, ptr [[NN_ADDR]], align 4 // CHECK11-NEXT: store i32 [[TMP0]], ptr [[NN_CASTED]], align 4 // CHECK11-NEXT: [[TMP1:%.*]] = load i32, ptr [[NN_CASTED]], align 4 -// CHECK11-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @[[GLOB1]], i32 1, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l154.omp_outlined.omp_outlined, i32 [[TMP1]]) +// CHECK11-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @[[GLOB1]], i32 1, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l160.omp_outlined.omp_outlined, i32 [[TMP1]]) // CHECK11-NEXT: ret void // // -// CHECK11-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l154.omp_outlined.omp_outlined +// CHECK11-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l160.omp_outlined.omp_outlined // CHECK11-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], i32 noundef [[NN:%.*]]) #[[ATTR0]] { // CHECK11-NEXT: entry: // CHECK11-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 4 @@ -4040,7 +4328,7 @@ int bar(int n){ // CHECK11-NEXT: ret void // // -// CHECK11-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l157 +// CHECK11-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l163 // CHECK11-SAME: (i32 noundef [[NN:%.*]]) #[[ATTR0]] { // CHECK11-NEXT: entry: // CHECK11-NEXT: [[NN_ADDR:%.*]] = alloca i32, align 4 @@ -4049,11 +4337,11 @@ int bar(int n){ // CHECK11-NEXT: [[TMP0:%.*]] = load i32, ptr [[NN_ADDR]], align 4 // CHECK11-NEXT: store i32 [[TMP0]], ptr [[NN_CASTED]], align 4 // CHECK11-NEXT: [[TMP1:%.*]] = load i32, ptr [[NN_CASTED]], align 4 -// CHECK11-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB1]], i32 1, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l157.omp_outlined, i32 [[TMP1]]) +// CHECK11-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB1]], i32 1, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l163.omp_outlined, i32 [[TMP1]]) // CHECK11-NEXT: ret void // // -// CHECK11-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l157.omp_outlined +// CHECK11-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l163.omp_outlined // CHECK11-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], i32 noundef [[NN:%.*]]) #[[ATTR0]] { // CHECK11-NEXT: entry: // CHECK11-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 4 @@ -4062,11 +4350,11 @@ int bar(int n){ // CHECK11-NEXT: store ptr [[DOTGLOBAL_TID_]], ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK11-NEXT: store ptr [[DOTBOUND_TID_]], ptr [[DOTBOUND_TID__ADDR]], align 4 // CHECK11-NEXT: store i32 [[NN]], ptr [[NN_ADDR]], align 4 -// CHECK11-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @[[GLOB1]], i32 1, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l157.omp_outlined.omp_outlined, ptr [[NN_ADDR]]) +// CHECK11-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @[[GLOB1]], i32 1, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l163.omp_outlined.omp_outlined, ptr [[NN_ADDR]]) // CHECK11-NEXT: ret void // // -// CHECK11-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l157.omp_outlined.omp_outlined +// CHECK11-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l163.omp_outlined.omp_outlined // CHECK11-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[NN:%.*]]) #[[ATTR0]] { // CHECK11-NEXT: entry: // CHECK11-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 4 @@ -4079,17 +4367,17 @@ int bar(int n){ // CHECK11-NEXT: ret void // // -// CHECK11-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z6bazzzziPi_l182 +// CHECK11-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z6bazzzziPi_l188 // CHECK11-SAME: (i32 noundef [[VLA:%.*]]) #[[ATTR0]] { // CHECK11-NEXT: entry: // CHECK11-NEXT: [[VLA_ADDR:%.*]] = alloca i32, align 4 // CHECK11-NEXT: store i32 [[VLA]], ptr [[VLA_ADDR]], align 4 // CHECK11-NEXT: [[TMP0:%.*]] = load i32, ptr [[VLA_ADDR]], align 4 -// CHECK11-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB1]], i32 1, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z6bazzzziPi_l182.omp_outlined, i32 [[TMP0]]) +// CHECK11-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB1]], i32 1, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z6bazzzziPi_l188.omp_outlined, i32 [[TMP0]]) // CHECK11-NEXT: ret void // // -// CHECK11-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z6bazzzziPi_l182.omp_outlined +// CHECK11-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z6bazzzziPi_l188.omp_outlined // CHECK11-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], i32 noundef [[VLA:%.*]]) #[[ATTR0]] { // CHECK11-NEXT: entry: // CHECK11-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 4 @@ -4103,7 +4391,7 @@ int bar(int n){ // CHECK11-NEXT: ret void // // -// CHECK11-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZL7fstatici_l209 +// CHECK11-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZL7fstatici_l215 // CHECK11-SAME: (i32 noundef [[A:%.*]], i32 noundef [[AA:%.*]], i32 noundef [[AAA:%.*]], ptr noundef nonnull align 4 dereferenceable(40) [[B:%.*]]) #[[ATTR0]] { // CHECK11-NEXT: entry: // CHECK11-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 @@ -4127,11 +4415,11 @@ int bar(int n){ // CHECK11-NEXT: [[TMP5:%.*]] = load i8, ptr [[AAA_ADDR]], align 1 // CHECK11-NEXT: store i8 [[TMP5]], ptr [[AAA_CASTED]], align 1 // CHECK11-NEXT: [[TMP6:%.*]] = load i32, ptr [[AAA_CASTED]], align 4 -// CHECK11-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB1]], i32 4, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZL7fstatici_l209.omp_outlined, i32 [[TMP2]], i32 [[TMP4]], i32 [[TMP6]], ptr [[TMP0]]) +// CHECK11-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB1]], i32 4, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZL7fstatici_l215.omp_outlined, i32 [[TMP2]], i32 [[TMP4]], i32 [[TMP6]], ptr [[TMP0]]) // CHECK11-NEXT: ret void // // -// CHECK11-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZL7fstatici_l209.omp_outlined +// CHECK11-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZL7fstatici_l215.omp_outlined // CHECK11-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], i32 noundef [[A:%.*]], i32 noundef [[AA:%.*]], i32 noundef [[AAA:%.*]], ptr noundef nonnull align 4 dereferenceable(40) [[B:%.*]]) #[[ATTR0]] { // CHECK11-NEXT: entry: // CHECK11-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 4 @@ -4167,7 +4455,7 @@ int bar(int n){ // CHECK11-NEXT: ret void // // -// CHECK11-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN2S12r1Ei_l227 +// CHECK11-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN2S12r1Ei_l233 // CHECK11-SAME: (ptr noundef [[THIS:%.*]], i32 noundef [[B:%.*]], i32 noundef [[VLA:%.*]], i32 noundef [[VLA1:%.*]], ptr noundef nonnull align 2 dereferenceable(2) [[C:%.*]]) #[[ATTR0]] { // CHECK11-NEXT: entry: // CHECK11-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4 @@ -4188,11 +4476,11 @@ int bar(int n){ // CHECK11-NEXT: [[TMP4:%.*]] = load i32, ptr [[B_ADDR]], align 4 // CHECK11-NEXT: store i32 [[TMP4]], ptr [[B_CASTED]], align 4 // CHECK11-NEXT: [[TMP5:%.*]] = load i32, ptr [[B_CASTED]], align 4 -// CHECK11-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB1]], i32 5, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN2S12r1Ei_l227.omp_outlined, ptr [[TMP0]], i32 [[TMP5]], i32 [[TMP1]], i32 [[TMP2]], ptr [[TMP3]]) +// CHECK11-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB1]], i32 5, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN2S12r1Ei_l233.omp_outlined, ptr [[TMP0]], i32 [[TMP5]], i32 [[TMP1]], i32 [[TMP2]], ptr [[TMP3]]) // CHECK11-NEXT: ret void // // -// CHECK11-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN2S12r1Ei_l227.omp_outlined +// CHECK11-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN2S12r1Ei_l233.omp_outlined // CHECK11-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], ptr noundef [[THIS:%.*]], i32 noundef [[B:%.*]], i32 noundef [[VLA:%.*]], i32 noundef [[VLA1:%.*]], ptr noundef nonnull align 2 dereferenceable(2) [[C:%.*]]) #[[ATTR0]] { // CHECK11-NEXT: entry: // CHECK11-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 4 @@ -4230,7 +4518,7 @@ int bar(int n){ // CHECK11-NEXT: ret void // // -// CHECK11-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z9ftemplateIiET_i_l192 +// CHECK11-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z9ftemplateIiET_i_l198 // CHECK11-SAME: (i32 noundef [[A:%.*]], i32 noundef [[AA:%.*]], ptr noundef nonnull align 4 dereferenceable(40) [[B:%.*]]) #[[ATTR0]] { // CHECK11-NEXT: entry: // CHECK11-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 @@ -4248,11 +4536,11 @@ int bar(int n){ // CHECK11-NEXT: [[TMP3:%.*]] = load i16, ptr [[AA_ADDR]], align 2 // CHECK11-NEXT: store i16 [[TMP3]], ptr [[AA_CASTED]], align 2 // CHECK11-NEXT: [[TMP4:%.*]] = load i32, ptr [[AA_CASTED]], align 4 -// CHECK11-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB1]], i32 3, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z9ftemplateIiET_i_l192.omp_outlined, i32 [[TMP2]], i32 [[TMP4]], ptr [[TMP0]]) +// CHECK11-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @[[GLOB1]], i32 3, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z9ftemplateIiET_i_l198.omp_outlined, i32 [[TMP2]], i32 [[TMP4]], ptr [[TMP0]]) // CHECK11-NEXT: ret void // // -// CHECK11-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z9ftemplateIiET_i_l192.omp_outlined +// CHECK11-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z9ftemplateIiET_i_l198.omp_outlined // CHECK11-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], i32 noundef [[A:%.*]], i32 noundef [[AA:%.*]], ptr noundef nonnull align 4 dereferenceable(40) [[B:%.*]]) #[[ATTR0]] { // CHECK11-NEXT: entry: // CHECK11-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 4 diff --git a/clang/test/OpenMP/target_visibility.cpp b/clang/test/OpenMP/target_visibility.cpp index 938d164df89bff..2554f653170b94 100644 --- a/clang/test/OpenMP/target_visibility.cpp +++ b/clang/test/OpenMP/target_visibility.cpp @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -debug-info-kind=limited -verify -fopenmp -x c++ -triple nvptx64-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-target-device -o - | FileCheck %s -// RUN: %clang_cc1 -debug-info-kind=limited -verify -fopenmp -x c++ -triple nvptx-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm %s -fopenmp-is-target-device -o - | FileCheck %s +// RUN: %clang_cc1 -debug-info-kind=limited -verify -fopenmp -x c++ -triple amdgcn-amd-amdhsa -fopenmp-targets=amdgcn-amd-amdhsa -emit-llvm %s -fopenmp-is-target-device -o - | FileCheck %s // expected-no-diagnostics @@ -21,6 +21,14 @@ void B::bar() { A a; a.foo(); } void B::sbar() { A::sfoo(); } #pragma omp declare target to(B::bar, B::sbar) +[[gnu::visibility("hidden")]] extern const int x = 0; +#pragma omp declare target to(x) device_type(nohost) + +[[gnu::visibility("hidden")]] int y = 0; +#pragma omp declare target to(y) + +// CHECK-DAG: @x = hidden{{.*}} constant i32 0 +// CHECK-DAG: @y = protected{{.*}} i32 0 // CHECK-DAG: define hidden void @_ZN1B4sbarEv() // CHECK-DAG: define linkonce_odr hidden void @_ZN1A4sfooEv() // CHECK-DAG: define hidden void @_ZN1B3barEv( diff --git a/clang/test/Parser/c2x-auto.c b/clang/test/Parser/c2x-auto.c new file mode 100644 index 00000000000000..b878a5b7c42d47 --- /dev/null +++ b/clang/test/Parser/c2x-auto.c @@ -0,0 +1,132 @@ +// RUN: %clang_cc1 -fsyntax-only -verify=expected,c23 -std=c23 %s +// RUN: %clang_cc1 -fsyntax-only -verify=expected,c17 -std=c17 %s + +#define AUTO_MACRO(_NAME, ARG, ARG2, ARG3) \ +auto _NAME = ARG + (ARG2 / ARG3); + +struct S { + int a; + auto b; // c23-error {{'auto' not allowed in struct member}} \ + c17-error {{type name does not allow storage class to be specified}} \ + c17-error {{type specifier missing, defaults to 'int'; ISO C99 and later do not support implicit int}} + union { + char c; + auto smth; // c23-error {{'auto' not allowed in union member}} \ + c17-error {{type name does not allow storage class to be specified}} \ + c17-error {{type specifier missing, defaults to 'int'; ISO C99 and later do not support implicit int}} + } u; +}; + +enum E : auto { // c23-error {{'auto' not allowed here}} \ + c17-error {{expected a type}} \ + c17-error {{type name does not allow storage class to be specified}} + One, + Two, + Tree, +}; + +auto basic_usage(auto auto) { // c23-error {{'auto' not allowed in function prototype}} \ + c23-error {{'auto' not allowed in function return type}} \ + c23-error {{cannot combine with previous 'auto' declaration specifier}} \ + c17-error {{invalid storage class specifier in function declarator}} \ + c17-error {{illegal storage class on function}} \ + c17-warning {{duplicate 'auto' declaration specifier}} \ + c17-warning {{omitting the parameter name in a function definition is a C23 extension}} \ + c17-error {{type specifier missing, defaults to 'int'; ISO C99 and later do not support implicit int}} \ + c17-error {{type specifier missing, defaults to 'int'; ISO C99 and later do not support implicit int}} + + auto = 4; // expected-error {{expected identifier or '('}} + + auto a = 4; // c17-error {{type specifier missing, defaults to 'int'; ISO C99 and later do not support implicit int}} + + auto auto aa = 12; // c23-error {{cannot combine with previous 'auto' declaration specifier}} \ + c17-warning {{duplicate 'auto' declaration specifier}} \ + c17-error {{type specifier missing, defaults to 'int'; ISO C99 and later do not support implicit int}} + + auto b[4]; // c23-error {{'auto' not allowed in array declaration}} \ + c17-error {{type specifier missing, defaults to 'int'; ISO C99 and later do not support implicit int}} + + auto array[auto]; // expected-error {{expected expression}} \ + c23-error {{declaration of variable 'array' with deduced type 'auto' requires an initializer}} \ + c17-error {{type specifier missing, defaults to 'int'; ISO C99 and later do not support implicit int}} + + AUTO_MACRO(auto, 1, 2, 3); // c23-error {{cannot combine with previous 'auto' declaration specifier}} \ + expected-error {{expected identifier or '('}} \ + c17-warning {{duplicate 'auto' declaration specifier}} + + auto c = (auto)a; // expected-error {{expected expression}} \ + c17-error {{type specifier missing, defaults to 'int'; ISO C99 and later do not support implicit int}} + + auto ci = (auto){12}; // expected-error {{expected expression}} \ + c17-error {{type specifier missing, defaults to 'int'; ISO C99 and later do not support implicit int}} + + int auto_cxx_decl = auto(0); // expected-error {{expected expression}} + + return c; +} + +void structs(void) { + struct s_auto { auto a; }; // c23-error {{'auto' not allowed in struct member}} \ + c17-error {{type name does not allow storage class to be specified}} \ + c17-error {{type specifier missing, defaults to 'int'; ISO C99 and later do not support implicit int}} + + // FIXME: this should end up being rejected when we implement underspecified + // declarations in N3006. + auto s_int = (struct { int a; } *)0; // c17-error {{incompatible pointer to integer conversion initializing 'int' with an expression of type}} \ + c17-error {{type specifier missing, defaults to 'int'; ISO C99 and later do not support implicit int}} + + typedef auto auto_type; // c23-error {{'auto' not allowed in typedef}} \ + c17-error {{cannot combine with previous 'typedef' declaration specifier}} \ + c17-error {{type specifier missing, defaults to 'int'; ISO C99 and later do not support implicit int}} +} + +void sizeof_alignas(void) { + auto auto_size = sizeof(auto); // expected-error {{expected expression}} \ + c17-error {{type specifier missing, defaults to 'int'; ISO C99 and later do not support implicit int}} +} + +void generic_alignof_alignas(void) { + int g; + _Generic(g, auto : 0); // c23-error {{'auto' not allowed here}} \ + c17-error {{expected a type}} \ + c17-error {{type name does not allow storage class to be specified}} + + _Alignof(auto); // expected-error {{expected expression}} \ + expected-warning {{'_Alignof' applied to an expression is a GNU extension}} + + _Alignas(auto); // expected-error {{expected expression}} \ + expected-warning {{declaration does not declare anything}} +} + +void function_designators(void) { + extern auto auto_ret_func(void); // c23-error {{'auto' not allowed in function return type}} \ + c17-error {{cannot combine with previous 'extern' declaration specifier}} \ + c17-error {{type specifier missing, defaults to 'int'; ISO C99 and later do not support implicit int}} + + extern void auto_param_func(auto); // c23-error {{'auto' not allowed in function prototype}} \ + c17-error {{invalid storage class specifier in function declarator}} \ + c17-error {{type specifier missing, defaults to 'int'; ISO C99 and later do not support implicit int}} + + auto (auto_ret_func)(void); // c23-error {{'auto' not allowed in function return type}} \ + c17-error {{illegal storage class on function}} \ + c17-error {{type specifier missing, defaults to 'int'; ISO C99 and later do not support implicit int}} + + void (auto_param_func)(auto); // c23-error {{'auto' not allowed in function prototype}} \ + c17-error {{invalid storage class specifier in function declarator}} \ + c17-error {{type specifier missing, defaults to 'int'; ISO C99 and later do not support implicit int}} +} + +void atomic(void) { + _Atomic(auto) atom1 = 12; // c23-error {{'auto' not allowed here}} \ + c23-error {{a type specifier is required for all declarations}} \ + c17-error {{expected a type}} \ + c17-error {{type name does not allow storage class to be specified}} \ + c17-error {{type specifier missing, defaults to 'int'; ISO C99 and later do not support implicit int}} + + _Atomic auto atom2 = 12; // c23-error {{_Atomic cannot be applied to type 'auto' in C23}} \ + c17-error {{type specifier missing, defaults to 'int'; ISO C99 and later do not support implicit int}} +} + +void attributes(void) { + auto ident [[clang::annotate("this works")]] = 12; // c17-error {{type specifier missing, defaults to 'int'; ISO C99 and later do not support implicit int}} +} diff --git a/clang/test/Preprocessor/predefined-macros.c b/clang/test/Preprocessor/predefined-macros.c index d77b699674af4e..c4a9672f0814aa 100644 --- a/clang/test/Preprocessor/predefined-macros.c +++ b/clang/test/Preprocessor/predefined-macros.c @@ -290,3 +290,20 @@ // RUN: -fcuda-is-device -fgpu-default-stream=per-thread \ // RUN: | FileCheck -match-full-lines %s --check-prefix=CHECK-PTH // CHECK-PTH: #define HIP_API_PER_THREAD_DEFAULT_STREAM 1 + +// RUN: %clang_cc1 %s -E -dM -o - -x hip --hipstdpar -triple x86_64-unknown-linux-gnu \ +// RUN: | FileCheck -match-full-lines %s --check-prefix=CHECK-HIPSTDPAR +// CHECK-HIPSTDPAR: #define __HIPSTDPAR__ 1 +// CHECK-HIPSTDPAR-NOT: #define __HIPSTDPAR_INTERPOSE_ALLOC__ 1 + +// RUN: %clang_cc1 %s -E -dM -o - -x hip --hipstdpar --hipstdpar-interpose-alloc \ +// RUN: -triple x86_64-unknown-linux-gnu | FileCheck -match-full-lines %s \ +// RUN: --check-prefix=CHECK-HIPSTDPAR-INTERPOSE +// CHECK-HIPSTDPAR-INTERPOSE: #define __HIPSTDPAR_INTERPOSE_ALLOC__ 1 +// CHECK-HIPSTDPAR-INTERPOSE: #define __HIPSTDPAR__ 1 + +// RUN: %clang_cc1 %s -E -dM -o - -x hip --hipstdpar --hipstdpar-interpose-alloc \ +// RUN: -triple amdgcn-amd-amdhsa -fcuda-is-device | FileCheck -match-full-lines \ +// RUN: %s --check-prefix=CHECK-HIPSTDPAR-INTERPOSE-DEV-NEG +// CHECK-HIPSTDPAR-INTERPOSE-DEV-NEG: #define __HIPSTDPAR__ 1 +// CHECK-HIPSTDPAR-INTERPOSE-DEV-NEG-NOT: #define __HIPSTDPAR_INTERPOSE_ALLOC__ 1 \ No newline at end of file diff --git a/clang/test/Preprocessor/riscv-target-features.c b/clang/test/Preprocessor/riscv-target-features.c index 4dd83cfa0620b9..242197e3f129a3 100644 --- a/clang/test/Preprocessor/riscv-target-features.c +++ b/clang/test/Preprocessor/riscv-target-features.c @@ -1001,13 +1001,13 @@ // RUN: -o - | FileCheck --check-prefix=CHECK-ZACAS-EXT %s // CHECK-ZACAS-EXT: __riscv_zacas 1000000{{$}} -// RUN: %clang --target=riscv32-unknown-linux-gnu -menable-experimental-extensions \ -// RUN: -march=rv32izfa0p2 -x c -E -dM %s \ +// RUN: %clang --target=riscv32-unknown-linux-gnu \ +// RUN: -march=rv32izfa -x c -E -dM %s \ // RUN: -o - | FileCheck --check-prefix=CHECK-ZFA-EXT %s -// RUN: %clang --target=riscv64-unknown-linux-gnu -menable-experimental-extensions \ -// RUN: -march=rv64izfa0p2 -x c -E -dM %s \ +// RUN: %clang --target=riscv64-unknown-linux-gnu \ +// RUN: -march=rv64izfa -x c -E -dM %s \ // RUN: -o - | FileCheck --check-prefix=CHECK-ZFA-EXT %s -// CHECK-ZFA-EXT: __riscv_zfa 2000{{$}} +// CHECK-ZFA-EXT: __riscv_zfa 1000000{{$}} // RUN: %clang --target=riscv32 -menable-experimental-extensions \ // RUN: -march=rv32izfbfmin0p8 -x c -E -dM %s \ diff --git a/clang/test/Sema/attr-counted-by.c b/clang/test/Sema/attr-counted-by.c new file mode 100644 index 00000000000000..28c76ce74118b8 --- /dev/null +++ b/clang/test/Sema/attr-counted-by.c @@ -0,0 +1,42 @@ +// RUN: %clang_cc1 -fstrict-flex-arrays=3 -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 {{field 'bork' in 'counted_by' not found}} +}; + +struct not_found_suggest { + int bork; // expected-note {{'bork' declared here}} + struct bar *fam[] __counted_by(blork); // expected-error {{field 'blork' in 'counted_by' not found; did you mean 'bork'?}} +}; + +int global; // expected-note {{variable 'global' is declared here}} + +struct found_outside_of_struct { + int bork; + struct bar *fam[] __counted_by(global); // expected-error {{field 'global' in 'counted_by' is not found in struct}} +}; + +struct self_referrential { + int bork; + struct bar *self[] __counted_by(self); // expected-error {{field 'self' in 'counted_by' cannot refer to the flexible array}} +}; + +struct non_int { + double non_integer; // expected-error {{field 'non_integer' in 'counted_by' is not a non-boolean integer type}} + struct bar *fam[] __counted_by(non_integer); // expected-note {{field 'non_integer' declared here}} +}; + +struct array_of_ints { + int non_integer[2]; // expected-error {{field 'non_integer' in 'counted_by' is not a non-boolean integer type}} + struct bar *fam[] __counted_by(non_integer); // expected-note {{field 'non_integer' declared here}} +}; + +struct not_a_fam { + double non_integer; + struct bar *non_fam __counted_by(non_integer); // expected-error {{'counted_by' only applies to flexible array members}} +}; diff --git a/clang/test/Sema/attr-target-clones-aarch64.c b/clang/test/Sema/attr-target-clones-aarch64.c index dd8e72c421b135..9adabf87732130 100644 --- a/clang/test/Sema/attr-target-clones-aarch64.c +++ b/clang/test/Sema/attr-target-clones-aarch64.c @@ -1,6 +1,6 @@ // RUN: %clang_cc1 -triple aarch64-linux-gnu -fsyntax-only -verify %s -void __attribute__((target_clones("fp16+sve2-aes", "sb+sve2-sha3"))) no_def(void); +void __attribute__((target_clones("fp16+sve2-aes", "sb+sve2-sha3+rcpc3"))) no_def(void); // expected-warning@+1 {{unsupported 'default' in the 'target_clones' attribute string; 'target_clones' attribute ignored}} void __attribute__((target_clones("default+sha3"))) warn1(void); diff --git a/clang/test/Sema/builtins-x86.c b/clang/test/Sema/builtins-x86.c index 0882c80514ae9c..cbaf7bcde871e1 100644 --- a/clang/test/Sema/builtins-x86.c +++ b/clang/test/Sema/builtins-x86.c @@ -22,19 +22,19 @@ void call_x86_32_builtins(void) { } __m128 test__builtin_ia32_cmpps(__m128 __a, __m128 __b) { - return __builtin_ia32_cmpps(__a, __b, 32); // expected-error {{argument value 32 is outside the valid range [0, 7]}} + return __builtin_ia32_cmpps(__a, __b, 32); // expected-error {{argument value 32 is outside the valid range [0, 31]}} } __m128d test__builtin_ia32_cmppd(__m128d __a, __m128d __b) { - return __builtin_ia32_cmppd(__a, __b, 32); // expected-error {{argument value 32 is outside the valid range [0, 7]}} + return __builtin_ia32_cmppd(__a, __b, 32); // expected-error {{argument value 32 is outside the valid range [0, 31]}} } __m128 test__builtin_ia32_cmpss(__m128 __a, __m128 __b) { - return __builtin_ia32_cmpss(__a, __b, 32); // expected-error {{argument value 32 is outside the valid range [0, 7]}} + return __builtin_ia32_cmpss(__a, __b, 32); // expected-error {{argument value 32 is outside the valid range [0, 31]}} } __m128d test__builtin_ia32_cmpsd(__m128d __a, __m128d __b) { - return __builtin_ia32_cmpsd(__a, __b, 32); // expected-error {{argument value 32 is outside the valid range [0, 7]}} + return __builtin_ia32_cmpsd(__a, __b, 32); // expected-error {{argument value 32 is outside the valid range [0, 31]}} } __mmask16 test__builtin_ia32_cmpps512_mask(__m512 __a, __m512 __b) { diff --git a/clang/test/Sema/c2x-auto.c b/clang/test/Sema/c2x-auto.c new file mode 100644 index 00000000000000..916c179adcf318 --- /dev/null +++ b/clang/test/Sema/c2x-auto.c @@ -0,0 +1,137 @@ +// RUN: %clang_cc1 -std=c2x -verify -pedantic -Wno-comments %s + +void test_basic_types(void) { + auto undefined; // expected-error {{declaration of variable 'undefined' with deduced type 'auto' requires an initializer}} + auto auto_int = 4; + auto auto_long = 4UL; + signed auto a = 1L; // expected-error {{'auto' cannot be signed or unsigned}} + + _Static_assert(_Generic(auto_int, int : 1)); + _Static_assert(_Generic(auto_long, unsigned long : 1)); +} + +void test_complex_types(void) { + _Complex auto i = 12.0; // expected-error {{'_Complex auto' is invalid}} +} + +void test_gnu_extensions(void) { + auto t = ({ // expected-warning {{use of GNU statement expression extension}} + auto b = 12; + b; + }); + _Static_assert(_Generic(t, int : 1)); +} + +void test_sizeof_typeof(void) { + auto auto_size = sizeof(auto); // expected-error {{expected expression}} + typeof(auto) tpof = 4; // expected-error {{expected expression}} +} + +void test_casts(void) { + auto int_cast = (int)(4 + 3); + auto double_cast = (double)(1 / 3); + auto long_cast = (long)(4UL + 3UL); + auto auto_cast = (auto)(4 + 3); // expected-error {{expected expression}} + + _Static_assert(_Generic(int_cast, int : 1)); + _Static_assert(_Generic(double_cast, double : 1)); + _Static_assert(_Generic(long_cast, long : 1)); +} + +void test_compound_literral(void) { + auto int_cl = (int){13}; + auto double_cl = (double){2.5}; + auto array[] = { 1, 2, 3 }; // expected-error {{cannot use 'auto' with array in C}} + + auto auto_cl = (auto){13}; // expected-error {{expected expression}} + + _Static_assert(_Generic(int_cl, int : 1)); + _Static_assert(_Generic(double_cl, double : 1)); +} + +void test_array_pointers(void) { + double array[3] = { 0 }; + auto a = array; + auto b = &array; + + _Static_assert(_Generic(array, double * : 1)); + _Static_assert(_Generic(a, double * : 1)); + _Static_assert(_Generic(b, double (*)[3] : 1)); +} + +void test_typeof() { + int typeof_target(); + auto result = (typeof(typeof_target())){12}; + + _Static_assert(_Generic(result, int : 1)); +} + +void test_qualifiers(const int y) { + const auto a = 12; + auto b = y; + static auto c = 1UL; + int* pa = &a; // expected-warning {{initializing 'int *' with an expression of type 'const int *' discards qualifiers}} + const int* pb = &b; + int* pc = &c; // expected-warning {{incompatible pointer types initializing 'int *' with an expression of type 'unsigned long *'}} + + _Static_assert(_Generic(a, int : 1)); + _Static_assert(_Generic(b, int : 1)); + _Static_assert(_Generic(c, unsigned long : 1)); + _Static_assert(_Generic(pa, int * : 1)); + _Static_assert(_Generic(pb, const int * : 1)); + _Static_assert(_Generic(pc, int * : 1)); +} + +void test_strings(void) { + auto str = "this is a string"; + auto str2[] = "this is a string"; // expected-warning {{type inference of a declaration other than a plain identifier with optional trailing attributes is a Clang extension}} + auto (str3) = "this is a string"; + auto (((str4))) = "this is a string"; + + _Static_assert(_Generic(str, char * : 1)); + _Static_assert(_Generic(str2, char * : 1)); + _Static_assert(_Generic(str3, char * : 1)); + _Static_assert(_Generic(str4, char * : 1)); +} + +void test_pointers(void) { + auto a = 12; + auto *ptr = &a; // expected-warning {{type inference of a declaration other than a plain identifier with optional trailing attributes is a Clang extension}} + auto *str = "this is a string"; // expected-warning {{type inference of a declaration other than a plain identifier with optional trailing attributes is a Clang extension}} + const auto *str2 = "this is a string"; // expected-warning {{type inference of a declaration other than a plain identifier with optional trailing attributes is a Clang extension}} + auto *b = &a; // expected-warning {{type inference of a declaration other than a plain identifier with optional trailing attributes is a Clang extension}} + *b = &a; // expected-error {{incompatible pointer to integer conversion assigning to 'int' from 'int *'; remove &}} + auto nptr = nullptr; + + _Static_assert(_Generic(a, int : 1)); + _Static_assert(_Generic(ptr, int * : 1)); + _Static_assert(_Generic(str, char * : 1)); + _Static_assert(_Generic(str2, const char * : 1)); + _Static_assert(_Generic(b, int * : 1)); + _Static_assert(_Generic(nptr, typeof(nullptr) : 1)); +} + +void test_prototypes(void) { + extern void foo(int a, int array[({ auto x = 12; x;})]); // expected-warning {{use of GNU statement expression extension}} +} + +void test_scopes(void) { + double a = 7; + double b = 9; + { + auto a = a * a; // expected-error {{variable 'a' declared with deduced type 'auto' cannot appear in its own initializer}} \ + expected-error {{variable 'a' declared with deduced type 'auto' cannot appear in its own initializer}} + } + { + auto b = a * a; + auto a = b; + + _Static_assert(_Generic(b, double : 1)); + _Static_assert(_Generic(a, double : 1)); + } +} + +[[clang::overloadable]] auto test(auto x) { // expected-error {{'auto' not allowed in function prototype}} \ + expected-error {{'auto' not allowed in function return type}} + return x; +} diff --git a/clang/test/Sema/fixed-enum.c b/clang/test/Sema/fixed-enum.c index c77f5b0cbe79c5..954ff8c452b80c 100644 --- a/clang/test/Sema/fixed-enum.c +++ b/clang/test/Sema/fixed-enum.c @@ -4,13 +4,18 @@ // RUN: %clang_cc1 -Weverything -std=c11 -xc -DC11 -verify %s // RUN: %clang_cc1 -pedantic -std=c11 -xc -DC11 -verify %s // RUN: %clang_cc1 -Weverything -std=c11 -xc -fms-extensions -DMS -verify %s +// RUN: %clang_cc1 -Weverything -std=c2x -xc -DC23 -verify %s +// RUN: %clang_cc1 -pedantic -std=c2x -xc -DC23 -verify %s +// RUN: %clang_cc1 -Weverything -std=c23 -xc -DC23 -verify %s +// RUN: %clang_cc1 -pedantic -std=c23 -xc -DC23 -verify %s +// RUN: %clang_cc1 -Weverything -std=c23 -xc -fms-extensions -DC23 -verify %s enum X : int {e}; #if defined(CXX11) // expected-warning@-2{{enumeration types with a fixed underlying type are incompatible with C++98}} #elif defined(CXX03) // expected-warning@-4{{enumeration types with a fixed underlying type are a C++11 extension}} -#elif defined(OBJC) +#elif defined(OBJC) || defined(C23) // No diagnostic #elif defined(C11) // expected-warning@-8{{enumeration types with a fixed underlying type are a Clang extension}} @@ -21,19 +26,19 @@ enum X : int {e}; // Don't warn about the forward declaration in any language mode. enum Fwd : int; enum Fwd : int { e2 }; -#ifndef OBJC +#if !defined(OBJC) && !defined(C23) // expected-warning@-3 {{enumeration types with a fixed underlying type}} // expected-warning@-3 {{enumeration types with a fixed underlying type}} #endif // Always error on the incompatible redeclaration. enum BadFwd : int; -#ifndef OBJC +#if !defined(OBJC) && !defined(C23) // expected-warning@-2 {{enumeration types with a fixed underlying type}} #endif // expected-note@-4 {{previous declaration is here}} enum BadFwd : char { e3 }; -#ifndef OBJC +#if !defined(OBJC) && !defined(C23) // expected-warning@-2 {{enumeration types with a fixed underlying type}} #endif // expected-error@-4 {{enumeration redeclared with different underlying type 'char' (was 'int')}} diff --git a/clang/test/SemaCXX/attr-target-version.cpp b/clang/test/SemaCXX/attr-target-version.cpp index da24503f775f5b..2e262cda367749 100644 --- a/clang/test/SemaCXX/attr-target-version.cpp +++ b/clang/test/SemaCXX/attr-target-version.cpp @@ -5,6 +5,7 @@ void __attribute__((target_version("vmull"))) wrong_tv(void); void __attribute__((target_version("dotprod"))) no_def(void); void __attribute__((target_version("rdm+fp"))) no_def(void); +void __attribute__((target_version("rcpc3"))) no_def(void); // expected-error@+1 {{no matching function for call to 'no_def'}} void foo(void) { no_def(); } diff --git a/clang/test/SemaCXX/constant-expression-cxx1z.cpp b/clang/test/SemaCXX/constant-expression-cxx1z.cpp index 9335626a5c90a4..c0766f70cf8815 100644 --- a/clang/test/SemaCXX/constant-expression-cxx1z.cpp +++ b/clang/test/SemaCXX/constant-expression-cxx1z.cpp @@ -177,3 +177,16 @@ namespace LambdaCallOp { p(); } } + +// This used to crash due to an assertion failure, +// see gh#67690 +namespace { + struct C { + int x; + }; + + template void f() { + const auto &[c] = *p; + &c; // expected-warning {{expression result unused}} + } +} diff --git a/clang/test/SemaCXX/cxx2a-consteval.cpp b/clang/test/SemaCXX/cxx2a-consteval.cpp index a091fadfa3094b..38cc4be32a27c2 100644 --- a/clang/test/SemaCXX/cxx2a-consteval.cpp +++ b/clang/test/SemaCXX/cxx2a-consteval.cpp @@ -8,7 +8,7 @@ consteval int f1(int i) { return i; } -consteval constexpr int f2(int i) { +consteval constexpr int f2(int i) { //expected-error@-1 {{cannot combine}} return i; } @@ -195,7 +195,7 @@ auto ptr = ret1(0); struct A { consteval int f(int) { // expected-note@-1+ {{declared here}} - return 0; + return 0; } }; @@ -239,7 +239,7 @@ constexpr int f_c(int i) { int t = f(i); // expected-error@-1 {{is not a constant expression}} // expected-note@-2 {{function parameter}} - return f(0); + return f(0); } consteval int f_eval(int i) { @@ -675,7 +675,7 @@ Bar a; // expected-note {{in instantiation of member function 'issue_55601 struct constantDerp { // Can be used in a constant expression. - consteval constantDerp(int) {} + consteval constantDerp(int) {} consteval operator int() const { return 5; } }; Bar b; @@ -1175,4 +1175,28 @@ struct T { static constexpr auto xx = ns::foo(A{}); // expected-error {{cannot take address of consteval function 'foo' outside of an immediate invocation}} }; +} + +namespace GH65520 { + +consteval int bar (int i) { if (i != 1) return 1/0; return 0; } +// expected-note@-1{{division by zero}} + +void +g () +{ + int a_ok[bar(1)]; + int a_err[bar(3)]; // expected-error {{call to consteval function 'GH65520::bar' is not a constant expression}} \ + // expected-note {{in call to 'bar(3)'}} +} + +consteval int undefined(); // expected-note {{declared here}} + +consteval void immediate() { + int a [undefined()]; // expected-note {{undefined function 'undefined' cannot be used in a constant expression}} \ + // expected-error {{call to consteval function 'GH65520::undefined' is not a constant expression}} \ + // expected-error {{variable of non-literal type 'int[undefined()]' cannot be defined in a constexpr function before C++23}} +} + + } diff --git a/clang/test/SemaCXX/cxx2b-deducing-this-compat.cpp b/clang/test/SemaCXX/cxx2b-deducing-this-compat.cpp new file mode 100644 index 00000000000000..32406dfcac4257 --- /dev/null +++ b/clang/test/SemaCXX/cxx2b-deducing-this-compat.cpp @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++20 %s -verify + +struct S { + void f(this auto &a); // expected-error {{explicit object parameters are incompatible with C++ standards before C++2b}} +}; + +void f() { + (void)[](this auto&a){}; // expected-error {{explicit object parameters are incompatible with C++ standards before C++2b}} +} diff --git a/clang/test/SemaCXX/cxx2b-deducing-this-constexpr.cpp b/clang/test/SemaCXX/cxx2b-deducing-this-constexpr.cpp new file mode 100644 index 00000000000000..9dbea17dd2cae3 --- /dev/null +++ b/clang/test/SemaCXX/cxx2b-deducing-this-constexpr.cpp @@ -0,0 +1,74 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++2b %s -verify +// expected-no-diagnostics + +template +struct Wrap : Base { + +}; + +struct S { + constexpr int f(this const S&) { + return 42; + } + constexpr int f(this const S&, auto&&... args) { + return (args + ... + 0); + } + constexpr int operator[](this const S&) { + return 42; + } + constexpr int operator[](this const S& self, int i) { + return i + self.base; + } + constexpr int operator()(this const S&) { + return 42; + } + constexpr int operator()(this const S& self, int i) { + return self.base + i; + } + constexpr bool operator==(this const S& self, auto && test) { + return self.base == test; + }; + constexpr int operator*(this const S& self) { + return self.base + 22; + }; + constexpr operator Wrap (this const S& self) { + return Wrap{self}; + }; + constexpr int operator <<(this Wrap self, int i) { + return self.base+i; + } + + int base = 20; +}; + +consteval void test() { + constexpr S s; + static_assert(s.f() == 42); + static_assert(s[] == 42); + static_assert(s[22] == 42); + static_assert(s.f() == 42); + static_assert(s() == 42); + static_assert(s(22) == 42); + static_assert(s == 20); + static_assert(s != 0); + static_assert(*s == 42); + static_assert((s << 11) == 31); +} + +namespace GH68070 { + +constexpr auto f = [x = 3](this Self&& self) { + return x; +}; + +auto g = [x = 3](this Self&& self) { + return x; +}; + +int test() { + constexpr int a = f(); + static_assert(a == 3); + return f() + g(); +} + +} diff --git a/clang/test/SemaCXX/cxx2b-deducing-this-coro.cpp b/clang/test/SemaCXX/cxx2b-deducing-this-coro.cpp new file mode 100644 index 00000000000000..dfa50cb75acfab --- /dev/null +++ b/clang/test/SemaCXX/cxx2b-deducing-this-coro.cpp @@ -0,0 +1,57 @@ +// RUN: %clang_cc1 -std=c++2b %s -fsyntax-only -verify + +#include "Inputs/std-coroutine.h" + +struct S; +template +class coro_test { +public: + struct promise_type; + using handle = std::coroutine_handle; + struct promise_type { + promise_type(const promise_type&) = delete; // #copy-ctr + promise_type(T); // #candidate + coro_test get_return_object(); + std::suspend_never initial_suspend(); + std::suspend_never final_suspend() noexcept; + void return_void(); + void unhandled_exception(); + + + template + void* operator new(decltype(0zu) sz, Arg&&, Args&... args) { + static_assert(!__is_same(__decay(Arg), S), "Ok"); // expected-error 2{{Ok}} + } + + }; +private: + handle h; +}; + + +template +struct std::coroutine_traits, Ret, P...> { + using promise_type = coro_test::promise_type; + static_assert(!__is_same(Ret, S&), "Ok"); // expected-error{{static assertion failed due to requirement '!__is_same(S &, S &)': Ok}} +}; + + +struct S { + + coro_test ok(this S&, int) { + co_return; // expected-note {{in instantiation}} + } + + coro_test ok2(this const S&) { // expected-note {{in instantiation}} + co_return; + } + + coro_test ko(this const S&) { // expected-error {{no matching constructor for initialization of 'std::coroutine_traits, const S &>::promise_type'}} \ + // expected-note {{in instantiation}} \ + // FIXME: the message below is unhelpful but this is pre-existing + // expected-note@#candidate {{candidate constructor not viable: requires 1 argument, but 0 were provided}} \ + // expected-note@#copy-ctr {{candidate constructor not viable}} + co_return; + } + +}; diff --git a/clang/test/SemaCXX/cxx2b-deducing-this.cpp b/clang/test/SemaCXX/cxx2b-deducing-this.cpp new file mode 100644 index 00000000000000..cb83270752443a --- /dev/null +++ b/clang/test/SemaCXX/cxx2b-deducing-this.cpp @@ -0,0 +1,544 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++2b -Woverloaded-virtual %s -verify + + +// FIXME: can we improve these diagnostics? +void f(this); // expected-error{{variable has incomplete type 'void'}} \ + // expected-error{{invalid use of 'this' outside of a non-static member function}} + +void g(this auto); // expected-error{{an explicit object parameter cannot appear in a non-member function}} + +auto l1 = [] (this auto) static {}; // expected-error{{an explicit object parameter cannot appear in a static lambda}} +auto l2 = [] (this auto) mutable {}; // expected-error{{a lambda with an explicit object parameter cannot be mutable}} +auto l3 = [](this auto...){}; // expected-error {{the explicit object parameter cannot be a function parameter pack}} +auto l4 = [](int, this auto){}; // expected-error {{an explicit object parameter can only appear as the first parameter of the lambda}} + +struct S { + static void f(this auto); // expected-error{{an explicit object parameter cannot appear in a static function}} + virtual void f(this S); // expected-error{{an explicit object parameter cannot appear in a virtual function}} + + void g(this auto) const; // expected-error{{explicit object member function cannot have 'const' qualifier}} + void h(this auto) &; // expected-error{{explicit object member function cannot have '&' qualifier}} + void i(this auto) &&; // expected-error{{explicit object member function cannot have '&&' qualifier}} + void j(this auto) volatile; // expected-error{{explicit object member function cannot have 'volatile' qualifier}} + void k(this auto) __restrict; // expected-error{{explicit object member function cannot have '__restrict' qualifier}} + void l(this auto) _Nonnull; // expected-error{{explicit object member function cannot have '' qualifie}} + + + void variadic(this auto...); // expected-error{{the explicit object parameter cannot be a function parameter pack}} + void not_first(int, this auto); // expected-error {{an explicit object parameter can only appear as the first parameter of the function}} + + S(this auto); // expected-error {{an explicit object parameter cannot appear in a constructor}} + ~S(this S) {} // expected-error {{an explicit object parameter cannot appear in a destructor}} \ + // expected-error {{destructor cannot have any parameters}} +}; + +namespace Override { +struct A { + virtual void f(); // expected-note 2{{here}} + virtual void g(int); // expected-note {{here}} + virtual void h() const; // expected-note 5{{here}} +}; + +// CWG2553 +struct B : A { + int f(this B&, int); // expected-warning {{hides overloaded virtual function}} + int f(this B&); // expected-error {{an explicit object parameter cannot appear in a virtual function}} + int g(this B&); // expected-warning {{hides overloaded virtual function}} + int h(this B&); // expected-error {{an explicit object parameter cannot appear in a virtual function}} + int h(this B&&); // expected-error {{an explicit object parameter cannot appear in a virtual function}} + int h(this const B&&); // expected-error {{an explicit object parameter cannot appear in a virtual function}} + int h(this A&); // expected-error {{an explicit object parameter cannot appear in a virtual function}} + int h(this int); // expected-error {{an explicit object parameter cannot appear in a virtual function}} +}; +} + +namespace DefaultArgs { + struct Test { void f(this const auto& = Test{}); }; + // expected-error@-1 {{the explicit object parameter cannot have a default argument}} + auto L = [](this const auto& = Test{}){}; + // expected-error@-1 {{the explicit object parameter cannot have a default argument}} +} + +struct CannotUseThis { + int fun(); + int m; + void f(this auto) { + this->fun(); // expected-error{{invalid use of 'this' in a function with an explicit object parameter}} + fun(); // expected-error {{call to non-static member function without an object argument}} + m = 0; // expected-error {{invalid use of member 'm' in explicit object member function}} + } +}; + +struct CannotUseThisBase { + void foo(); + int n; + static int i; +}; + +struct CannotUseThisDerived : CannotUseThisBase { + void bar(this auto) { + foo(); // expected-error {{call to non-static member function without an object argument}} + n = 12; // expected-error {{invalid use of member 'n' in explicit object member function}} + i = 100; + } +}; + +namespace ThisInLambdaWithCaptures { + +struct Test { + Test(auto&&); +}; + +void test() { + + [i = 0](this Test) { }(); + // expected-error@-1 {{invalid explicit object parameter type 'ThisInLambdaWithCaptures::Test' in lambda with capture; the type must be the same as, or derived from, the lambda}} + + struct Derived; + auto ok = [i = 0](this const Derived&) {}; + auto ko = [i = 0](this const Test&) {}; + // expected-error@-1 {{invalid explicit object parameter type 'ThisInLambdaWithCaptures::Test' in lambda with capture; the type must be the same as, or derived from, the lambda}} + + struct Derived : decltype(ok){}; + Derived dok{ok}; + dok(); + + struct DerivedErr : decltype(ko){}; + DerivedErr dko{ko}; + dko(); + + auto alsoOk = [](this const Test &) {}; + alsoOk(); +} + +struct Frobble; +auto nothingIsOkay = [i = 0](this const Frobble &) {}; // expected-note {{candidate function not viable: requires 0 non-object arguments, but 1 was provided}} +struct Frobble {} f; +void test2() { + nothingIsOkay(f); // expected-error {{no matching function for call to object of type}} +} + +} + +struct Corresponding { + void a(this Corresponding&); // expected-note 2{{here}} + void a(); // expected-error{{cannot be redeclared}} + void a() &; // expected-error{{cannot be redeclared}} + void a(this Corresponding&, int); + void a(this Corresponding&, double); + + void b(this const Corresponding&); // expected-note 2{{here}} + void b() const; // expected-error{{cannot be redeclared}} + void b() const &; // expected-error{{cannot be redeclared}} + + void c(this Corresponding&&); // expected-note {{here}} + void c() &&; // expected-error{{cannot be redeclared}} + + void d(this Corresponding&); + void d(this Corresponding&&); + void d(this const Corresponding&); + void d(this const int&); + void d(this const int); + void d(this int); + + void e(this const Corresponding&&); // expected-note {{here}} + void e() const &&; // expected-error{{cannot be redeclared}} + +}; + +template +struct CorrespondingTpl { + void a(this CorrespondingTpl&); // expected-note 2{{here}} + void a(); // expected-error{{cannot be redeclared}} + void a() &; // expected-error{{cannot be redeclared}} + void a(this Corresponding&, int); + void a(this Corresponding&, double); + void a(long); + + + void b(this const CorrespondingTpl&); // expected-note 2{{here}} + void b() const; // expected-error{{cannot be redeclared}} + void b() const &; // expected-error{{cannot be redeclared}} + + void c(this CorrespondingTpl&&); // expected-note {{here}} + void c() &&; // expected-error{{cannot be redeclared}} + + void d(this Corresponding&); + void d(this Corresponding&&); + void d(this const Corresponding&); + void d(this const int&); + void d(this const int); + void d(this int); + + void e(this const CorrespondingTpl&&); // expected-note {{here}} + void e() const &&; // expected-error{{cannot be redeclared}} +}; + +struct C { + template + C(T){} +}; + +void func(int i) { + (void)[=](this auto&&) { return i; }(); + (void)[=](this const auto&) { return i; }(); + (void)[i](this C) { return i; }(); // expected-error{{invalid explicit object parameter type 'C'}} + (void)[=](this C) { return i; }(); // expected-error{{invalid explicit object parameter type 'C'}} + (void)[](this C) { return 42; }(); + auto l = [=](this auto&) {}; + struct D : decltype(l) {}; + D d{l}; + d(); +} + +void TestMutationInLambda() { + [i = 0](this auto &&){ i++; }(); + [i = 0](this auto){ i++; }(); + [i = 0](this const auto&){ i++; }(); + // expected-error@-1 {{cannot assign to a variable captured by copy in a non-mutable lambda}} +} + +struct Over_Call_Func_Example { + void a(); + void b() { + a(); // ok, (*this).a() + } + + void f(this const Over_Call_Func_Example&); // expected-note {{here}} + void g() const { + f(); // ok: (*this).f() + f(*this); // expected-error{{too many non-object arguments to function call}} + this->f(); // ok + } + + static void h() { + f(); // expected-error{{call to non-static member function without an object argument}} + f(Over_Call_Func_Example{}); // expected-error{{call to non-static member function without an object argument}} + Over_Call_Func_Example{}.f(); // ok + } + + void k(this int); + operator int() const; + void m(this const Over_Call_Func_Example& c) { + c.k(); // ok + } +}; + +struct AmbiguousConversion { + void f(this int); // expected-note {{candidate function}} + void f(this float); // expected-note {{candidate function}} + + operator int() const; + operator float() const; + + void test(this const AmbiguousConversion &s) { + s.f(); // expected-error {{call to member function 'f' is ambiguous}} + } +}; + +struct IntToShort { + void s(this short); + operator int() const; + void test(this const IntToShort &val) { + val.s(); + } +}; + +struct ShortToInt { + void s(this int); + operator short() const; + void test(this const ShortToInt &val) { + val.s(); + } +}; + +namespace arity_diagnostics { +struct S { + void f(this auto &&, auto, auto); // expected-note {{requires 2 non-object arguments, but 0 were provided}} + void g(this auto &&, auto, auto); // expected-note {{requires 2 non-object arguments, but 3 were provided}} + void h(this auto &&, int, int i = 0); // expected-note {{requires at least 1 non-object argument, but 0 were provided}} + void i(this S&&, int); // expected-note 2{{declared here}} +}; + +int test() { + void(*f)(S&&, int, int) = &S::f; + f(S{}, 1, 2); + f(S{}, 1); // expected-error {{too few arguments to function call, expected 3, have 2}} + f(S{}); // expected-error {{too few arguments to function call, expected 3, have 1}} + f(S{}, 1, 2, 3); //expected-error {{too many arguments to function call, expected 3, have 4}} + + S{}.f(1, 2); + S{}.f(); // expected-error{{no matching member function for call to 'f'}} + S{}.g(1,2,3); // expected-error {{no matching member function for call to 'g'}} + S{}.h(); // expected-error {{no matching member function for call to 'h'}} + S{}.i(); // expected-error {{too few non-object arguments to function call, expected 1, have 0}} + S{}.i(1, 2, 3); // expected-error {{too many non-object arguments to function call, expected 1, have 3}} +} + +} + +namespace AddressOf { + +struct s { + static void f(int); + void f(this auto &&) {} + void g(this s &&) {}; + + void test_qual() { + using F = void(s&&); + F* a = &f; // expected-error {{must explicitly qualify name of member function when taking its address}} + F* b = &g; // expected-error {{must explicitly qualify name of member function when taking its address}} + F* c = &s::f; + F* d = &s::g; + } +}; + +void test() { + using F = void(s&&); + F* a = &s::f; + F* b = &s::g; + a(s{}); + b(s{}); +} + +} + +namespace std { + struct strong_ordering { + int n; + constexpr operator int() const { return n; } + static const strong_ordering equal, greater, less; + }; + constexpr strong_ordering strong_ordering::equal = {0}; + constexpr strong_ordering strong_ordering::greater = {1}; + constexpr strong_ordering strong_ordering::less = {-1}; +} + +namespace operators_deduction { + +template +constexpr bool is_same = false; + +template +constexpr bool is_same = true; + +template