diff --git a/.github/workflows/libcxx-build-and-test.yaml b/.github/workflows/libcxx-build-and-test.yaml index cba8afbb54f0f..a061be3892523 100644 --- a/.github/workflows/libcxx-build-and-test.yaml +++ b/.github/workflows/libcxx-build-and-test.yaml @@ -37,7 +37,7 @@ jobs: stage1: if: github.repository_owner == 'llvm' runs-on: libcxx-self-hosted-linux - container: ghcr.io/llvm/libcxx-linux-builder:0fd6f684b9c84c32d6cbfd9742402e788b2879f1 + container: ghcr.io/llvm/libcxx-linux-builder:d8a0709b1090350a7fe3604d8ab78c7d62f10698 continue-on-error: false strategy: fail-fast: false @@ -74,7 +74,7 @@ jobs: stage2: if: github.repository_owner == 'llvm' runs-on: libcxx-self-hosted-linux - container: ghcr.io/llvm/libcxx-linux-builder:0fd6f684b9c84c32d6cbfd9742402e788b2879f1 + container: ghcr.io/llvm/libcxx-linux-builder:d8a0709b1090350a7fe3604d8ab78c7d62f10698 needs: [ stage1 ] continue-on-error: false strategy: @@ -162,7 +162,7 @@ jobs: - config: 'generic-msan' machine: libcxx-self-hosted-linux runs-on: ${{ matrix.machine }} - container: ghcr.io/llvm/libcxx-linux-builder:0fd6f684b9c84c32d6cbfd9742402e788b2879f1 + container: ghcr.io/llvm/libcxx-linux-builder:d8a0709b1090350a7fe3604d8ab78c7d62f10698 steps: - uses: actions/checkout@v4 - name: ${{ matrix.config }} diff --git a/bolt/lib/Core/BinaryContext.cpp b/bolt/lib/Core/BinaryContext.cpp index ac96b836ed579..f88e34b8e8962 100644 --- a/bolt/lib/Core/BinaryContext.cpp +++ b/bolt/lib/Core/BinaryContext.cpp @@ -1961,7 +1961,15 @@ void BinaryContext::printInstruction(raw_ostream &OS, const MCInst &Instruction, OS << "\tjit\t" << MIB->getTargetSymbol(Instruction)->getName() << " # ID: " << DynamicID; } else { - InstPrinter->printInst(&Instruction, 0, "", *STI, OS); + // If there are annotations on the instruction, the MCInstPrinter will fail + // to print the preferred alias as it only does so when the number of + // operands is as expected. See + // https://github.com/llvm/llvm-project/blob/782f1a0d895646c364a53f9dcdd6d4ec1f3e5ea0/llvm/lib/MC/MCInstPrinter.cpp#L142 + // Therefore, create a temporary copy of the Inst from which the annotations + // are removed, and print that Inst. + MCInst InstNoAnnot = Instruction; + MIB->stripAnnotations(InstNoAnnot); + InstPrinter->printInst(&InstNoAnnot, 0, "", *STI, OS); } if (MIB->isCall(Instruction)) { if (MIB->isTailCall(Instruction)) diff --git a/bolt/lib/Core/Relocation.cpp b/bolt/lib/Core/Relocation.cpp index 4e888a5b147ac..e9a9741bc3716 100644 --- a/bolt/lib/Core/Relocation.cpp +++ b/bolt/lib/Core/Relocation.cpp @@ -75,6 +75,8 @@ static bool isSupportedAArch64(uint64_t Type) { case ELF::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC: case ELF::R_AARCH64_TLSLE_ADD_TPREL_HI12: case ELF::R_AARCH64_TLSLE_ADD_TPREL_LO12_NC: + case ELF::R_AARCH64_TLSLE_MOVW_TPREL_G0: + case ELF::R_AARCH64_TLSLE_MOVW_TPREL_G0_NC: case ELF::R_AARCH64_LD64_GOT_LO12_NC: case ELF::R_AARCH64_TLSDESC_LD64_LO12: case ELF::R_AARCH64_TLSDESC_ADD_LO12: @@ -183,6 +185,8 @@ static size_t getSizeForTypeAArch64(uint64_t Type) { case ELF::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC: case ELF::R_AARCH64_TLSLE_ADD_TPREL_HI12: case ELF::R_AARCH64_TLSLE_ADD_TPREL_LO12_NC: + case ELF::R_AARCH64_TLSLE_MOVW_TPREL_G0: + case ELF::R_AARCH64_TLSLE_MOVW_TPREL_G0_NC: case ELF::R_AARCH64_LD64_GOT_LO12_NC: case ELF::R_AARCH64_TLSDESC_LD64_LO12: case ELF::R_AARCH64_TLSDESC_ADD_LO12: @@ -651,6 +655,8 @@ static bool isTLSAArch64(uint64_t Type) { case ELF::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC: case ELF::R_AARCH64_TLSLE_ADD_TPREL_HI12: case ELF::R_AARCH64_TLSLE_ADD_TPREL_LO12_NC: + case ELF::R_AARCH64_TLSLE_MOVW_TPREL_G0: + case ELF::R_AARCH64_TLSLE_MOVW_TPREL_G0_NC: case ELF::R_AARCH64_TLSDESC_LD64_LO12: case ELF::R_AARCH64_TLSDESC_ADD_LO12: case ELF::R_AARCH64_TLSDESC_CALL: @@ -716,6 +722,8 @@ static bool isPCRelativeAArch64(uint64_t Type) { case ELF::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC: case ELF::R_AARCH64_TLSLE_ADD_TPREL_HI12: case ELF::R_AARCH64_TLSLE_ADD_TPREL_LO12_NC: + case ELF::R_AARCH64_TLSLE_MOVW_TPREL_G0: + case ELF::R_AARCH64_TLSLE_MOVW_TPREL_G0_NC: case ELF::R_AARCH64_LD64_GOT_LO12_NC: case ELF::R_AARCH64_TLSDESC_LD64_LO12: case ELF::R_AARCH64_TLSDESC_ADD_LO12: diff --git a/bolt/lib/Rewrite/LinuxKernelRewriter.cpp b/bolt/lib/Rewrite/LinuxKernelRewriter.cpp index 03b414b71caca..0532468c237e0 100644 --- a/bolt/lib/Rewrite/LinuxKernelRewriter.cpp +++ b/bolt/lib/Rewrite/LinuxKernelRewriter.cpp @@ -123,6 +123,30 @@ inline raw_ostream &operator<<(raw_ostream &OS, const ORCState &E) { namespace { +/// Extension to DataExtractor that supports reading addresses stored in +/// PC-relative format. +class AddressExtractor : public DataExtractor { + uint64_t DataAddress; + +public: + AddressExtractor(StringRef Data, uint64_t DataAddress, bool IsLittleEndian, + uint8_t AddressSize) + : DataExtractor(Data, IsLittleEndian, AddressSize), + DataAddress(DataAddress) {} + + /// Extract 32-bit PC-relative address/pointer. + uint64_t getPCRelAddress32(Cursor &C) { + const uint64_t Base = DataAddress + C.tell(); + return Base + (int32_t)getU32(C); + } + + /// Extract 64-bit PC-relative address/pointer. + uint64_t getPCRelAddress64(Cursor &C) { + const uint64_t Base = DataAddress + C.tell(); + return Base + (int64_t)getU64(C); + } +}; + class LinuxKernelRewriter final : public MetadataRewriter { /// Information required for updating metadata referencing an instruction. struct InstructionFixup { @@ -423,13 +447,13 @@ Error LinuxKernelRewriter::processSMPLocks() { return createStringError(errc::executable_format_error, "bad size of .smp_locks section"); - DataExtractor DE = DataExtractor(SMPLocksSection->getContents(), - BC.AsmInfo->isLittleEndian(), - BC.AsmInfo->getCodePointerSize()); - DataExtractor::Cursor Cursor(0); + AddressExtractor AE(SMPLocksSection->getContents(), SectionAddress, + BC.AsmInfo->isLittleEndian(), + BC.AsmInfo->getCodePointerSize()); + AddressExtractor::Cursor Cursor(0); while (Cursor && Cursor.tell() < SectionSize) { const uint64_t Offset = Cursor.tell(); - const uint64_t IP = SectionAddress + Offset + (int32_t)DE.getU32(Cursor); + const uint64_t IP = AE.getPCRelAddress32(Cursor); // Consume the status of the cursor. if (!Cursor) @@ -499,20 +523,17 @@ Error LinuxKernelRewriter::readORCTables() { return createStringError(errc::executable_format_error, "ORC entries number mismatch detected"); - const uint64_t IPSectionAddress = ORCUnwindIPSection->getAddress(); - DataExtractor OrcDE = DataExtractor(ORCUnwindSection->getContents(), - BC.AsmInfo->isLittleEndian(), - BC.AsmInfo->getCodePointerSize()); - DataExtractor IPDE = DataExtractor(ORCUnwindIPSection->getContents(), - BC.AsmInfo->isLittleEndian(), - BC.AsmInfo->getCodePointerSize()); + DataExtractor OrcDE(ORCUnwindSection->getContents(), + BC.AsmInfo->isLittleEndian(), + BC.AsmInfo->getCodePointerSize()); + AddressExtractor IPAE( + ORCUnwindIPSection->getContents(), ORCUnwindIPSection->getAddress(), + BC.AsmInfo->isLittleEndian(), BC.AsmInfo->getCodePointerSize()); DataExtractor::Cursor ORCCursor(0); DataExtractor::Cursor IPCursor(0); uint64_t PrevIP = 0; for (uint32_t Index = 0; Index < NumORCEntries; ++Index) { - const uint64_t IP = - IPSectionAddress + IPCursor.tell() + (int32_t)IPDE.getU32(IPCursor); - + const uint64_t IP = IPAE.getPCRelAddress32(IPCursor); // Consume the status of the cursor. if (!IPCursor) return createStringError(errc::executable_format_error, @@ -856,15 +877,13 @@ Error LinuxKernelRewriter::validateORCTables() { if (!ORCUnwindIPSection) return Error::success(); - const uint64_t IPSectionAddress = ORCUnwindIPSection->getAddress(); - DataExtractor IPDE = DataExtractor(ORCUnwindIPSection->getOutputContents(), - BC.AsmInfo->isLittleEndian(), - BC.AsmInfo->getCodePointerSize()); - DataExtractor::Cursor IPCursor(0); + AddressExtractor IPAE( + ORCUnwindIPSection->getOutputContents(), ORCUnwindIPSection->getAddress(), + BC.AsmInfo->isLittleEndian(), BC.AsmInfo->getCodePointerSize()); + AddressExtractor::Cursor IPCursor(0); uint64_t PrevIP = 0; for (uint32_t Index = 0; Index < NumORCEntries; ++Index) { - const uint64_t IP = - IPSectionAddress + IPCursor.tell() + (int32_t)IPDE.getU32(IPCursor); + const uint64_t IP = IPAE.getPCRelAddress32(IPCursor); if (!IPCursor) return createStringError(errc::executable_format_error, "out of bounds while reading ORC IP table: %s", @@ -916,16 +935,14 @@ Error LinuxKernelRewriter::readStaticCalls() { "static call table size error"); const uint64_t SectionAddress = StaticCallSection->getAddress(); - DataExtractor DE(StaticCallSection->getContents(), - BC.AsmInfo->isLittleEndian(), - BC.AsmInfo->getCodePointerSize()); - DataExtractor::Cursor Cursor(StaticCallTableAddress - SectionAddress); + AddressExtractor AE(StaticCallSection->getContents(), SectionAddress, + BC.AsmInfo->isLittleEndian(), + BC.AsmInfo->getCodePointerSize()); + AddressExtractor::Cursor Cursor(StaticCallTableAddress - SectionAddress); uint32_t EntryID = 0; while (Cursor && Cursor.tell() < Stop->getAddress() - SectionAddress) { - const uint64_t CallAddress = - SectionAddress + Cursor.tell() + (int32_t)DE.getU32(Cursor); - const uint64_t KeyAddress = - SectionAddress + Cursor.tell() + (int32_t)DE.getU32(Cursor); + const uint64_t CallAddress = AE.getPCRelAddress32(Cursor); + const uint64_t KeyAddress = AE.getPCRelAddress32(Cursor); // Consume the status of the cursor. if (!Cursor) @@ -1027,18 +1044,15 @@ Error LinuxKernelRewriter::readExceptionTable() { return createStringError(errc::executable_format_error, "exception table size error"); - const uint64_t SectionAddress = ExceptionsSection->getAddress(); - DataExtractor DE(ExceptionsSection->getContents(), - BC.AsmInfo->isLittleEndian(), - BC.AsmInfo->getCodePointerSize()); - DataExtractor::Cursor Cursor(0); + AddressExtractor AE( + ExceptionsSection->getContents(), ExceptionsSection->getAddress(), + BC.AsmInfo->isLittleEndian(), BC.AsmInfo->getCodePointerSize()); + AddressExtractor::Cursor Cursor(0); uint32_t EntryID = 0; while (Cursor && Cursor.tell() < ExceptionsSection->getSize()) { - const uint64_t InstAddress = - SectionAddress + Cursor.tell() + (int32_t)DE.getU32(Cursor); - const uint64_t FixupAddress = - SectionAddress + Cursor.tell() + (int32_t)DE.getU32(Cursor); - const uint64_t Data = DE.getU32(Cursor); + const uint64_t InstAddress = AE.getPCRelAddress32(Cursor); + const uint64_t FixupAddress = AE.getPCRelAddress32(Cursor); + const uint64_t Data = AE.getU32(Cursor); // Consume the status of the cursor. if (!Cursor) @@ -1134,9 +1148,9 @@ Error LinuxKernelRewriter::readParaInstructions() { if (!ParavirtualPatchSection) return Error::success(); - DataExtractor DE = DataExtractor(ParavirtualPatchSection->getContents(), - BC.AsmInfo->isLittleEndian(), - BC.AsmInfo->getCodePointerSize()); + DataExtractor DE(ParavirtualPatchSection->getContents(), + BC.AsmInfo->isLittleEndian(), + BC.AsmInfo->getCodePointerSize()); uint32_t EntryID = 0; DataExtractor::Cursor Cursor(0); while (Cursor && !DE.eof(Cursor)) { @@ -1235,15 +1249,14 @@ Error LinuxKernelRewriter::readBugTable() { return createStringError(errc::executable_format_error, "bug table size error"); - const uint64_t SectionAddress = BugTableSection->getAddress(); - DataExtractor DE(BugTableSection->getContents(), BC.AsmInfo->isLittleEndian(), - BC.AsmInfo->getCodePointerSize()); - DataExtractor::Cursor Cursor(0); + AddressExtractor AE( + BugTableSection->getContents(), BugTableSection->getAddress(), + BC.AsmInfo->isLittleEndian(), BC.AsmInfo->getCodePointerSize()); + AddressExtractor::Cursor Cursor(0); uint32_t EntryID = 0; while (Cursor && Cursor.tell() < BugTableSection->getSize()) { const uint64_t Pos = Cursor.tell(); - const uint64_t InstAddress = - SectionAddress + Pos + (int32_t)DE.getU32(Cursor); + const uint64_t InstAddress = AE.getPCRelAddress32(Cursor); Cursor.seek(Pos + BUG_TABLE_ENTRY_SIZE); if (!Cursor) @@ -1402,23 +1415,20 @@ Error LinuxKernelRewriter::readAltInstructions() { Error LinuxKernelRewriter::tryReadAltInstructions(uint32_t AltInstFeatureSize, bool AltInstHasPadLen, bool ParseOnly) { - const uint64_t Address = AltInstrSection->getAddress(); - DataExtractor DE = DataExtractor(AltInstrSection->getContents(), - BC.AsmInfo->isLittleEndian(), - BC.AsmInfo->getCodePointerSize()); + AddressExtractor AE( + AltInstrSection->getContents(), AltInstrSection->getAddress(), + BC.AsmInfo->isLittleEndian(), BC.AsmInfo->getCodePointerSize()); + AddressExtractor::Cursor Cursor(0); uint64_t EntryID = 0; - DataExtractor::Cursor Cursor(0); - while (Cursor && !DE.eof(Cursor)) { - const uint64_t OrgInstAddress = - Address + Cursor.tell() + (int32_t)DE.getU32(Cursor); - const uint64_t AltInstAddress = - Address + Cursor.tell() + (int32_t)DE.getU32(Cursor); - const uint64_t Feature = DE.getUnsigned(Cursor, AltInstFeatureSize); - const uint8_t OrgSize = DE.getU8(Cursor); - const uint8_t AltSize = DE.getU8(Cursor); + while (Cursor && !AE.eof(Cursor)) { + const uint64_t OrgInstAddress = AE.getPCRelAddress32(Cursor); + const uint64_t AltInstAddress = AE.getPCRelAddress32(Cursor); + const uint64_t Feature = AE.getUnsigned(Cursor, AltInstFeatureSize); + const uint8_t OrgSize = AE.getU8(Cursor); + const uint8_t AltSize = AE.getU8(Cursor); // Older kernels may have the padlen field. - const uint8_t PadLen = AltInstHasPadLen ? DE.getU8(Cursor) : 0; + const uint8_t PadLen = AltInstHasPadLen ? AE.getU8(Cursor) : 0; if (!Cursor) return createStringError( @@ -1537,19 +1547,17 @@ Error LinuxKernelRewriter::readPCIFixupTable() { return createStringError(errc::executable_format_error, "PCI fixup table size error"); - const uint64_t Address = PCIFixupSection->getAddress(); - DataExtractor DE = DataExtractor(PCIFixupSection->getContents(), - BC.AsmInfo->isLittleEndian(), - BC.AsmInfo->getCodePointerSize()); + AddressExtractor AE( + PCIFixupSection->getContents(), PCIFixupSection->getAddress(), + BC.AsmInfo->isLittleEndian(), BC.AsmInfo->getCodePointerSize()); + AddressExtractor::Cursor Cursor(0); uint64_t EntryID = 0; - DataExtractor::Cursor Cursor(0); - while (Cursor && !DE.eof(Cursor)) { - const uint16_t Vendor = DE.getU16(Cursor); - const uint16_t Device = DE.getU16(Cursor); - const uint32_t Class = DE.getU32(Cursor); - const uint32_t ClassShift = DE.getU32(Cursor); - const uint64_t HookAddress = - Address + Cursor.tell() + (int32_t)DE.getU32(Cursor); + while (Cursor && !AE.eof(Cursor)) { + const uint16_t Vendor = AE.getU16(Cursor); + const uint16_t Device = AE.getU16(Cursor); + const uint32_t Class = AE.getU32(Cursor); + const uint32_t ClassShift = AE.getU32(Cursor); + const uint64_t HookAddress = AE.getPCRelAddress32(Cursor); if (!Cursor) return createStringError(errc::executable_format_error, @@ -1654,18 +1662,15 @@ Error LinuxKernelRewriter::readStaticKeysJumpTable() { "static keys jump table size error"); const uint64_t SectionAddress = StaticKeysJumpSection->getAddress(); - DataExtractor DE(StaticKeysJumpSection->getContents(), - BC.AsmInfo->isLittleEndian(), - BC.AsmInfo->getCodePointerSize()); - DataExtractor::Cursor Cursor(StaticKeysJumpTableAddress - SectionAddress); + AddressExtractor AE(StaticKeysJumpSection->getContents(), SectionAddress, + BC.AsmInfo->isLittleEndian(), + BC.AsmInfo->getCodePointerSize()); + AddressExtractor::Cursor Cursor(StaticKeysJumpTableAddress - SectionAddress); uint32_t EntryID = 0; while (Cursor && Cursor.tell() < Stop->getAddress() - SectionAddress) { - const uint64_t JumpAddress = - SectionAddress + Cursor.tell() + (int32_t)DE.getU32(Cursor); - const uint64_t TargetAddress = - SectionAddress + Cursor.tell() + (int32_t)DE.getU32(Cursor); - const uint64_t KeyAddress = - SectionAddress + Cursor.tell() + (int64_t)DE.getU64(Cursor); + const uint64_t JumpAddress = AE.getPCRelAddress32(Cursor); + const uint64_t TargetAddress = AE.getPCRelAddress32(Cursor); + const uint64_t KeyAddress = AE.getPCRelAddress64(Cursor); // Consume the status of the cursor. if (!Cursor) @@ -1859,21 +1864,18 @@ Error LinuxKernelRewriter::updateStaticKeysJumpTablePostEmit() { return Error::success(); const uint64_t SectionAddress = StaticKeysJumpSection->getAddress(); - DataExtractor DE(StaticKeysJumpSection->getOutputContents(), - BC.AsmInfo->isLittleEndian(), - BC.AsmInfo->getCodePointerSize()); - DataExtractor::Cursor Cursor(StaticKeysJumpTableAddress - SectionAddress); + AddressExtractor AE(StaticKeysJumpSection->getOutputContents(), + SectionAddress, BC.AsmInfo->isLittleEndian(), + BC.AsmInfo->getCodePointerSize()); + AddressExtractor::Cursor Cursor(StaticKeysJumpTableAddress - SectionAddress); const BinaryData *Stop = BC.getBinaryDataByName("__stop___jump_table"); uint32_t EntryID = 0; uint64_t NumShort = 0; uint64_t NumLong = 0; while (Cursor && Cursor.tell() < Stop->getAddress() - SectionAddress) { - const uint64_t JumpAddress = - SectionAddress + Cursor.tell() + (int32_t)DE.getU32(Cursor); - const uint64_t TargetAddress = - SectionAddress + Cursor.tell() + (int32_t)DE.getU32(Cursor); - const uint64_t KeyAddress = - SectionAddress + Cursor.tell() + (int64_t)DE.getU64(Cursor); + const uint64_t JumpAddress = AE.getPCRelAddress32(Cursor); + const uint64_t TargetAddress = AE.getPCRelAddress32(Cursor); + const uint64_t KeyAddress = AE.getPCRelAddress64(Cursor); // Consume the status of the cursor. if (!Cursor) diff --git a/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp b/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp index 7e08e5c81d26f..679c9774c767f 100644 --- a/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp +++ b/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp @@ -1449,6 +1449,8 @@ class AArch64MCPlusBuilder : public MCPlusBuilder { case ELF::R_AARCH64_TLSDESC_LD64_LO12: case ELF::R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21: case ELF::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC: + case ELF::R_AARCH64_TLSLE_MOVW_TPREL_G0: + case ELF::R_AARCH64_TLSLE_MOVW_TPREL_G0_NC: case ELF::R_AARCH64_MOVW_UABS_G0: case ELF::R_AARCH64_MOVW_UABS_G0_NC: case ELF::R_AARCH64_MOVW_UABS_G1: diff --git a/bolt/test/RISCV/call-annotations.s b/bolt/test/RISCV/call-annotations.s index ff99e0f1dfd84..f876544e214ca 100644 --- a/bolt/test/RISCV/call-annotations.s +++ b/bolt/test/RISCV/call-annotations.s @@ -16,13 +16,13 @@ f: // CHECK-LABEL: Binary Function "_start" after building cfg { // CHECK: auipc ra, f -// CHECK-NEXT: jalr ra, -0x4(ra) # Offset: 4 -// CHECK-NEXT: jal ra, f # Offset: 8 -// CHECK-NEXT: jal zero, f # TAILCALL # Offset: 12 +// CHECK-NEXT: jalr -0x4(ra) # Offset: 4 +// CHECK-NEXT: jal f # Offset: 8 +// CHECK-NEXT: j f # TAILCALL # Offset: 12 // CHECK-LABEL: Binary Function "long_tail" after building cfg { // CHECK: auipc t1, f -// CHECK-NEXT: jalr zero, -0x18(t1) # TAILCALL # Offset: 8 +// CHECK-NEXT: jr -0x18(t1) # TAILCALL # Offset: 8 // CHECK-LABEL: Binary Function "compressed_tail" after building cfg { // CHECK: jr a0 # TAILCALL # Offset: 0 diff --git a/bolt/test/RISCV/relax.s b/bolt/test/RISCV/relax.s index ec390ea76b5c7..74f049b8f8dd9 100644 --- a/bolt/test/RISCV/relax.s +++ b/bolt/test/RISCV/relax.s @@ -5,9 +5,9 @@ // RUN: llvm-objdump -d %t.bolt | FileCheck --check-prefix=OBJDUMP %s // CHECK: Binary Function "_start" after building cfg { -// CHECK: jal ra, near_f +// CHECK: jal near_f // CHECK-NEXT: auipc ra, far_f -// CHECK-NEXT: jalr ra, 0xc(ra) +// CHECK-NEXT: jalr 0xc(ra) // CHECK-NEXT: j near_f // CHECK: Binary Function "_start" after fix-riscv-calls { diff --git a/bolt/test/RISCV/reloc-branch.s b/bolt/test/RISCV/reloc-branch.s index 6a8b5a28e19d9..780d978f36f44 100644 --- a/bolt/test/RISCV/reloc-branch.s +++ b/bolt/test/RISCV/reloc-branch.s @@ -7,7 +7,7 @@ .p2align 1 // CHECK: Binary Function "_start" after building cfg { _start: -// CHECK: beq zero, zero, .Ltmp0 +// CHECK: beqz zero, .Ltmp0 beq zero, zero, 1f nop // CHECK: .Ltmp0 diff --git a/bolt/test/RISCV/reloc-jal.s b/bolt/test/RISCV/reloc-jal.s index ce54265fac05e..62a2f1dbea03a 100644 --- a/bolt/test/RISCV/reloc-jal.s +++ b/bolt/test/RISCV/reloc-jal.s @@ -14,7 +14,7 @@ f: .globl _start .p2align 1 _start: -// CHECK: jal ra, f +// CHECK: jal f jal ra, f ret .size _start, .-_start diff --git a/clang-tools-extra/clang-tidy/readability/ContainerSizeEmptyCheck.h b/clang-tools-extra/clang-tidy/readability/ContainerSizeEmptyCheck.h index acd8a6bfc50f5..3aa4bdc496194 100644 --- a/clang-tools-extra/clang-tidy/readability/ContainerSizeEmptyCheck.h +++ b/clang-tools-extra/clang-tidy/readability/ContainerSizeEmptyCheck.h @@ -18,10 +18,11 @@ namespace clang::tidy::readability { /// a call to `empty()`. /// /// The emptiness of a container should be checked using the `empty()` method -/// instead of the `size()` method. It shows clearer intent to use `empty()`. -/// Furthermore some containers may implement the `empty()` method but not -/// implement the `size()` method. Using `empty()` whenever possible makes it -/// easier to switch to another container in the future. +/// instead of the `size()`/`length()` method. It shows clearer intent to use +/// `empty()`. Furthermore some containers may implement the `empty()` method +/// but not implement the `size()` or `length()` method. Using `empty()` +/// whenever possible makes it easier to switch to another container in the +/// future. class ContainerSizeEmptyCheck : public ClangTidyCheck { public: ContainerSizeEmptyCheck(StringRef Name, ClangTidyContext *Context); diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/narrowing-conversions.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/narrowing-conversions.rst index 04260e75aa558..7cc0b2809b458 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/narrowing-conversions.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/narrowing-conversions.rst @@ -27,6 +27,40 @@ This check will flag: - All applications of binary operators with a narrowing conversions. For example: ``int i; i+= 0.1;``. +Arithmetic with smaller integer types than ``int`` trigger implicit conversions, +as explained under `"Integral Promotion" on cppreference.com +`_. +This check diagnoses more instances of narrowing than the compiler warning +`-Wconversion` does. The example below demonstrates this behavior. + +.. code-block:: c++ + + // The following function definition demonstrates usage of arithmetic with + // integer types smaller than `int` and how the narrowing conversion happens + // implicitly. + void computation(short argument1, short argument2) { + // Arithmetic written by humans: + short result = argument1 + argument2; + // Arithmetic actually performed by C++: + short result = static_cast(static_cast(argument1) + static_cast(argument2)); + } + + void recommended_resolution(short argument1, short argument2) { + short result = argument1 + argument2; + // ^ warning: narrowing conversion from 'int' to signed type 'short' is implementation-defined + + // The cppcoreguidelines recommend to resolve this issue by using the GSL + // in one of two ways. Either by a cast that throws if a loss of precision + // would occur. + short result = gsl::narrow(argument1 + argument2); + // Or it can be resolved without checking the result risking invalid results. + short result = gsl::narrow_cast(argument1 + argument2); + + // A classical `static_cast` will silence the warning as well if the GSL + // is not available. + short result = static_cast(argument1 + argument2); + } + Options ------- diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-type-vararg.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-type-vararg.cpp index 6792c7920dd11..3f73d1de333f4 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-type-vararg.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-type-vararg.cpp @@ -51,8 +51,8 @@ void my_printf(const char* format, ...) { int my_vprintf(const char* format, va_list arg ); // OK to declare function taking va_list -void ignoredBuiltinsTest() { - (void)__builtin_assume_aligned(0, 8); +void ignoredBuiltinsTest(void *ptr) { + (void)__builtin_assume_aligned(ptr, 8); (void)__builtin_constant_p(0); (void)__builtin_fpclassify(0, 0, 0, 0, 0, 0.f); (void)__builtin_isinf_sign(0.f); diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 29794f27d3005..a85ef60b7b58b 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -445,6 +445,10 @@ New Compiler Flags - The ``-Warray-compare-cxx26`` warning has been added to warn about array comparison starting from C++26, this warning is enabled as an error by default. +- '-fsanitize-merge' (default) and '-fno-sanitize-merge' have been added for + fine-grained control of which UBSan checks are allowed to be merged by the + backend (for example, -fno-sanitize-merge=bool,enum). + Deprecated Compiler Flags ------------------------- @@ -484,6 +488,8 @@ Removed Compiler Flags derivatives) is now removed, since it's no longer possible to suppress the diagnostic (see above). Users can expect an `unknown warning` diagnostic if it's still in use. +- The experimental flag '-ubsan-unique-traps' has been removed. It is + superseded by '-fno-sanitize-merge'. Attribute Changes in Clang -------------------------- @@ -700,6 +706,8 @@ Improvements to Clang's diagnostics return ptr + index < ptr; // warning } +- Fix -Wdangling false positives on conditional operators (#120206). + Improvements to Clang's time-trace ---------------------------------- @@ -850,6 +858,7 @@ Bug Fixes to C++ Support - Clang no longer rejects deleting a pointer of incomplete enumeration type. (#GH99278) - Fixed recognition of ``std::initializer_list`` when it's surrounded with ``extern "C++"`` and exported out of a module (which is the case e.g. in MSVC's implementation of ``std`` module). (#GH118218) +- Fixed a pack expansion issue in checking unexpanded parameter sizes. (#GH17042) Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -1199,6 +1208,8 @@ Sanitizers ``-fsanitize=type`` flag. This sanitizer detects violations of C/C++ type-based aliasing rules. +- Implemented ``-f[no-]sanitize-trap=local-bounds``, and ``-f[no-]sanitize-recover=local-bounds``. + Python Binding Changes ---------------------- - Fixed an issue that led to crashes when calling ``Type.get_exception_specification_kind``. diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h index 122118b8f3763..dfc562da88afe 100644 --- a/clang/include/clang-c/Index.h +++ b/clang/include/clang-c/Index.h @@ -2190,7 +2190,15 @@ enum CXCursorKind { */ CXCursor_OpenACCWaitConstruct = 327, - CXCursor_LastStmt = CXCursor_OpenACCWaitConstruct, + /** OpenACC init Construct. + */ + CXCursor_OpenACCInitConstruct = 328, + + /** OpenACC shutdown Construct. + */ + CXCursor_OpenACCShutdownConstruct = 329, + + CXCursor_LastStmt = CXCursor_OpenACCShutdownConstruct, /** * Cursor that represents the translation unit itself. diff --git a/clang/include/clang/AST/OpenACCClause.h b/clang/include/clang/AST/OpenACCClause.h index 51db58d484a25..b4747c68a1dfd 100644 --- a/clang/include/clang/AST/OpenACCClause.h +++ b/clang/include/clang/AST/OpenACCClause.h @@ -619,6 +619,20 @@ class OpenACCAsyncClause : public OpenACCClauseWithSingleIntExpr { SourceLocation EndLoc); }; +class OpenACCDeviceNumClause : public OpenACCClauseWithSingleIntExpr { + OpenACCDeviceNumClause(SourceLocation BeginLoc, SourceLocation LParenLoc, + Expr *IntExpr, SourceLocation EndLoc); + +public: + static bool classof(const OpenACCClause *C) { + return C->getClauseKind() == OpenACCClauseKind::DeviceNum; + } + static OpenACCDeviceNumClause *Create(const ASTContext &C, + SourceLocation BeginLoc, + SourceLocation LParenLoc, Expr *IntExpr, + SourceLocation EndLoc); +}; + /// Represents a 'collapse' clause on a 'loop' construct. This clause takes an /// integer constant expression 'N' that represents how deep to collapse the /// construct. It also takes an optional 'force' tag that permits intervening diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index d9a87b30062df..f5b32ed51698e 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -4076,6 +4076,10 @@ DEF_TRAVERSE_STMT(OpenACCWaitConstruct, { TRY_TO(TraverseStmt(E)); TRY_TO(VisitOpenACCClauseList(S->clauses())); }) +DEF_TRAVERSE_STMT(OpenACCInitConstruct, + { TRY_TO(VisitOpenACCClauseList(S->clauses())); }) +DEF_TRAVERSE_STMT(OpenACCShutdownConstruct, + { TRY_TO(VisitOpenACCClauseList(S->clauses())); }) // Traverse HLSL: Out argument expression DEF_TRAVERSE_STMT(HLSLOutArgExpr, {}) diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h index 83fafbabb1d46..07cb63956aed0 100644 --- a/clang/include/clang/AST/Stmt.h +++ b/clang/include/clang/AST/Stmt.h @@ -109,6 +109,18 @@ class alignas(void *) Stmt { //===--- Statement bitfields classes ---===// + enum { NumStmtBits = 9 }; + +#define STMT(CLASS, PARENT) +#define STMT_RANGE(BASE, FIRST, LAST) +#define LAST_STMT_RANGE(BASE, FIRST, LAST) \ + static_assert( \ + llvm::isInt(StmtClass::LAST##Class), \ + "The number of 'StmtClass'es is strictly bounded under two to " \ + "the power of 'NumStmtBits'"); +#define ABSTRACT_STMT(STMT) +#include "clang/AST/StmtNodes.inc" + class StmtBitfields { friend class ASTStmtReader; friend class ASTStmtWriter; @@ -116,9 +128,8 @@ class alignas(void *) Stmt { /// The statement class. LLVM_PREFERRED_TYPE(StmtClass) - unsigned sClass : 8; + unsigned sClass : NumStmtBits; }; - enum { NumStmtBits = 8 }; class NullStmtBitfields { friend class ASTStmtReader; diff --git a/clang/include/clang/AST/StmtOpenACC.h b/clang/include/clang/AST/StmtOpenACC.h index 093393a81be9c..e311eded5599b 100644 --- a/clang/include/clang/AST/StmtOpenACC.h +++ b/clang/include/clang/AST/StmtOpenACC.h @@ -592,5 +592,85 @@ class OpenACCWaitConstruct final return const_child_range(Begin, Begin + NumExprs); } }; + +// This class represents an 'init' construct, which has just a clause list. +class OpenACCInitConstruct final + : public OpenACCConstructStmt, + private llvm::TrailingObjects { + friend TrailingObjects; + OpenACCInitConstruct(unsigned NumClauses) + : OpenACCConstructStmt(OpenACCInitConstructClass, + OpenACCDirectiveKind::Init, SourceLocation{}, + SourceLocation{}, SourceLocation{}) { + std::uninitialized_value_construct( + getTrailingObjects(), + getTrailingObjects() + NumClauses); + setClauseList(MutableArrayRef(getTrailingObjects(), + NumClauses)); + } + OpenACCInitConstruct(SourceLocation Start, SourceLocation DirectiveLoc, + SourceLocation End, + ArrayRef Clauses) + : OpenACCConstructStmt(OpenACCInitConstructClass, + OpenACCDirectiveKind::Init, Start, DirectiveLoc, + End) { + std::uninitialized_copy(Clauses.begin(), Clauses.end(), + getTrailingObjects()); + setClauseList(MutableArrayRef(getTrailingObjects(), + Clauses.size())); + } + +public: + static bool classof(const Stmt *T) { + return T->getStmtClass() == OpenACCInitConstructClass; + } + static OpenACCInitConstruct *CreateEmpty(const ASTContext &C, + unsigned NumClauses); + static OpenACCInitConstruct *Create(const ASTContext &C, SourceLocation Start, + SourceLocation DirectiveLoc, + SourceLocation End, + ArrayRef Clauses); +}; + +// This class represents a 'shutdown' construct, which has just a clause list. +class OpenACCShutdownConstruct final + : public OpenACCConstructStmt, + private llvm::TrailingObjects { + friend TrailingObjects; + OpenACCShutdownConstruct(unsigned NumClauses) + : OpenACCConstructStmt(OpenACCShutdownConstructClass, + OpenACCDirectiveKind::Shutdown, SourceLocation{}, + SourceLocation{}, SourceLocation{}) { + std::uninitialized_value_construct( + getTrailingObjects(), + getTrailingObjects() + NumClauses); + setClauseList(MutableArrayRef(getTrailingObjects(), + NumClauses)); + } + OpenACCShutdownConstruct(SourceLocation Start, SourceLocation DirectiveLoc, + SourceLocation End, + ArrayRef Clauses) + : OpenACCConstructStmt(OpenACCShutdownConstructClass, + OpenACCDirectiveKind::Shutdown, Start, + DirectiveLoc, End) { + std::uninitialized_copy(Clauses.begin(), Clauses.end(), + getTrailingObjects()); + setClauseList(MutableArrayRef(getTrailingObjects(), + Clauses.size())); + } + +public: + static bool classof(const Stmt *T) { + return T->getStmtClass() == OpenACCShutdownConstructClass; + } + static OpenACCShutdownConstruct *CreateEmpty(const ASTContext &C, + unsigned NumClauses); + static OpenACCShutdownConstruct * + Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, + SourceLocation End, ArrayRef Clauses); +}; + } // namespace clang #endif // LLVM_CLANG_AST_STMTOPENACC_H diff --git a/clang/include/clang/AST/TextNodeDumper.h b/clang/include/clang/AST/TextNodeDumper.h index b6f16be7a5b98..5383b53fdc491 100644 --- a/clang/include/clang/AST/TextNodeDumper.h +++ b/clang/include/clang/AST/TextNodeDumper.h @@ -416,6 +416,8 @@ class TextNodeDumper void VisitOpenACCExitDataConstruct(const OpenACCExitDataConstruct *S); void VisitOpenACCHostDataConstruct(const OpenACCHostDataConstruct *S); void VisitOpenACCWaitConstruct(const OpenACCWaitConstruct *S); + void VisitOpenACCInitConstruct(const OpenACCInitConstruct *S); + void VisitOpenACCShutdownConstruct(const OpenACCShutdownConstruct *S); void VisitOpenACCAsteriskSizeExpr(const OpenACCAsteriskSizeExpr *S); void VisitEmbedExpr(const EmbedExpr *S); void VisitAtomicExpr(const AtomicExpr *AE); diff --git a/clang/include/clang/Analysis/FlowSensitive/SmartPointerAccessorCaching.h b/clang/include/clang/Analysis/FlowSensitive/SmartPointerAccessorCaching.h new file mode 100644 index 0000000000000..3e4016518eaac --- /dev/null +++ b/clang/include/clang/Analysis/FlowSensitive/SmartPointerAccessorCaching.h @@ -0,0 +1,63 @@ +//===-- SmartPointerAccessorCaching.h ---------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines utilities to help cache accessors for smart pointer +// like objects. +// +// These should be combined with CachedConstAccessorsLattice. +// Beyond basic const accessors, smart pointers may have the following two +// additional issues: +// +// 1) There may be multiple accessors for the same underlying object, e.g. +// `operator->`, `operator*`, and `get`. Users may use a mixture of these +// accessors, so the cache should unify them. +// +// 2) There may be non-const overloads of accessors. They are still safe to +// cache, as they don't modify the container object. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_SMARTPOINTERACCESSORCACHING_H +#define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_SMARTPOINTERACCESSORCACHING_H + +#include + +#include "clang/AST/Decl.h" +#include "clang/AST/Stmt.h" +#include "clang/ASTMatchers/ASTMatchers.h" + +namespace clang::dataflow { + +/// Matchers: +/// For now, these match on any class with an `operator*` or `operator->` +/// where the return types have a similar shape as std::unique_ptr +/// and std::optional. +/// +/// - `*` returns a reference to a type `T` +/// - `->` returns a pointer to `T` +/// - `get` returns a pointer to `T` +/// - `value` returns a reference `T` +/// +/// (1) The `T` should all match across the accessors (ignoring qualifiers). +/// +/// (2) The specific accessor used in a call isn't required to be const, +/// but the class must have a const overload of each accessor. +/// +/// For now, we don't have customization to ignore certain classes. +/// For example, if writing a ClangTidy check for `std::optional`, these +/// would also match `std::optional`. In order to have special handling +/// for `std::optional`, we assume the (Matcher, TransferFunction) case +/// with custom handling is ordered early so that these generic cases +/// do not trigger. +ast_matchers::StatementMatcher isSmartPointerLikeOperatorStar(); +ast_matchers::StatementMatcher isSmartPointerLikeOperatorArrow(); +ast_matchers::StatementMatcher isSmartPointerLikeValueMethodCall(); +ast_matchers::StatementMatcher isSmartPointerLikeGetMethodCall(); + +} // namespace clang::dataflow + +#endif // LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_SMARTPOINTERACCESSORCACHING_H diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index d67a81f8564a8..491bc83c1e129 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -3423,7 +3423,7 @@ def warn_typecheck_vector_element_sizes_not_equal : Warning< def err_ext_vector_component_exceeds_length : Error< "vector component access exceeds type %0">; def err_ext_vector_component_name_illegal : Error< - "illegal vector component name '%0'">; + "illegal vector component name %0">; def err_attribute_address_space_negative : Error< "address space is negative">; def err_attribute_address_space_too_high : Error< @@ -5863,10 +5863,10 @@ def err_pack_expansion_without_parameter_packs : Error< "pack expansion does not contain any unexpanded parameter packs">; def err_pack_expansion_length_conflict : Error< "pack expansion contains parameter packs %0 and %1 that have different " - "lengths (%2 vs. %3)">; + "lengths (%2 vs. %select{|at least }3%4))">; def err_pack_expansion_length_conflict_multilevel : Error< "pack expansion contains parameter pack %0 that has a different " - "length (%1 vs. %2) from outer parameter packs">; + "length (%1 vs. %select{|at least }2%3) from outer parameter packs">; def err_pack_expansion_length_conflict_partial : Error< "pack expansion contains parameter pack %0 that has a different " "length (at least %1 vs. %2) from outer parameter packs">; @@ -12324,6 +12324,8 @@ def warn_noderef_to_dereferenceable_pointer : Warning< def err_builtin_launder_invalid_arg : Error< "%select{non-pointer|function pointer|void pointer}0 argument to " "'__builtin_launder' is not allowed">; +def err_builtin_assume_aligned_invalid_arg : Error< + "non-pointer argument to '__builtin_assume_aligned' is not allowed">; def err_builtin_is_within_lifetime_invalid_arg : Error< "%select{non-|function }0pointer argument to '__builtin_is_within_lifetime' " @@ -12667,8 +12669,8 @@ def err_acc_int_expr_requires_integer def err_acc_int_expr_incomplete_class_type : Error<"OpenACC integer expression has incomplete class type %0">; def err_acc_int_expr_explicit_conversion - : Error<"OpenACC integer expression type %0 requires explicit conversion " - "to %1">; + : Error<"OpenACC integer expression requires explicit conversion " + "from %0 to %1">; def note_acc_int_expr_conversion : Note<"conversion to %select{integral|enumeration}0 type %1">; def err_acc_int_expr_multiple_conversions diff --git a/clang/include/clang/Basic/OpenACCClauses.def b/clang/include/clang/Basic/OpenACCClauses.def index c7ffac391e202..1b619bc0dfd4c 100644 --- a/clang/include/clang/Basic/OpenACCClauses.def +++ b/clang/include/clang/Basic/OpenACCClauses.def @@ -40,6 +40,7 @@ CLAUSE_ALIAS(PresentOrCreate, Create, true) VISIT_CLAUSE(Default) VISIT_CLAUSE(Delete) VISIT_CLAUSE(Detach) +VISIT_CLAUSE(DeviceNum) VISIT_CLAUSE(DevicePtr) VISIT_CLAUSE(DeviceType) CLAUSE_ALIAS(DType, DeviceType, false) diff --git a/clang/include/clang/Basic/StmtNodes.td b/clang/include/clang/Basic/StmtNodes.td index 6c7314b06d858..31280df93e4c6 100644 --- a/clang/include/clang/Basic/StmtNodes.td +++ b/clang/include/clang/Basic/StmtNodes.td @@ -313,6 +313,8 @@ def OpenACCEnterDataConstruct : StmtNode; def OpenACCExitDataConstruct : StmtNode; def OpenACCHostDataConstruct : StmtNode; def OpenACCWaitConstruct : StmtNode; +def OpenACCInitConstruct : StmtNode; +def OpenACCShutdownConstruct : StmtNode; // OpenACC Additional Expressions. def OpenACCAsteriskSizeExpr : StmtNode; diff --git a/clang/include/clang/Basic/arm_sve.td b/clang/include/clang/Basic/arm_sve.td index e9396e34adad8..1c6bdb8cad2d1 100644 --- a/clang/include/clang/Basic/arm_sve.td +++ b/clang/include/clang/Basic/arm_sve.td @@ -463,18 +463,19 @@ let SVETargetGuard = "sve,bf16", SMETargetGuard = "sme,bf16" in { let SVETargetGuard = "sve2p1", SMETargetGuard = InvalidMode in { // Contiguous truncating store from quadword (single vector). - def SVST1UWQ : MInst<"svst1wq[_{d}]", "vPcd", "iUif", [IsStore], MemEltTyInt32, "aarch64_sve_st1wq">; - def SVST1UWQ_VNUM : MInst<"svst1wq_vnum[_{d}]", "vPcld", "iUif", [IsStore], MemEltTyInt32, "aarch64_sve_st1wq">; + def SVST1UWQ : MInst<"svst1wq[_{d}]", "vPpd", "iUif", [IsStore], MemEltTyInt32, "aarch64_sve_st1wq">; + def SVST1UWQ_VNUM : MInst<"svst1wq_vnum[_{d}]", "vPpld", "iUif", [IsStore], MemEltTyInt32, "aarch64_sve_st1wq">; - def SVST1UDQ : MInst<"svst1dq[_{d}]", "vPcd", "lUld", [IsStore], MemEltTyInt64, "aarch64_sve_st1dq">; - def SVST1UDQ_VNUM : MInst<"svst1dq_vnum[_{d}]", "vPcld", "lUld", [IsStore], MemEltTyInt64, "aarch64_sve_st1dq">; + def SVST1UDQ : MInst<"svst1dq[_{d}]", "vPpd", "lUld", [IsStore], MemEltTyInt64, "aarch64_sve_st1dq">; + def SVST1UDQ_VNUM : MInst<"svst1dq_vnum[_{d}]", "vPpld", "lUld", [IsStore], MemEltTyInt64, "aarch64_sve_st1dq">; // Store one vector (vector base + scalar offset) def SVST1Q_SCATTER_U64BASE_OFFSET : MInst<"svst1q_scatter[_{2}base]_offset[_{d}]", "vPgld", "cUcsUsiUilUlfhdb", [IsScatterStore, IsByteIndexed], MemEltTyDefault, "aarch64_sve_st1q_scatter_scalar_offset">; def SVST1Q_SCATTER_U64BASE : MInst<"svst1q_scatter[_{2}base][_{d}]", "vPgd", "cUcsUsiUilUlfhdb", [IsScatterStore, IsByteIndexed], MemEltTyDefault, "aarch64_sve_st1q_scatter_scalar_offset">; // Store one vector (scalar base + vector offset) - def SVST1Q_SCATTER_U64OFFSET : MInst<"svst1q_scatter_[{3}]offset[_{d}]", "vPpgd", "cUcsUsiUilUlfhdb", [IsScatterStore, IsByteIndexed], MemEltTyDefault, "aarch64_sve_st1q_scatter_vector_offset">; + def SVST1Q_SCATTER_OFFSETS_U : MInst<"svst1q_scatter_[{3}]offset[_{d}]", "vPpgd", "cUcsUsiUilUlfhdb", [IsScatterStore, IsByteIndexed], MemEltTyDefault, "aarch64_sve_st1q_scatter_vector_offset">; + def SVST1Q_SCATTER_OFFSETS_S : MInst<"svst1q_scatter_[{3}]offset[_{d}]", "vPp#d", "cUcsUsiUilUlfhdb", [IsScatterStore, IsByteIndexed], MemEltTyDefault, "aarch64_sve_st1q_scatter_vector_offset">; // Store N vectors into N-element structure (scalar base) defm SVST2Q : StructStore<"svst2q[_{d}]", "vPc2", "aarch64_sve_st2q">; @@ -488,6 +489,7 @@ let SVETargetGuard = "sve2p1", SMETargetGuard = InvalidMode in { // Scatter store quadwords (scalar base + vector index) def SVST1Q_SCATTER_INDICES_U : MInst<"svst1q_scatter_[{3}]index[_{d}]", "vPpgd", "sUsiUilUlbhfd", [IsScatterStore], MemEltTyDefault, "aarch64_sve_st1q_scatter_index">; + def SVST1Q_SCATTER_INDICES_S : MInst<"svst1q_scatter_[{3}]index[_{d}]", "vPp#d", "sUsiUilUlbhfd", [IsScatterStore], MemEltTyDefault, "aarch64_sve_st1q_scatter_index">; // Scatter store quadwords (vector base + scalar index) def SVST1Q_SCATTER_INDEX_S : MInst<"svst1q_scatter[_{2}base]_index[_{d}]", "vPgld", "sUsiUilUlbhfd", [IsScatterStore], MemEltTyDefault, "aarch64_sve_st1q_scatter_scalar_offset">; diff --git a/clang/include/clang/Basic/arm_sve_sme_incl.td b/clang/include/clang/Basic/arm_sve_sme_incl.td index ee899209ad832..13e7cf45471c2 100644 --- a/clang/include/clang/Basic/arm_sve_sme_incl.td +++ b/clang/include/clang/Basic/arm_sve_sme_incl.td @@ -70,6 +70,7 @@ include "arm_immcheck_incl.td" // x: vector of signed integers // u: vector of unsigned integers // d: default +// p: pointer type // c: const pointer type // P: predicate type // s: scalar of element type @@ -101,6 +102,7 @@ include "arm_immcheck_incl.td" // [: svuint8_t // t: svint32_t // z: svuint32_t +// #: svint64_t // g: svuint64_t // O: svfloat16_t // M: svfloat32_t diff --git a/clang/include/clang/Sema/SemaOpenACC.h b/clang/include/clang/Sema/SemaOpenACC.h index 04ab1ac429a2d..addc33bf3c76b 100644 --- a/clang/include/clang/Sema/SemaOpenACC.h +++ b/clang/include/clang/Sema/SemaOpenACC.h @@ -296,13 +296,15 @@ class SemaOpenACC : public SemaBase { assert((ClauseKind == OpenACCClauseKind::NumGangs || ClauseKind == OpenACCClauseKind::NumWorkers || ClauseKind == OpenACCClauseKind::Async || + ClauseKind == OpenACCClauseKind::DeviceNum || ClauseKind == OpenACCClauseKind::Tile || ClauseKind == OpenACCClauseKind::Worker || ClauseKind == OpenACCClauseKind::Vector || ClauseKind == OpenACCClauseKind::VectorLength) && "Parsed clause kind does not have a int exprs"); - // 'async' and 'wait' have an optional IntExpr, so be tolerant of that. + // 'async', 'worker', 'vector', and 'wait' have an optional IntExpr, so be + // tolerant of that. if ((ClauseKind == OpenACCClauseKind::Async || ClauseKind == OpenACCClauseKind::Worker || ClauseKind == OpenACCClauseKind::Vector || @@ -346,6 +348,7 @@ class SemaOpenACC : public SemaBase { assert((ClauseKind == OpenACCClauseKind::NumGangs || ClauseKind == OpenACCClauseKind::NumWorkers || ClauseKind == OpenACCClauseKind::Async || + ClauseKind == OpenACCClauseKind::DeviceNum || ClauseKind == OpenACCClauseKind::Tile || ClauseKind == OpenACCClauseKind::Gang || ClauseKind == OpenACCClauseKind::Worker || @@ -482,6 +485,7 @@ class SemaOpenACC : public SemaBase { assert((ClauseKind == OpenACCClauseKind::NumGangs || ClauseKind == OpenACCClauseKind::NumWorkers || ClauseKind == OpenACCClauseKind::Async || + ClauseKind == OpenACCClauseKind::DeviceNum || ClauseKind == OpenACCClauseKind::Tile || ClauseKind == OpenACCClauseKind::Worker || ClauseKind == OpenACCClauseKind::Vector || @@ -493,6 +497,7 @@ class SemaOpenACC : public SemaBase { assert((ClauseKind == OpenACCClauseKind::NumGangs || ClauseKind == OpenACCClauseKind::NumWorkers || ClauseKind == OpenACCClauseKind::Async || + ClauseKind == OpenACCClauseKind::DeviceNum || ClauseKind == OpenACCClauseKind::Tile || ClauseKind == OpenACCClauseKind::Worker || ClauseKind == OpenACCClauseKind::Vector || diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h index 57e27c373bffa..dfd82afad4007 100644 --- a/clang/include/clang/Serialization/ASTBitCodes.h +++ b/clang/include/clang/Serialization/ASTBitCodes.h @@ -2022,6 +2022,8 @@ enum StmtCode { STMT_OPENACC_EXIT_DATA_CONSTRUCT, STMT_OPENACC_HOST_DATA_CONSTRUCT, STMT_OPENACC_WAIT_CONSTRUCT, + STMT_OPENACC_INIT_CONSTRUCT, + STMT_OPENACC_SHUTDOWN_CONSTRUCT, // HLSL Constructs EXPR_HLSL_OUT_ARG, diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/APSIntPtr.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/APSIntPtr.h new file mode 100644 index 0000000000000..84a6bf1406ac6 --- /dev/null +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/APSIntPtr.h @@ -0,0 +1,64 @@ +//== APSIntPtr.h - Wrapper for APSInt objects owned separately -*- C++ -*--==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_APSIntPtr_H +#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_APSIntPtr_H + +#include "llvm/ADT/APSInt.h" +#include "llvm/Support/Compiler.h" + +namespace clang::ento { + +/// A safe wrapper around APSInt objects allocated and owned by +/// \c BasicValueFactory. This just wraps a common llvm::APSInt. +class APSIntPtr { + using APSInt = llvm::APSInt; + +public: + APSIntPtr() = delete; + APSIntPtr(const APSIntPtr &) = default; + APSIntPtr &operator=(const APSIntPtr &) & = default; + ~APSIntPtr() = default; + + /// You should not use this API. + /// If do, ensure that the \p Ptr not going to dangle. + /// Prefer using \c BasicValueFactory::getValue() to get an APSIntPtr object. + static APSIntPtr unsafeConstructor(const APSInt *Ptr) { + return APSIntPtr(Ptr); + } + + LLVM_ATTRIBUTE_RETURNS_NONNULL + const APSInt *get() const { return Ptr; } + /*implicit*/ operator const APSInt &() const { return *get(); } + + APSInt operator-() const { return -*Ptr; } + APSInt operator~() const { return ~*Ptr; } + +#define DEFINE_OPERATOR(OP) \ + bool operator OP(APSIntPtr Other) const { return (*Ptr)OP(*Other.Ptr); } + DEFINE_OPERATOR(>) + DEFINE_OPERATOR(>=) + DEFINE_OPERATOR(<) + DEFINE_OPERATOR(<=) + DEFINE_OPERATOR(==) + DEFINE_OPERATOR(!=) +#undef DEFINE_OPERATOR + + const APSInt &operator*() const { return *Ptr; } + const APSInt *operator->() const { return Ptr; } + +private: + explicit APSIntPtr(const APSInt *Ptr) : Ptr(Ptr) {} + + /// Owned by \c BasicValueFactory. + const APSInt *Ptr; +}; + +} // namespace clang::ento + +#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_APSIntPtr_H diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h index ec503b41b381a..ef04f9c485e88 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h @@ -18,10 +18,11 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/Expr.h" #include "clang/AST/Type.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/APSIntPtr.h" #include "clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" #include "clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" #include "llvm/ADT/APSInt.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/ImmutableList.h" @@ -129,7 +130,7 @@ class BasicValueFactory { // This is private because external clients should use the factory // method that takes a QualType. - const llvm::APSInt& getValue(uint64_t X, unsigned BitWidth, bool isUnsigned); + APSIntPtr getValue(uint64_t X, unsigned BitWidth, bool isUnsigned); public: BasicValueFactory(ASTContext &ctx, llvm::BumpPtrAllocator &Alloc) @@ -140,9 +141,9 @@ class BasicValueFactory { ASTContext &getContext() const { return Ctx; } - const llvm::APSInt& getValue(const llvm::APSInt& X); - const llvm::APSInt& getValue(const llvm::APInt& X, bool isUnsigned); - const llvm::APSInt& getValue(uint64_t X, QualType T); + APSIntPtr getValue(const llvm::APSInt &X); + APSIntPtr getValue(const llvm::APInt &X, bool isUnsigned); + APSIntPtr getValue(uint64_t X, QualType T); /// Returns the type of the APSInt used to store values of the given QualType. APSIntType getAPSIntType(QualType T) const { @@ -165,79 +166,70 @@ class BasicValueFactory { /// Convert - Create a new persistent APSInt with the same value as 'From' /// but with the bitwidth and signedness of 'To'. - const llvm::APSInt &Convert(const llvm::APSInt& To, - const llvm::APSInt& From) { + APSIntPtr Convert(const llvm::APSInt &To, const llvm::APSInt &From) { APSIntType TargetType(To); if (TargetType == APSIntType(From)) - return From; + return getValue(From); return getValue(TargetType.convert(From)); } - const llvm::APSInt &Convert(QualType T, const llvm::APSInt &From) { + APSIntPtr Convert(QualType T, const llvm::APSInt &From) { APSIntType TargetType = getAPSIntType(T); return Convert(TargetType, From); } - const llvm::APSInt &Convert(APSIntType TargetType, const llvm::APSInt &From) { + APSIntPtr Convert(APSIntType TargetType, const llvm::APSInt &From) { if (TargetType == APSIntType(From)) - return From; + return getValue(From); return getValue(TargetType.convert(From)); } - const llvm::APSInt &getIntValue(uint64_t X, bool isUnsigned) { + APSIntPtr getIntValue(uint64_t X, bool isUnsigned) { QualType T = isUnsigned ? Ctx.UnsignedIntTy : Ctx.IntTy; return getValue(X, T); } - const llvm::APSInt &getMaxValue(const llvm::APSInt &v) { + APSIntPtr getMaxValue(const llvm::APSInt &v) { return getValue(APSIntType(v).getMaxValue()); } - const llvm::APSInt &getMinValue(const llvm::APSInt &v) { + APSIntPtr getMinValue(const llvm::APSInt &v) { return getValue(APSIntType(v).getMinValue()); } - const llvm::APSInt &getMaxValue(QualType T) { - return getMaxValue(getAPSIntType(T)); - } + APSIntPtr getMaxValue(QualType T) { return getMaxValue(getAPSIntType(T)); } - const llvm::APSInt &getMinValue(QualType T) { - return getMinValue(getAPSIntType(T)); - } + APSIntPtr getMinValue(QualType T) { return getMinValue(getAPSIntType(T)); } - const llvm::APSInt &getMaxValue(APSIntType T) { - return getValue(T.getMaxValue()); - } + APSIntPtr getMaxValue(APSIntType T) { return getValue(T.getMaxValue()); } - const llvm::APSInt &getMinValue(APSIntType T) { - return getValue(T.getMinValue()); - } + APSIntPtr getMinValue(APSIntType T) { return getValue(T.getMinValue()); } - const llvm::APSInt &Add1(const llvm::APSInt &V) { + APSIntPtr Add1(const llvm::APSInt &V) { llvm::APSInt X = V; ++X; return getValue(X); } - const llvm::APSInt &Sub1(const llvm::APSInt &V) { + APSIntPtr Sub1(const llvm::APSInt &V) { llvm::APSInt X = V; --X; return getValue(X); } - const llvm::APSInt &getZeroWithTypeSize(QualType T) { + APSIntPtr getZeroWithTypeSize(QualType T) { assert(T->isScalarType()); return getValue(0, Ctx.getTypeSize(T), true); } - const llvm::APSInt &getTruthValue(bool b, QualType T) { + APSIntPtr getTruthValue(bool b, QualType T) { return getValue(b ? 1 : 0, Ctx.getIntWidth(T), T->isUnsignedIntegerOrEnumerationType()); } - const llvm::APSInt &getTruthValue(bool b) { + APSIntPtr getTruthValue(bool b) { return getTruthValue(b, Ctx.getLogicalOperationType()); } @@ -273,9 +265,9 @@ class BasicValueFactory { accumCXXBase(llvm::iterator_range PathRange, const nonloc::PointerToMember &PTM, const clang::CastKind &kind); - const llvm::APSInt* evalAPSInt(BinaryOperator::Opcode Op, - const llvm::APSInt& V1, - const llvm::APSInt& V2); + std::optional evalAPSInt(BinaryOperator::Opcode Op, + const llvm::APSInt &V1, + const llvm::APSInt &V2); const std::pair& getPersistentSValWithData(const SVal& V, uintptr_t Data); diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h index 0d9566285f5d4..f88bf70d72398 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h @@ -1206,7 +1206,7 @@ class ElementRegion : public TypedValueRegion { : TypedValueRegion(sReg, ElementRegionKind), ElementType(elementType), Index(Idx) { assert((!isa(Idx) || - Idx.castAs().getValue().isSigned()) && + Idx.castAs().getValue()->isSigned()) && "The index must be signed"); assert(!elementType.isNull() && !elementType->isVoidType() && "Invalid region type!"); diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h index 29f534eba2a26..a20516b003c7d 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h @@ -70,7 +70,6 @@ template struct ProgramStateTrait { /// values will never change. class ProgramState : public llvm::FoldingSetNode { public: - typedef llvm::ImmutableSet IntSetTy; typedef llvm::ImmutableMap GenericDataMap; private: diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h index 5766af1fc78a4..7cfb24e5e649d 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h @@ -16,6 +16,7 @@ #include "clang/Basic/JsonSupport.h" #include "clang/Basic/TargetInfo.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h" #include "clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SMTConv.h" #include @@ -154,7 +155,7 @@ class SMTConstraintManager : public clang::ento::SimpleConstraintManager { return nullptr; // This is the only solution, store it - return &BVF.getValue(Value); + return BVF.getValue(Value).get(); } if (const SymbolCast *SC = dyn_cast(Sym)) { @@ -167,16 +168,16 @@ class SMTConstraintManager : public clang::ento::SimpleConstraintManager { const llvm::APSInt *Value; if (!(Value = getSymVal(State, CastSym))) return nullptr; - return &BVF.Convert(SC->getType(), *Value); + return BVF.Convert(SC->getType(), *Value).get(); } if (const BinarySymExpr *BSE = dyn_cast(Sym)) { const llvm::APSInt *LHS, *RHS; if (const SymIntExpr *SIE = dyn_cast(BSE)) { LHS = getSymVal(State, SIE->getLHS()); - RHS = &SIE->getRHS(); + RHS = SIE->getRHS().get(); } else if (const IntSymExpr *ISE = dyn_cast(BSE)) { - LHS = &ISE->getLHS(); + LHS = ISE->getLHS().get(); RHS = getSymVal(State, ISE->getRHS()); } else if (const SymSymExpr *SSM = dyn_cast(BSE)) { // Early termination to avoid expensive call @@ -195,7 +196,9 @@ class SMTConstraintManager : public clang::ento::SimpleConstraintManager { std::tie(ConvertedRHS, RTy) = SMTConv::fixAPSInt(Ctx, *RHS); SMTConv::doIntTypeConversion( Solver, Ctx, ConvertedLHS, LTy, ConvertedRHS, RTy); - return BVF.evalAPSInt(BSE->getOpcode(), ConvertedLHS, ConvertedRHS); + std::optional Res = + BVF.evalAPSInt(BSE->getOpcode(), ConvertedLHS, ConvertedRHS); + return Res ? Res.value().get() : nullptr; } llvm_unreachable("Unsupported expression to get symbol value!"); diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h index ec2b2b2456948..54430d426a82a 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h @@ -329,11 +329,10 @@ class SValBuilder { } nonloc::SymbolVal makeNonLoc(const SymExpr *lhs, BinaryOperator::Opcode op, - const llvm::APSInt &rhs, QualType type); + APSIntPtr rhs, QualType type); - nonloc::SymbolVal makeNonLoc(const llvm::APSInt &rhs, - BinaryOperator::Opcode op, const SymExpr *lhs, - QualType type); + nonloc::SymbolVal makeNonLoc(APSIntPtr rhs, BinaryOperator::Opcode op, + const SymExpr *lhs, QualType type); nonloc::SymbolVal makeNonLoc(const SymExpr *lhs, BinaryOperator::Opcode op, const SymExpr *rhs, QualType type); diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h index a054a819a15a8..aeb57b28077c6 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h @@ -17,6 +17,7 @@ #include "clang/AST/Expr.h" #include "clang/AST/Type.h" #include "clang/Basic/LLVM.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/APSIntPtr.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h" #include "llvm/ADT/APSInt.h" #include "llvm/ADT/FoldingSet.h" @@ -298,9 +299,12 @@ class SymbolVal : public NonLoc { /// Value representing integer constant. class ConcreteInt : public NonLoc { public: - explicit ConcreteInt(const llvm::APSInt &V) : NonLoc(ConcreteIntKind, &V) {} + explicit ConcreteInt(APSIntPtr V) : NonLoc(ConcreteIntKind, V.get()) {} - const llvm::APSInt &getValue() const { return *castDataAs(); } + APSIntPtr getValue() const { + // This is safe because in the ctor we take a safe APSIntPtr. + return APSIntPtr::unsafeConstructor(castDataAs()); + } static bool classof(SVal V) { return V.getKind() == ConcreteIntKind; } }; @@ -510,9 +514,12 @@ class MemRegionVal : public Loc { class ConcreteInt : public Loc { public: - explicit ConcreteInt(const llvm::APSInt &V) : Loc(ConcreteIntKind, &V) {} + explicit ConcreteInt(APSIntPtr V) : Loc(ConcreteIntKind, V.get()) {} - const llvm::APSInt &getValue() const { return *castDataAs(); } + APSIntPtr getValue() const { + // This is safe because in the ctor we take a safe APSIntPtr. + return APSIntPtr::unsafeConstructor(castDataAs()); + } static bool classof(SVal V) { return V.getKind() == ConcreteIntKind; } }; diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h index 3b64d38ee2b23..73732d532f630 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h @@ -18,6 +18,7 @@ #include "clang/AST/Type.h" #include "clang/Analysis/AnalysisDeclContext.h" #include "clang/Basic/LLVM.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/APSIntPtr.h" #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" #include "clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h" @@ -410,9 +411,7 @@ class BinarySymExpr : public SymExpr { return 1; } - static const llvm::APSInt *getPointer(const llvm::APSInt &Value) { - return &Value; - } + static const llvm::APSInt *getPointer(APSIntPtr Value) { return Value.get(); } static const SymExpr *getPointer(const SymExpr *Value) { return Value; } static void dumpToStreamImpl(raw_ostream &os, const SymExpr *Value); @@ -468,11 +467,11 @@ class BinarySymExprImpl : public BinarySymExpr { }; /// Represents a symbolic expression like 'x' + 3. -using SymIntExpr = BinarySymExprImpl; /// Represents a symbolic expression like 3 - 'x'. -using IntSymExpr = BinarySymExprImpl; /// Represents a symbolic expression like 'x' + 'y'. @@ -537,15 +536,14 @@ class SymbolManager { QualType From, QualType To); const SymIntExpr *getSymIntExpr(const SymExpr *lhs, BinaryOperator::Opcode op, - const llvm::APSInt& rhs, QualType t); + APSIntPtr rhs, QualType t); const SymIntExpr *getSymIntExpr(const SymExpr &lhs, BinaryOperator::Opcode op, - const llvm::APSInt& rhs, QualType t) { + APSIntPtr rhs, QualType t) { return getSymIntExpr(&lhs, op, rhs, t); } - const IntSymExpr *getIntSymExpr(const llvm::APSInt& lhs, - BinaryOperator::Opcode op, + const IntSymExpr *getIntSymExpr(APSIntPtr lhs, BinaryOperator::Opcode op, const SymExpr *rhs, QualType t); const SymSymExpr *getSymSymExpr(const SymExpr *lhs, BinaryOperator::Opcode op, diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp index d6b33c8aeeaac..2ae91feb2d9e8 100644 --- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp +++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp @@ -1862,10 +1862,10 @@ static bool interp__builtin_memcpy(InterpState &S, CodePtr OpPC, } QualType ElemType; - if (SrcPtr.getFieldDesc()->isArray()) - ElemType = SrcPtr.getFieldDesc()->getElemQualType(); + if (DestPtr.getFieldDesc()->isArray()) + ElemType = DestPtr.getFieldDesc()->getElemQualType(); else - ElemType = SrcPtr.getType(); + ElemType = DestPtr.getType(); unsigned ElemSize = S.getASTContext().getTypeSizeInChars(ElemType).getQuantity(); @@ -1876,6 +1876,18 @@ static bool interp__builtin_memcpy(InterpState &S, CodePtr OpPC, return false; } + QualType SrcElemType; + if (SrcPtr.getFieldDesc()->isArray()) + SrcElemType = SrcPtr.getFieldDesc()->getElemQualType(); + else + SrcElemType = SrcPtr.getType(); + + if (!S.getASTContext().hasSameUnqualifiedType(ElemType, SrcElemType)) { + S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_memcpy_type_pun) + << Move << SrcElemType << ElemType; + return false; + } + // Check for overlapping memory regions. if (!Move && Pointer::pointToSameBlock(SrcPtr, DestPtr)) { unsigned SrcIndex = SrcPtr.getIndex() * SrcPtr.elemSize(); @@ -1893,8 +1905,8 @@ static bool interp__builtin_memcpy(InterpState &S, CodePtr OpPC, // As a last resort, reject dummy pointers. if (DestPtr.isDummy() || SrcPtr.isDummy()) return false; - - if (!DoBitCastPtr(S, OpPC, SrcPtr, DestPtr, Size.getZExtValue())) + assert(Size.getZExtValue() % ElemSize == 0); + if (!DoMemcpy(S, OpPC, SrcPtr, DestPtr, Bytes(Size.getZExtValue()).toBits())) return false; S.Stk.push(DestPtr); diff --git a/clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp b/clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp index 07f7694370821..0fc94e1694822 100644 --- a/clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp +++ b/clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp @@ -448,3 +448,34 @@ bool clang::interp::DoBitCastPtr(InterpState &S, CodePtr OpPC, return Success; } + +bool clang::interp::DoMemcpy(InterpState &S, CodePtr OpPC, + const Pointer &SrcPtr, const Pointer &DestPtr, + Bits Size) { + assert(SrcPtr.isBlockPointer()); + assert(DestPtr.isBlockPointer()); + + unsigned SrcStartOffset = SrcPtr.getByteOffset(); + unsigned DestStartOffset = DestPtr.getByteOffset(); + + enumeratePointerFields(SrcPtr, S.getContext(), Size, + [&](const Pointer &P, PrimType T, Bits BitOffset, + Bits FullBitWidth, bool PackedBools) -> bool { + unsigned SrcOffsetDiff = + P.getByteOffset() - SrcStartOffset; + + Pointer DestP = + Pointer(DestPtr.asBlockPointer().Pointee, + DestPtr.asBlockPointer().Base, + DestStartOffset + SrcOffsetDiff); + + TYPE_SWITCH(T, { + DestP.deref() = P.deref(); + DestP.initialize(); + }); + + return true; + }); + + return true; +} diff --git a/clang/lib/AST/ByteCode/InterpBuiltinBitCast.h b/clang/lib/AST/ByteCode/InterpBuiltinBitCast.h index b45613b2f21e2..a0191bab693c4 100644 --- a/clang/lib/AST/ByteCode/InterpBuiltinBitCast.h +++ b/clang/lib/AST/ByteCode/InterpBuiltinBitCast.h @@ -33,6 +33,10 @@ bool DoBitCastPtr(InterpState &S, CodePtr OpPC, const Pointer &FromPtr, Pointer &ToPtr, size_t Size); bool readPointerToBuffer(const Context &Ctx, const Pointer &FromPtr, BitcastBuffer &Buffer, bool ReturnOnUninit); + +bool DoMemcpy(InterpState &S, CodePtr OpPC, const Pointer &SrcPtr, + const Pointer &DestPtr, Bits Size); + } // namespace interp } // namespace clang diff --git a/clang/lib/AST/ByteCode/Pointer.h b/clang/lib/AST/ByteCode/Pointer.h index 457fe93b27817..0d467c2abf083 100644 --- a/clang/lib/AST/ByteCode/Pointer.h +++ b/clang/lib/AST/ByteCode/Pointer.h @@ -107,6 +107,7 @@ class Pointer { : Offset(Offset), StorageKind(Storage::Fn) { PointeeStorage.Fn = FunctionPointer(F); } + Pointer(Block *Pointee, unsigned Base, uint64_t Offset); ~Pointer(); void operator=(const Pointer &P); @@ -706,8 +707,6 @@ class Pointer { friend struct InitMap; friend class DynamicAllocator; - Pointer(Block *Pointee, unsigned Base, uint64_t Offset); - /// Returns the embedded descriptor preceding a field. InlineDescriptor *getInlineDesc() const { assert(isBlockPointer()); diff --git a/clang/lib/AST/OpenACCClause.cpp b/clang/lib/AST/OpenACCClause.cpp index fbc9f6d15fa7b..d69fab5cc413c 100644 --- a/clang/lib/AST/OpenACCClause.cpp +++ b/clang/lib/AST/OpenACCClause.cpp @@ -46,6 +46,7 @@ bool OpenACCClauseWithCondition::classof(const OpenACCClause *C) { bool OpenACCClauseWithSingleIntExpr::classof(const OpenACCClause *C) { return OpenACCNumWorkersClause::classof(C) || OpenACCVectorLengthClause::classof(C) || + OpenACCDeviceNumClause::classof(C) || OpenACCVectorClause::classof(C) || OpenACCWorkerClause::classof(C) || OpenACCCollapseClause::classof(C) || OpenACCAsyncClause::classof(C); } @@ -218,6 +219,26 @@ OpenACCAsyncClause *OpenACCAsyncClause::Create(const ASTContext &C, return new (Mem) OpenACCAsyncClause(BeginLoc, LParenLoc, IntExpr, EndLoc); } +OpenACCDeviceNumClause::OpenACCDeviceNumClause(SourceLocation BeginLoc, + SourceLocation LParenLoc, Expr *IntExpr, + SourceLocation EndLoc) + : OpenACCClauseWithSingleIntExpr(OpenACCClauseKind::DeviceNum, BeginLoc, + LParenLoc, IntExpr, EndLoc) { + assert((IntExpr->isInstantiationDependent() || + IntExpr->getType()->isIntegerType()) && + "device_num expression type not scalar/dependent"); +} + +OpenACCDeviceNumClause *OpenACCDeviceNumClause::Create(const ASTContext &C, + SourceLocation BeginLoc, + SourceLocation LParenLoc, + Expr *IntExpr, + SourceLocation EndLoc) { + void *Mem = + C.Allocate(sizeof(OpenACCDeviceNumClause), alignof(OpenACCDeviceNumClause)); + return new (Mem) OpenACCDeviceNumClause(BeginLoc, LParenLoc, IntExpr, EndLoc); +} + OpenACCWaitClause *OpenACCWaitClause::Create( const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc, Expr *DevNumExpr, SourceLocation QueuesLoc, ArrayRef QueueIdExprs, @@ -547,6 +568,13 @@ void OpenACCClausePrinter::VisitVectorLengthClause( OS << ")"; } +void OpenACCClausePrinter::VisitDeviceNumClause( + const OpenACCDeviceNumClause &C) { + OS << "device_num("; + printExpr(C.getIntExpr()); + OS << ")"; +} + void OpenACCClausePrinter::VisitAsyncClause(const OpenACCAsyncClause &C) { OS << "async"; if (C.hasIntExpr()) { diff --git a/clang/lib/AST/StmtOpenACC.cpp b/clang/lib/AST/StmtOpenACC.cpp index 6d9f267702e37..e6d76ea30f029 100644 --- a/clang/lib/AST/StmtOpenACC.cpp +++ b/clang/lib/AST/StmtOpenACC.cpp @@ -225,3 +225,43 @@ OpenACCWaitConstruct *OpenACCWaitConstruct::Create( QueuesLoc, QueueIdExprs, RParenLoc, End, Clauses); return Inst; } +OpenACCInitConstruct *OpenACCInitConstruct::CreateEmpty(const ASTContext &C, + unsigned NumClauses) { + void *Mem = + C.Allocate(OpenACCInitConstruct::totalSizeToAlloc( + NumClauses)); + auto *Inst = new (Mem) OpenACCInitConstruct(NumClauses); + return Inst; +} + +OpenACCInitConstruct * +OpenACCInitConstruct::Create(const ASTContext &C, SourceLocation Start, + SourceLocation DirectiveLoc, SourceLocation End, + ArrayRef Clauses) { + void *Mem = + C.Allocate(OpenACCInitConstruct::totalSizeToAlloc( + Clauses.size())); + auto *Inst = + new (Mem) OpenACCInitConstruct(Start, DirectiveLoc, End, Clauses); + return Inst; +} +OpenACCShutdownConstruct * +OpenACCShutdownConstruct::CreateEmpty(const ASTContext &C, + unsigned NumClauses) { + void *Mem = C.Allocate( + OpenACCShutdownConstruct::totalSizeToAlloc( + NumClauses)); + auto *Inst = new (Mem) OpenACCShutdownConstruct(NumClauses); + return Inst; +} + +OpenACCShutdownConstruct *OpenACCShutdownConstruct::Create( + const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, + SourceLocation End, ArrayRef Clauses) { + void *Mem = C.Allocate( + OpenACCShutdownConstruct::totalSizeToAlloc( + Clauses.size())); + auto *Inst = + new (Mem) OpenACCShutdownConstruct(Start, DirectiveLoc, End, Clauses); + return Inst; +} diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp index ecc9b6e35db72..c5d19f70fc6ea 100644 --- a/clang/lib/AST/StmtPrinter.cpp +++ b/clang/lib/AST/StmtPrinter.cpp @@ -127,6 +127,8 @@ namespace { void PrintOMPExecutableDirective(OMPExecutableDirective *S, bool ForceNoStmt = false); void PrintFPPragmas(CompoundStmt *S); + void PrintOpenACCClauseList(OpenACCConstructStmt *S); + void PrintOpenACCConstruct(OpenACCConstructStmt *S); void PrintExpr(Expr *E) { if (E) @@ -1155,87 +1157,52 @@ void StmtPrinter::VisitOMPTargetParallelGenericLoopDirective( //===----------------------------------------------------------------------===// // OpenACC construct printing methods //===----------------------------------------------------------------------===// -void StmtPrinter::VisitOpenACCComputeConstruct(OpenACCComputeConstruct *S) { - Indent() << "#pragma acc " << S->getDirectiveKind(); - +void StmtPrinter::PrintOpenACCClauseList(OpenACCConstructStmt *S) { if (!S->clauses().empty()) { OS << ' '; OpenACCClausePrinter Printer(OS, Policy); Printer.VisitClauseList(S->clauses()); } +} +void StmtPrinter::PrintOpenACCConstruct(OpenACCConstructStmt *S) { + Indent() << "#pragma acc " << S->getDirectiveKind(); + PrintOpenACCClauseList(S); OS << '\n'; - +} +void StmtPrinter::VisitOpenACCComputeConstruct(OpenACCComputeConstruct *S) { + PrintOpenACCConstruct(S); PrintStmt(S->getStructuredBlock()); } void StmtPrinter::VisitOpenACCLoopConstruct(OpenACCLoopConstruct *S) { - Indent() << "#pragma acc loop"; - - if (!S->clauses().empty()) { - OS << ' '; - OpenACCClausePrinter Printer(OS, Policy); - Printer.VisitClauseList(S->clauses()); - } - OS << '\n'; - + PrintOpenACCConstruct(S); PrintStmt(S->getLoop()); } void StmtPrinter::VisitOpenACCCombinedConstruct(OpenACCCombinedConstruct *S) { - Indent() << "#pragma acc " << S->getDirectiveKind(); - if (!S->clauses().empty()) { - OS << ' '; - OpenACCClausePrinter Printer(OS, Policy); - Printer.VisitClauseList(S->clauses()); - } - OS << '\n'; - + PrintOpenACCConstruct(S); PrintStmt(S->getLoop()); } void StmtPrinter::VisitOpenACCDataConstruct(OpenACCDataConstruct *S) { - Indent() << "#pragma acc data"; - - if (!S->clauses().empty()) { - OS << ' '; - OpenACCClausePrinter Printer(OS, Policy); - Printer.VisitClauseList(S->clauses()); - } - OS << '\n'; - + PrintOpenACCConstruct(S); + PrintStmt(S->getStructuredBlock()); +} +void StmtPrinter::VisitOpenACCHostDataConstruct(OpenACCHostDataConstruct *S) { + PrintOpenACCConstruct(S); PrintStmt(S->getStructuredBlock()); } void StmtPrinter::VisitOpenACCEnterDataConstruct(OpenACCEnterDataConstruct *S) { - Indent() << "#pragma acc enter data"; - - if (!S->clauses().empty()) { - OS << ' '; - OpenACCClausePrinter Printer(OS, Policy); - Printer.VisitClauseList(S->clauses()); - } - OS << '\n'; + PrintOpenACCConstruct(S); } void StmtPrinter::VisitOpenACCExitDataConstruct(OpenACCExitDataConstruct *S) { - Indent() << "#pragma acc exit data"; - - if (!S->clauses().empty()) { - OS << ' '; - OpenACCClausePrinter Printer(OS, Policy); - Printer.VisitClauseList(S->clauses()); - } - OS << '\n'; + PrintOpenACCConstruct(S); } -void StmtPrinter::VisitOpenACCHostDataConstruct(OpenACCHostDataConstruct *S) { - Indent() << "#pragma acc host_data"; - - if (!S->clauses().empty()) { - OS << ' '; - OpenACCClausePrinter Printer(OS, Policy); - Printer.VisitClauseList(S->clauses()); - } - OS << '\n'; - - PrintStmt(S->getStructuredBlock()); +void StmtPrinter::VisitOpenACCInitConstruct(OpenACCInitConstruct *S) { + PrintOpenACCConstruct(S); +} +void StmtPrinter::VisitOpenACCShutdownConstruct(OpenACCShutdownConstruct *S) { + PrintOpenACCConstruct(S); } void StmtPrinter::VisitOpenACCWaitConstruct(OpenACCWaitConstruct *S) { @@ -1258,11 +1225,7 @@ void StmtPrinter::VisitOpenACCWaitConstruct(OpenACCWaitConstruct *S) { OS << ")"; } - if (!S->clauses().empty()) { - OS << ' '; - OpenACCClausePrinter Printer(OS, Policy); - Printer.VisitClauseList(S->clauses()); - } + PrintOpenACCClauseList(S); OS << '\n'; } diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index fccd97dca23af..27313f9ae1275 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -2645,6 +2645,11 @@ void OpenACCClauseProfiler::VisitAsyncClause(const OpenACCAsyncClause &Clause) { Profiler.VisitStmt(Clause.getIntExpr()); } +void OpenACCClauseProfiler::VisitDeviceNumClause( + const OpenACCDeviceNumClause &Clause) { + Profiler.VisitStmt(Clause.getIntExpr()); +} + void OpenACCClauseProfiler::VisitWorkerClause( const OpenACCWorkerClause &Clause) { if (Clause.hasIntExpr()) @@ -2751,6 +2756,19 @@ void StmtProfiler::VisitOpenACCWaitConstruct(const OpenACCWaitConstruct *S) { P.VisitOpenACCClauseList(S->clauses()); } +void StmtProfiler::VisitOpenACCInitConstruct(const OpenACCInitConstruct *S) { + VisitStmt(S); + OpenACCClauseProfiler P{*this}; + P.VisitOpenACCClauseList(S->clauses()); +} + +void StmtProfiler::VisitOpenACCShutdownConstruct( + const OpenACCShutdownConstruct *S) { + VisitStmt(S); + OpenACCClauseProfiler P{*this}; + P.VisitOpenACCClauseList(S->clauses()); +} + void StmtProfiler::VisitHLSLOutArgExpr(const HLSLOutArgExpr *S) { VisitStmt(S); } diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp index 7cdffbe20e575..018147e68aba6 100644 --- a/clang/lib/AST/TextNodeDumper.cpp +++ b/clang/lib/AST/TextNodeDumper.cpp @@ -413,6 +413,7 @@ void TextNodeDumper::Visit(const OpenACCClause *C) { case OpenACCClauseKind::Independent: case OpenACCClauseKind::Detach: case OpenACCClauseKind::Delete: + case OpenACCClauseKind::DeviceNum: case OpenACCClauseKind::DevicePtr: case OpenACCClauseKind::Finalize: case OpenACCClauseKind::FirstPrivate: @@ -2963,6 +2964,13 @@ void TextNodeDumper::VisitOpenACCHostDataConstruct( void TextNodeDumper::VisitOpenACCWaitConstruct(const OpenACCWaitConstruct *S) { OS << " " << S->getDirectiveKind(); } +void TextNodeDumper::VisitOpenACCInitConstruct(const OpenACCInitConstruct *S) { + OS << " " << S->getDirectiveKind(); +} +void TextNodeDumper::VisitOpenACCShutdownConstruct( + const OpenACCShutdownConstruct *S) { + OS << " " << S->getDirectiveKind(); +} void TextNodeDumper::VisitEmbedExpr(const EmbedExpr *S) { AddChild("begin", [=] { OS << S->getStartingElementPos(); }); diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index 976361d07b68b..caa0ac858a1be 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -5118,7 +5118,7 @@ bool Type::isHLSLIntangibleType() const { CXXRecordDecl *RD = RT->getAsCXXRecordDecl(); assert(RD != nullptr && - "all HLSL struct and classes should be CXXRecordDecl"); + "all HLSL structs and classes should be CXXRecordDecl"); assert(RD->isCompleteDefinition() && "expecting complete type"); return RD->isHLSLIntangible(); } diff --git a/clang/lib/Analysis/FlowSensitive/CMakeLists.txt b/clang/lib/Analysis/FlowSensitive/CMakeLists.txt index 05cdaa7e27823..0c30df8b4b194 100644 --- a/clang/lib/Analysis/FlowSensitive/CMakeLists.txt +++ b/clang/lib/Analysis/FlowSensitive/CMakeLists.txt @@ -10,6 +10,7 @@ add_clang_library(clangAnalysisFlowSensitive Logger.cpp RecordOps.cpp SimplifyConstraints.cpp + SmartPointerAccessorCaching.cpp Transfer.cpp TypeErasedDataflowAnalysis.cpp Value.cpp diff --git a/clang/lib/Analysis/FlowSensitive/SmartPointerAccessorCaching.cpp b/clang/lib/Analysis/FlowSensitive/SmartPointerAccessorCaching.cpp new file mode 100644 index 0000000000000..a0c81aa933da8 --- /dev/null +++ b/clang/lib/Analysis/FlowSensitive/SmartPointerAccessorCaching.cpp @@ -0,0 +1,147 @@ +#include "clang/Analysis/FlowSensitive/SmartPointerAccessorCaching.h" + +#include "clang/AST/CanonicalType.h" +#include "clang/AST/DeclCXX.h" +#include "clang/ASTMatchers/ASTMatchers.h" +#include "clang/ASTMatchers/ASTMatchersMacros.h" +#include "clang/Basic/OperatorKinds.h" + +namespace clang::dataflow { + +namespace { + +using ast_matchers::callee; +using ast_matchers::cxxMemberCallExpr; +using ast_matchers::cxxMethodDecl; +using ast_matchers::cxxOperatorCallExpr; +using ast_matchers::hasName; +using ast_matchers::hasOverloadedOperatorName; +using ast_matchers::ofClass; +using ast_matchers::parameterCountIs; +using ast_matchers::pointerType; +using ast_matchers::referenceType; +using ast_matchers::returns; + +bool hasSmartPointerClassShape(const CXXRecordDecl &RD, bool &HasGet, + bool &HasValue) { + // We may want to cache this search, but in current profiles it hasn't shown + // up as a hot spot (possibly because there aren't many hits, relatively). + bool HasArrow = false; + bool HasStar = false; + CanQualType StarReturnType, ArrowReturnType, GetReturnType, ValueReturnType; + for (const auto *MD : RD.methods()) { + // We only consider methods that are const and have zero parameters. + // It may be that there is a non-const overload for the method, but + // there should at least be a const overload as well. + if (!MD->isConst() || MD->getNumParams() != 0) + continue; + switch (MD->getOverloadedOperator()) { + case OO_Star: + if (MD->getReturnType()->isReferenceType()) { + HasStar = true; + StarReturnType = MD->getReturnType() + .getNonReferenceType() + ->getCanonicalTypeUnqualified(); + } + break; + case OO_Arrow: + if (MD->getReturnType()->isPointerType()) { + HasArrow = true; + ArrowReturnType = MD->getReturnType() + ->getPointeeType() + ->getCanonicalTypeUnqualified(); + } + break; + case OO_None: { + IdentifierInfo *II = MD->getIdentifier(); + if (II == nullptr) + continue; + if (II->isStr("get")) { + if (MD->getReturnType()->isPointerType()) { + HasGet = true; + GetReturnType = MD->getReturnType() + ->getPointeeType() + ->getCanonicalTypeUnqualified(); + } + } else if (II->isStr("value")) { + if (MD->getReturnType()->isReferenceType()) { + HasValue = true; + ValueReturnType = MD->getReturnType() + .getNonReferenceType() + ->getCanonicalTypeUnqualified(); + } + } + } break; + default: + break; + } + } + + if (!HasStar || !HasArrow || StarReturnType != ArrowReturnType) + return false; + HasGet = HasGet && (GetReturnType == StarReturnType); + HasValue = HasValue && (ValueReturnType == StarReturnType); + return true; +} + +} // namespace +} // namespace clang::dataflow + +// AST_MATCHER macros create an "internal" namespace, so we put it in +// its own anonymous namespace instead of in clang::dataflow. +namespace { + +AST_MATCHER(clang::CXXRecordDecl, smartPointerClassWithGet) { + bool HasGet = false; + bool HasValue = false; + bool HasStarAndArrow = + clang::dataflow::hasSmartPointerClassShape(Node, HasGet, HasValue); + return HasStarAndArrow && HasGet; +} + +AST_MATCHER(clang::CXXRecordDecl, smartPointerClassWithValue) { + bool HasGet = false; + bool HasValue = false; + bool HasStarAndArrow = + clang::dataflow::hasSmartPointerClassShape(Node, HasGet, HasValue); + return HasStarAndArrow && HasValue; +} + +AST_MATCHER(clang::CXXRecordDecl, smartPointerClassWithGetOrValue) { + bool HasGet = false; + bool HasValue = false; + bool HasStarAndArrow = + clang::dataflow::hasSmartPointerClassShape(Node, HasGet, HasValue); + return HasStarAndArrow && (HasGet || HasValue); +} + +} // namespace + +namespace clang::dataflow { + +ast_matchers::StatementMatcher isSmartPointerLikeOperatorStar() { + return cxxOperatorCallExpr( + hasOverloadedOperatorName("*"), + callee(cxxMethodDecl(parameterCountIs(0), returns(referenceType()), + ofClass(smartPointerClassWithGetOrValue())))); +} + +ast_matchers::StatementMatcher isSmartPointerLikeOperatorArrow() { + return cxxOperatorCallExpr( + hasOverloadedOperatorName("->"), + callee(cxxMethodDecl(parameterCountIs(0), returns(pointerType()), + ofClass(smartPointerClassWithGetOrValue())))); +} +ast_matchers::StatementMatcher isSmartPointerLikeValueMethodCall() { + return cxxMemberCallExpr(callee( + cxxMethodDecl(parameterCountIs(0), returns(referenceType()), + hasName("value"), ofClass(smartPointerClassWithValue())))); +} + +ast_matchers::StatementMatcher isSmartPointerLikeGetMethodCall() { + return cxxMemberCallExpr(callee( + cxxMethodDecl(parameterCountIs(0), returns(pointerType()), hasName("get"), + ofClass(smartPointerClassWithGet())))); +} + +} // namespace clang::dataflow diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp index b1003f2ce5032..e6c9d77d29f6f 100644 --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -1028,9 +1028,20 @@ void EmitAssemblyHelper::RunOptimizationPipeline( // of the pipeline. if (LangOpts.Sanitize.has(SanitizerKind::LocalBounds)) PB.registerScalarOptimizerLateEPCallback( - [](FunctionPassManager &FPM, OptimizationLevel Level) { - FPM.addPass( - BoundsCheckingPass(BoundsCheckingPass::ReportingMode::Trap)); + [this](FunctionPassManager &FPM, OptimizationLevel Level) { + BoundsCheckingPass::ReportingMode Mode; + if (CodeGenOpts.SanitizeTrap.has(SanitizerKind::LocalBounds)) { + Mode = BoundsCheckingPass::ReportingMode::Trap; + } else if (CodeGenOpts.SanitizeMinimalRuntime) { + Mode = CodeGenOpts.SanitizeRecover.has(SanitizerKind::LocalBounds) + ? BoundsCheckingPass::ReportingMode::MinRuntime + : BoundsCheckingPass::ReportingMode::MinRuntimeAbort; + } else { + Mode = CodeGenOpts.SanitizeRecover.has(SanitizerKind::LocalBounds) + ? BoundsCheckingPass::ReportingMode::FullRuntime + : BoundsCheckingPass::ReportingMode::FullRuntimeAbort; + } + FPM.addPass(BoundsCheckingPass(Mode)); }); // Don't add sanitizers if we are here from ThinLTO PostLink. That already diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index d3fa5be6777ef..ba1cba291553b 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -52,11 +52,6 @@ using namespace clang; using namespace CodeGen; -// Experiment to make sanitizers easier to debug -static llvm::cl::opt ClSanitizeDebugDeoptimization( - "ubsan-unique-traps", llvm::cl::Optional, - llvm::cl::desc("Deoptimize traps for UBSAN so there is 1 trap per check.")); - // TODO: Introduce frontend options to enabled per sanitizers, similar to // `fsanitize-trap`. static llvm::cl::opt ClSanitizeGuardChecks( @@ -3581,8 +3576,7 @@ static void emitCheckHandlerCall(CodeGenFunction &CGF, llvm::AttributeList::FunctionIndex, B), /*Local=*/true); llvm::CallInst *HandlerCall = CGF.EmitNounwindRuntimeCall(Fn, FnArgs); - NoMerge = NoMerge || ClSanitizeDebugDeoptimization || - !CGF.CGM.getCodeGenOpts().OptimizationLevel || + NoMerge = NoMerge || !CGF.CGM.getCodeGenOpts().OptimizationLevel || (CGF.CurCodeDecl && CGF.CurCodeDecl->hasAttr()); if (NoMerge) HandlerCall->addFnAttr(llvm::Attribute::NoMerge); @@ -3915,8 +3909,7 @@ void CodeGenFunction::EmitTrapCheck(llvm::Value *Checked, llvm::BasicBlock *&TrapBB = TrapBBs[CheckHandlerID]; - NoMerge = NoMerge || ClSanitizeDebugDeoptimization || - !CGM.getCodeGenOpts().OptimizationLevel || + NoMerge = NoMerge || !CGM.getCodeGenOpts().OptimizationLevel || (CurCodeDecl && CurCodeDecl->hasAttr()); if (TrapBB && !NoMerge) { diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h index 85238ee34b447..edb87f9d5efdf 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.h +++ b/clang/lib/CodeGen/CGHLSLRuntime.h @@ -103,8 +103,9 @@ class CGHLSLRuntime { GENERATE_HLSL_INTRINSIC_FUNCTION(SClamp, sclamp) GENERATE_HLSL_INTRINSIC_FUNCTION(UClamp, uclamp) - GENERATE_HLSL_INTRINSIC_FUNCTION(CreateHandleFromBinding, handle_fromBinding) - GENERATE_HLSL_INTRINSIC_FUNCTION(BufferUpdateCounter, bufferUpdateCounter) + GENERATE_HLSL_INTRINSIC_FUNCTION(CreateHandleFromBinding, + resource_handlefrombinding) + GENERATE_HLSL_INTRINSIC_FUNCTION(BufferUpdateCounter, resource_updatecounter) GENERATE_HLSL_INTRINSIC_FUNCTION(GroupMemoryBarrierWithGroupSync, group_memory_barrier_with_group_sync) diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp index 6c604f44e283b..3974739d2abb4 100644 --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -473,6 +473,12 @@ void CodeGenFunction::EmitStmt(const Stmt *S, ArrayRef Attrs) { case Stmt::OpenACCWaitConstructClass: EmitOpenACCWaitConstruct(cast(*S)); break; + case Stmt::OpenACCInitConstructClass: + EmitOpenACCInitConstruct(cast(*S)); + break; + case Stmt::OpenACCShutdownConstructClass: + EmitOpenACCShutdownConstruct(cast(*S)); + break; } } diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 4d4139180e100..1a5c42f8f974d 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -4123,6 +4123,16 @@ class CodeGenFunction : public CodeGenTypeCache { // but in the future we will implement some sort of IR. } + void EmitOpenACCInitConstruct(const OpenACCInitConstruct &S) { + // TODO OpenACC: Implement this. It is currently implemented as a 'no-op', + // but in the future we will implement some sort of IR. + } + + void EmitOpenACCShutdownConstruct(const OpenACCShutdownConstruct &S) { + // TODO OpenACC: Implement this. It is currently implemented as a 'no-op', + // but in the future we will implement some sort of IR. + } + //===--------------------------------------------------------------------===// // LValue Expression Emission //===--------------------------------------------------------------------===// diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 5ac3eefbd6c51..c49f763148828 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -4283,7 +4283,7 @@ void CodeGenModule::emitMultiVersionFunctions() { getContext().forEachMultiversionedFunctionVersion( FD, [&](const FunctionDecl *CurFD) { llvm::SmallVector Feats; - bool IsDefined = CurFD->doesThisDeclarationHaveABody(); + bool IsDefined = CurFD->getDefinition() != nullptr; if (const auto *TA = CurFD->getAttr()) { assert(getTarget().getTriple().isX86() && "Unsupported target"); diff --git a/clang/lib/CodeGen/SanitizerMetadata.cpp b/clang/lib/CodeGen/SanitizerMetadata.cpp index 405124c8b8717..61fdf3399ff3c 100644 --- a/clang/lib/CodeGen/SanitizerMetadata.cpp +++ b/clang/lib/CodeGen/SanitizerMetadata.cpp @@ -145,6 +145,9 @@ void SanitizerMetadata::reportGlobal(llvm::GlobalVariable *GV, const VarDecl &D, for (auto *Attr : D.specific_attrs()) NoSanitizeMask |= Attr->getMask(); + if (D.hasExternalStorage()) + NoSanitizeMask |= SanitizerKind::Type; + return NoSanitizeMask; }; diff --git a/clang/lib/Driver/SanitizerArgs.cpp b/clang/lib/Driver/SanitizerArgs.cpp index 595bfb45f97f4..7726e464f2b45 100644 --- a/clang/lib/Driver/SanitizerArgs.cpp +++ b/clang/lib/Driver/SanitizerArgs.cpp @@ -27,9 +27,9 @@ using namespace llvm::opt; static const SanitizerMask NeedsUbsanRt = SanitizerKind::Undefined | SanitizerKind::Integer | - SanitizerKind::ImplicitConversion | SanitizerKind::Nullability | - SanitizerKind::CFI | SanitizerKind::FloatDivideByZero | - SanitizerKind::ObjCCast; + SanitizerKind::LocalBounds | SanitizerKind::ImplicitConversion | + SanitizerKind::Nullability | SanitizerKind::CFI | + SanitizerKind::FloatDivideByZero | SanitizerKind::ObjCCast; static const SanitizerMask NeedsUbsanCxxRt = SanitizerKind::Vptr | SanitizerKind::CFI; static const SanitizerMask NotAllowedWithTrap = SanitizerKind::Vptr; @@ -69,7 +69,8 @@ static const SanitizerMask TrappingSupported = SanitizerKind::LocalBounds | SanitizerKind::CFI | SanitizerKind::FloatDivideByZero | SanitizerKind::ObjCCast; static const SanitizerMask MergeDefault = SanitizerKind::Undefined; -static const SanitizerMask TrappingDefault = SanitizerKind::CFI; +static const SanitizerMask TrappingDefault = + SanitizerKind::CFI | SanitizerKind::LocalBounds; static const SanitizerMask CFIClasses = SanitizerKind::CFIVCall | SanitizerKind::CFINVCall | SanitizerKind::CFIMFCall | SanitizerKind::CFIDerivedCast | @@ -1106,10 +1107,10 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC, options::OPT_fno_sanitize_link_runtime, LinkRuntimes); // Parse -link-cxx-sanitizer flag. - LinkCXXRuntimes = Args.hasArg(options::OPT_fsanitize_link_cxx_runtime, - options::OPT_fno_sanitize_link_cxx_runtime, - LinkCXXRuntimes) || - D.CCCIsCXX(); + LinkCXXRuntimes = D.CCCIsCXX(); + LinkCXXRuntimes = + Args.hasFlag(options::OPT_fsanitize_link_cxx_runtime, + options::OPT_fno_sanitize_link_cxx_runtime, LinkCXXRuntimes); NeedsMemProfRt = Args.hasFlag(options::OPT_fmemory_profile, options::OPT_fmemory_profile_EQ, diff --git a/clang/lib/Driver/ToolChains/FreeBSD.cpp b/clang/lib/Driver/ToolChains/FreeBSD.cpp index be44fc4fe1a84..88a27e3192827 100644 --- a/clang/lib/Driver/ToolChains/FreeBSD.cpp +++ b/clang/lib/Driver/ToolChains/FreeBSD.cpp @@ -225,13 +225,7 @@ void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA, break; } - if (Triple.isRISCV64()) { - CmdArgs.push_back("-X"); - if (Args.hasArg(options::OPT_mno_relax)) - CmdArgs.push_back("--no-relax"); - } - - if (Triple.isLoongArch64()) { + if (Triple.isLoongArch64() || Triple.isRISCV64()) { CmdArgs.push_back("-X"); if (Args.hasArg(options::OPT_mno_relax)) CmdArgs.push_back("--no-relax"); diff --git a/clang/lib/Driver/ToolChains/PS4CPU.cpp b/clang/lib/Driver/ToolChains/PS4CPU.cpp index c2eeb8f513066..fd4c2f9bf68cd 100644 --- a/clang/lib/Driver/ToolChains/PS4CPU.cpp +++ b/clang/lib/Driver/ToolChains/PS4CPU.cpp @@ -361,9 +361,10 @@ void tools::PS5cpu::Linker::ConstructJob(Compilation &C, const JobAction &JA, if (StringRef Jobs = getLTOParallelism(Args, D); !Jobs.empty()) AddLTOFlag(Twine("jobs=") + Jobs); + Args.AddAllArgs(CmdArgs, options::OPT_L); TC.AddFilePathLibArgs(Args, CmdArgs); - Args.addAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group, - options::OPT_s, options::OPT_t}); + Args.addAllArgs(CmdArgs, + {options::OPT_T_Group, options::OPT_s, options::OPT_t}); if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle)) CmdArgs.push_back("--no-demangle"); diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 6a8caa23753f3..f2cfa7f49f62f 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -493,7 +493,7 @@ class AnnotatingParser { (CurrentToken->Next->is(tok::l_paren) || (CurrentToken->Next->is(tok::l_square) && (Line.MustBeDeclaration || - PrevNonComment->isTypeName(LangOpts))))) { + (PrevNonComment && PrevNonComment->isTypeName(LangOpts)))))) { OpeningParen.setType(OpeningParen.Next->is(tok::caret) ? TT_ObjCBlockLParen : TT_FunctionTypeLParen); diff --git a/clang/lib/Parse/ParseOpenACC.cpp b/clang/lib/Parse/ParseOpenACC.cpp index 5da34a2f5db92..ede409096548c 100644 --- a/clang/lib/Parse/ParseOpenACC.cpp +++ b/clang/lib/Parse/ParseOpenACC.cpp @@ -574,6 +574,8 @@ bool doesDirectiveHaveAssociatedStmt(OpenACCDirectiveKind DirKind) { case OpenACCDirectiveKind::EnterData: case OpenACCDirectiveKind::ExitData: case OpenACCDirectiveKind::Wait: + case OpenACCDirectiveKind::Init: + case OpenACCDirectiveKind::Shutdown: return false; case OpenACCDirectiveKind::Parallel: case OpenACCDirectiveKind::Serial: @@ -606,6 +608,8 @@ unsigned getOpenACCScopeFlags(OpenACCDirectiveKind DirKind) { case OpenACCDirectiveKind::ExitData: case OpenACCDirectiveKind::HostData: case OpenACCDirectiveKind::Wait: + case OpenACCDirectiveKind::Init: + case OpenACCDirectiveKind::Shutdown: return 0; case OpenACCDirectiveKind::Invalid: llvm_unreachable("Shouldn't be creating a scope for an invalid construct"); @@ -1081,6 +1085,7 @@ Parser::OpenACCClauseParseResult Parser::ParseOpenACCClauseParams( // TODO OpenACC: as we implement the 'rest' of the above, this 'if' should // be removed leaving just the 'setIntExprDetails'. if (ClauseKind == OpenACCClauseKind::NumWorkers || + ClauseKind == OpenACCClauseKind::DeviceNum || ClauseKind == OpenACCClauseKind::VectorLength) ParsedClause.setIntExprDetails(IntExpr.get()); diff --git a/clang/lib/Sema/CheckExprLifetime.cpp b/clang/lib/Sema/CheckExprLifetime.cpp index 843fdb4a65cd7..7109de03cadd1 100644 --- a/clang/lib/Sema/CheckExprLifetime.cpp +++ b/clang/lib/Sema/CheckExprLifetime.cpp @@ -582,6 +582,15 @@ static void visitFunctionCallArguments(IndirectLocalPath &Path, Expr *Call, // Temp().ptr; // Here ptr might not dangle. if (isa(Arg->IgnoreImpCasts())) return; + // Avoid false positives when the object is constructed from a conditional + // operator argument. A common case is: + // // 'ptr' might not be owned by the Owner object. + // std::string_view s = cond() ? Owner().ptr : sv; + if (const auto *Cond = + dyn_cast(Arg->IgnoreImpCasts()); + Cond && isPointerLikeType(Cond->getType())) + return; + auto ReturnType = Callee->getReturnType(); // Once we initialized a value with a non gsl-owner reference, it can no @@ -1091,14 +1100,13 @@ enum PathLifetimeKind { /// supposed to lifetime-extend along. static PathLifetimeKind shouldLifetimeExtendThroughPath(const IndirectLocalPath &Path) { - PathLifetimeKind Kind = PathLifetimeKind::Extend; for (auto Elem : Path) { if (Elem.Kind == IndirectLocalPathEntry::DefaultInit) return PathLifetimeKind::Extend; - else if (Elem.Kind != IndirectLocalPathEntry::LambdaCaptureInit) + if (Elem.Kind != IndirectLocalPathEntry::LambdaCaptureInit) return PathLifetimeKind::NoExtend; } - return Kind; + return PathLifetimeKind::Extend; } /// Find the range for the first interesting entry in the path at or after I. diff --git a/clang/lib/Sema/HLSLExternalSemaSource.cpp b/clang/lib/Sema/HLSLExternalSemaSource.cpp index f3362fb619afc..4faeda856c469 100644 --- a/clang/lib/Sema/HLSLExternalSemaSource.cpp +++ b/clang/lib/Sema/HLSLExternalSemaSource.cpp @@ -864,6 +864,10 @@ static BuiltinTypeDeclBuilder setupBufferType(CXXRecordDecl *Decl, Sema &S, .addDefaultHandleConstructor(); } +// This function is responsible for constructing the constraint expression for +// this concept: +// template concept is_typed_resource_element_compatible = +// __is_typed_resource_element_compatible; static Expr *constructTypedBufferConstraintExpr(Sema &S, SourceLocation NameLoc, TemplateTypeParmDecl *T) { ASTContext &Context = S.getASTContext(); @@ -885,8 +889,58 @@ static Expr *constructTypedBufferConstraintExpr(Sema &S, SourceLocation NameLoc, return TypedResExpr; } -static ConceptDecl *constructTypedBufferConceptDecl(Sema &S, - NamespaceDecl *NSD) { +// This function is responsible for constructing the constraint expression for +// this concept: +// template concept is_structured_resource_element_compatible = +// !__is_intangible && sizeof(T) >= 1; +static Expr *constructStructuredBufferConstraintExpr(Sema &S, + SourceLocation NameLoc, + TemplateTypeParmDecl *T) { + ASTContext &Context = S.getASTContext(); + + // Obtain the QualType for 'bool' + QualType BoolTy = Context.BoolTy; + + // Create a QualType that points to this TemplateTypeParmDecl + QualType TType = Context.getTypeDeclType(T); + + // Create a TypeSourceInfo for the template type parameter 'T' + TypeSourceInfo *TTypeSourceInfo = + Context.getTrivialTypeSourceInfo(TType, NameLoc); + + TypeTraitExpr *IsIntangibleExpr = + TypeTraitExpr::Create(Context, BoolTy, NameLoc, UTT_IsIntangibleType, + {TTypeSourceInfo}, NameLoc, true); + + // negate IsIntangibleExpr + UnaryOperator *NotIntangibleExpr = UnaryOperator::Create( + Context, IsIntangibleExpr, UO_LNot, BoolTy, VK_LValue, OK_Ordinary, + NameLoc, false, FPOptionsOverride()); + + // element types also may not be of 0 size + UnaryExprOrTypeTraitExpr *SizeOfExpr = new (Context) UnaryExprOrTypeTraitExpr( + UETT_SizeOf, TTypeSourceInfo, BoolTy, NameLoc, NameLoc); + + // Create a BinaryOperator that checks if the size of the type is not equal to + // 1 Empty structs have a size of 1 in HLSL, so we need to check for that + IntegerLiteral *rhs = IntegerLiteral::Create( + Context, llvm::APInt(Context.getTypeSize(Context.getSizeType()), 1, true), + Context.getSizeType(), NameLoc); + + BinaryOperator *SizeGEQOneExpr = + BinaryOperator::Create(Context, SizeOfExpr, rhs, BO_GE, BoolTy, VK_LValue, + OK_Ordinary, NameLoc, FPOptionsOverride()); + + // Combine the two constraints + BinaryOperator *CombinedExpr = BinaryOperator::Create( + Context, NotIntangibleExpr, SizeGEQOneExpr, BO_LAnd, BoolTy, VK_LValue, + OK_Ordinary, NameLoc, FPOptionsOverride()); + + return CombinedExpr; +} + +static ConceptDecl *constructBufferConceptDecl(Sema &S, NamespaceDecl *NSD, + bool isTypedBuffer) { ASTContext &Context = S.getASTContext(); DeclContext *DC = NSD->getDeclContext(); SourceLocation DeclLoc = SourceLocation(); @@ -907,9 +961,18 @@ static ConceptDecl *constructTypedBufferConceptDecl(Sema &S, TemplateParameterList *ConceptParams = TemplateParameterList::Create( Context, DeclLoc, DeclLoc, {T}, DeclLoc, nullptr); - DeclarationName DeclName = DeclarationName( - &Context.Idents.get("__is_typed_resource_element_compatible")); - Expr *ConstraintExpr = constructTypedBufferConstraintExpr(S, DeclLoc, T); + DeclarationName DeclName; + Expr *ConstraintExpr = nullptr; + + if (isTypedBuffer) { + DeclName = DeclarationName( + &Context.Idents.get("__is_typed_resource_element_compatible")); + ConstraintExpr = constructTypedBufferConstraintExpr(S, DeclLoc, T); + } else { + DeclName = DeclarationName( + &Context.Idents.get("__is_structured_resource_element_compatible")); + ConstraintExpr = constructStructuredBufferConstraintExpr(S, DeclLoc, T); + } // Create a ConceptDecl ConceptDecl *CD = @@ -927,8 +990,10 @@ static ConceptDecl *constructTypedBufferConceptDecl(Sema &S, void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() { CXXRecordDecl *Decl; - ConceptDecl *TypedBufferConcept = - constructTypedBufferConceptDecl(*SemaPtr, HLSLNamespace); + ConceptDecl *TypedBufferConcept = constructBufferConceptDecl( + *SemaPtr, HLSLNamespace, /*isTypedBuffer*/ true); + ConceptDecl *StructuredBufferConcept = constructBufferConceptDecl( + *SemaPtr, HLSLNamespace, /*isTypedBuffer*/ false); Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "RWBuffer") .addSimpleTemplateParams({"element_type"}, TypedBufferConcept) .finalizeForwardDeclaration(); @@ -944,7 +1009,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() { Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "RasterizerOrderedBuffer") - .addSimpleTemplateParams({"element_type"}) + .addSimpleTemplateParams({"element_type"}, StructuredBufferConcept) .finalizeForwardDeclaration(); onCompletion(Decl, [this](CXXRecordDecl *Decl) { setupBufferType(Decl, *SemaPtr, ResourceClass::UAV, @@ -956,7 +1021,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() { }); Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "StructuredBuffer") - .addSimpleTemplateParams({"element_type"}) + .addSimpleTemplateParams({"element_type"}, StructuredBufferConcept) .finalizeForwardDeclaration(); onCompletion(Decl, [this](CXXRecordDecl *Decl) { setupBufferType(Decl, *SemaPtr, ResourceClass::SRV, ResourceKind::RawBuffer, @@ -966,7 +1031,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() { }); Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "RWStructuredBuffer") - .addSimpleTemplateParams({"element_type"}) + .addSimpleTemplateParams({"element_type"}, StructuredBufferConcept) .finalizeForwardDeclaration(); onCompletion(Decl, [this](CXXRecordDecl *Decl) { setupBufferType(Decl, *SemaPtr, ResourceClass::UAV, ResourceKind::RawBuffer, @@ -979,7 +1044,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() { Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "AppendStructuredBuffer") - .addSimpleTemplateParams({"element_type"}) + .addSimpleTemplateParams({"element_type"}, StructuredBufferConcept) .finalizeForwardDeclaration(); onCompletion(Decl, [this](CXXRecordDecl *Decl) { setupBufferType(Decl, *SemaPtr, ResourceClass::UAV, ResourceKind::RawBuffer, @@ -990,7 +1055,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() { Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "ConsumeStructuredBuffer") - .addSimpleTemplateParams({"element_type"}) + .addSimpleTemplateParams({"element_type"}, StructuredBufferConcept) .finalizeForwardDeclaration(); onCompletion(Decl, [this](CXXRecordDecl *Decl) { setupBufferType(Decl, *SemaPtr, ResourceClass::UAV, ResourceKind::RawBuffer, @@ -1001,7 +1066,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() { Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "RasterizerOrderedStructuredBuffer") - .addSimpleTemplateParams({"element_type"}) + .addSimpleTemplateParams({"element_type"}, StructuredBufferConcept) .finalizeForwardDeclaration(); onCompletion(Decl, [this](CXXRecordDecl *Decl) { setupBufferType(Decl, *SemaPtr, ResourceClass::UAV, ResourceKind::RawBuffer, diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index a248a6b53b0d0..e703a62ff9cf1 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -5320,9 +5320,11 @@ bool Sema::BuiltinAssumeAligned(CallExpr *TheCall) { { ExprResult FirstArgResult = DefaultFunctionArrayLvalueConversion(FirstArg); - if (checkBuiltinArgument(*this, TheCall, 0)) + if (!FirstArgResult.get()->getType()->isPointerType()) { + Diag(TheCall->getBeginLoc(), diag::err_builtin_assume_aligned_invalid_arg) + << TheCall->getSourceRange(); return true; - /// In-place updation of FirstArg by checkBuiltinArgument is ignored. + } TheCall->setArg(0, FirstArgResult.get()); } @@ -8080,8 +8082,9 @@ static void CheckFormatString( } if (Type == Sema::FST_Printf || Type == Sema::FST_NSString || - Type == Sema::FST_FreeBSDKPrintf || Type == Sema::FST_OSLog || - Type == Sema::FST_OSTrace || Type == Sema::FST_Syslog) { + Type == Sema::FST_Kprintf || Type == Sema::FST_FreeBSDKPrintf || + Type == Sema::FST_OSLog || Type == Sema::FST_OSTrace || + Type == Sema::FST_Syslog) { CheckPrintfHandler H( S, FExpr, OrigFormatExpr, Type, firstDataArg, numDataArgs, (Type == Sema::FST_NSString || Type == Sema::FST_OSTrace), Str, APK, @@ -8090,7 +8093,7 @@ static void CheckFormatString( if (!analyze_format_string::ParsePrintfString( H, Str, Str + StrLen, S.getLangOpts(), S.Context.getTargetInfo(), - Type == Sema::FST_FreeBSDKPrintf)) + Type == Sema::FST_Kprintf || Type == Sema::FST_FreeBSDKPrintf)) H.DoneProcessing(); } else if (Type == Sema::FST_Scanf) { CheckScanfHandler H(S, FExpr, OrigFormatExpr, Type, firstDataArg, diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 55e891e3acf20..4001c4d263f1d 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -11073,9 +11073,9 @@ bool Sema::shouldLinkDependentDeclWithPrevious(Decl *D, Decl *PrevDecl) { static bool CheckMultiVersionValue(Sema &S, const FunctionDecl *FD) { const auto *TA = FD->getAttr(); const auto *TVA = FD->getAttr(); - assert( - (TA || TVA) && - "MultiVersion candidate requires a target or target_version attribute"); + + assert((TA || TVA) && "Expecting target or target_version attribute"); + const TargetInfo &TargetInfo = S.Context.getTargetInfo(); enum ErrType { Feature = 0, Architecture = 1 }; @@ -11372,10 +11372,6 @@ static bool CheckMultiVersionFirstFunction(Sema &S, FunctionDecl *FD) { // otherwise it is treated as a normal function. if (TA && !TA->isDefaultVersion()) return false; - // The target_version attribute only causes Multiversioning if this - // declaration is NOT the default version. - if (TVA && TVA->isDefaultVersion()) - return false; if ((TA || TVA) && CheckMultiVersionValue(S, FD)) { FD->setInvalidDecl(); @@ -11422,26 +11418,24 @@ static bool CheckDeclarationCausesMultiVersioning(Sema &S, FunctionDecl *OldFD, LookupResult &Previous) { assert(!OldFD->isMultiVersion() && "Unexpected MultiVersion"); + const auto *NewTA = NewFD->getAttr(); + const auto *OldTA = OldFD->getAttr(); + const auto *NewTVA = NewFD->getAttr(); + const auto *OldTVA = OldFD->getAttr(); + + assert((NewTA || NewTVA) && "Excpecting target or target_version attribute"); + // The definitions should be allowed in any order. If we have discovered // a new target version and the preceeding was the default, then add the // corresponding attribute to it. patchDefaultTargetVersion(NewFD, OldFD); - const auto *NewTA = NewFD->getAttr(); - const auto *NewTVA = NewFD->getAttr(); - const auto *OldTA = OldFD->getAttr(); - // If the old decl is NOT MultiVersioned yet, and we don't cause that // to change, this is a simple redeclaration. if (NewTA && !NewTA->isDefaultVersion() && (!OldTA || OldTA->getFeaturesStr() == NewTA->getFeaturesStr())) return false; - // The target_version attribute only causes Multiversioning if this - // declaration is NOT the default version. - if (NewTVA && NewTVA->isDefaultVersion()) - return false; - // Otherwise, this decl causes MultiVersioning. if (CheckMultiVersionAdditionalRules(S, OldFD, NewFD, true, NewTVA ? MultiVersionKind::TargetVersion @@ -11456,7 +11450,8 @@ static bool CheckDeclarationCausesMultiVersioning(Sema &S, FunctionDecl *OldFD, } // If this is 'default', permit the forward declaration. - if (NewTA && NewTA->isDefaultVersion() && !OldTA) { + if ((NewTA && NewTA->isDefaultVersion() && !OldTA) || + (NewTVA && NewTVA->isDefaultVersion() && !OldTVA)) { Redeclaration = true; OldDecl = OldFD; OldFD->setIsMultiVersion(); @@ -11464,7 +11459,7 @@ static bool CheckDeclarationCausesMultiVersioning(Sema &S, FunctionDecl *OldFD, return false; } - if (CheckMultiVersionValue(S, OldFD)) { + if ((OldTA || OldTVA) && CheckMultiVersionValue(S, OldFD)) { S.Diag(NewFD->getLocation(), diag::note_multiversioning_caused_here); NewFD->setInvalidDecl(); return true; @@ -11761,9 +11756,7 @@ static bool CheckMultiVersionAdditionalDecl( // Else, this is simply a non-redecl case. Checking the 'value' is only // necessary in the Target case, since The CPUSpecific/Dispatch cases are // handled in the attribute adding step. - if ((NewMVKind == MultiVersionKind::TargetVersion || - NewMVKind == MultiVersionKind::Target) && - CheckMultiVersionValue(S, NewFD)) { + if ((NewTA || NewTVA) && CheckMultiVersionValue(S, NewFD)) { NewFD->setInvalidDecl(); return true; } @@ -11799,6 +11792,12 @@ static bool CheckMultiVersionAdditionalDecl( static bool CheckMultiVersionFunction(Sema &S, FunctionDecl *NewFD, bool &Redeclaration, NamedDecl *&OldDecl, LookupResult &Previous) { + const TargetInfo &TI = S.getASTContext().getTargetInfo(); + + // Check if FMV is disabled. + if (TI.getTriple().isAArch64() && !TI.hasFeature("fmv")) + return false; + const auto *NewTA = NewFD->getAttr(); const auto *NewTVA = NewFD->getAttr(); const auto *NewCPUDisp = NewFD->getAttr(); @@ -11821,14 +11820,12 @@ static bool CheckMultiVersionFunction(Sema &S, FunctionDecl *NewFD, return false; } - const llvm::Triple &T = S.getASTContext().getTargetInfo().getTriple(); - // Target attribute on AArch64 is not used for multiversioning - if (NewTA && T.isAArch64()) + if (NewTA && TI.getTriple().isAArch64()) return false; // Target attribute on RISCV is not used for multiversioning - if (NewTA && T.isRISCV()) + if (NewTA && TI.getTriple().isRISCV()) return false; if (!OldDecl || !OldDecl->getAsFunction() || diff --git a/clang/lib/Sema/SemaExceptionSpec.cpp b/clang/lib/Sema/SemaExceptionSpec.cpp index 505cc5e153fa7..ac3666394d0e8 100644 --- a/clang/lib/Sema/SemaExceptionSpec.cpp +++ b/clang/lib/Sema/SemaExceptionSpec.cpp @@ -1399,6 +1399,8 @@ CanThrowResult Sema::canThrow(const Stmt *S) { case Stmt::OpenACCEnterDataConstructClass: case Stmt::OpenACCExitDataConstructClass: case Stmt::OpenACCWaitConstructClass: + case Stmt::OpenACCInitConstructClass: + case Stmt::OpenACCShutdownConstructClass: // These expressions can never throw. return CT_Cannot; diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index e06a092177ef0..24f7d27c69115 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -11789,10 +11789,11 @@ static bool checkForArray(const Expr *E) { /// Detect patterns ptr + size >= ptr and ptr + size < ptr, where ptr is a /// pointer and size is an unsigned integer. Return whether the result is /// always true/false. -static std::optional isTautologicalBoundsCheck(const Expr *LHS, +static std::optional isTautologicalBoundsCheck(Sema &S, const Expr *LHS, const Expr *RHS, BinaryOperatorKind Opc) { - if (!LHS->getType()->isPointerType()) + if (!LHS->getType()->isPointerType() || + S.getLangOpts().isSignedOverflowDefined()) return std::nullopt; // Canonicalize to >= or < predicate. @@ -11940,7 +11941,7 @@ static void diagnoseTautologicalComparison(Sema &S, SourceLocation Loc, << 1 /*array comparison*/ << Result); } else if (std::optional Res = - isTautologicalBoundsCheck(LHS, RHS, Opc)) { + isTautologicalBoundsCheck(S, LHS, RHS, Opc)) { S.DiagRuntimeBehavior(Loc, nullptr, S.PDiag(diag::warn_comparison_always) << 2 /*pointer comparison*/ diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp index bcc1b92ffdec7..d130e8b86bc56 100644 --- a/clang/lib/Sema/SemaExprMember.cpp +++ b/clang/lib/Sema/SemaExprMember.cpp @@ -434,8 +434,11 @@ CheckExtVectorComponent(Sema &S, QualType baseType, ExprValueKind &VK, if (!HalvingSwizzle && *compStr) { // We didn't get to the end of the string. This means the component names // didn't come from the same set *or* we encountered an illegal name. - S.Diag(OpLoc, diag::err_ext_vector_component_name_illegal) - << StringRef(compStr, 1) << SourceRange(CompLoc); + size_t Offset = compStr - CompName->getNameStart() + 1; + char Fmt[3] = {'\'', *compStr, '\''}; + S.Diag(OpLoc.getLocWithOffset(Offset), + diag::err_ext_vector_component_name_illegal) + << StringRef(Fmt, 3) << SourceRange(CompLoc); return QualType(); } diff --git a/clang/lib/Sema/SemaOpenACC.cpp b/clang/lib/Sema/SemaOpenACC.cpp index aa9097bfa1743..42bbdf1f3f9fa 100644 --- a/clang/lib/Sema/SemaOpenACC.cpp +++ b/clang/lib/Sema/SemaOpenACC.cpp @@ -444,6 +444,17 @@ bool doesClauseApplyToDirective(OpenACCDirectiveKind DirectiveKind, } } + case OpenACCClauseKind::DeviceNum: { + switch (DirectiveKind) { + case OpenACCDirectiveKind::Init: + case OpenACCDirectiveKind::Shutdown: + case OpenACCDirectiveKind::Set: + return true; + default: + return false; + } + } + case OpenACCClauseKind::UseDevice: { switch (DirectiveKind) { case OpenACCDirectiveKind::HostData: @@ -574,7 +585,9 @@ bool checkValidAfterDeviceType( bool isDirectiveKindImplemented(OpenACCDirectiveKind DK) { return isOpenACCComputeDirectiveKind(DK) || isOpenACCCombinedDirectiveKind(DK) || isOpenACCDataDirectiveKind(DK) || - DK == OpenACCDirectiveKind::Loop || DK == OpenACCDirectiveKind::Wait; + DK == OpenACCDirectiveKind::Loop || DK == OpenACCDirectiveKind::Wait || + DK == OpenACCDirectiveKind::Init || + DK == OpenACCDirectiveKind::Shutdown; } class SemaOpenACCClauseVisitor { @@ -699,7 +712,10 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitIfClause( // sense. Prose DOES exist for 'data' and 'host_data', 'enter data' and 'exit // data' both don't, but other implmementations do this. OpenACC issue 519 // filed for the latter two. - if (checkAlreadyHasClauseOfKind(SemaRef, ExistingClauses, Clause)) + // GCC allows this on init/shutdown, presumably for good reason, so we do too. + if (Clause.getDirectiveKind() != OpenACCDirectiveKind::Init && + Clause.getDirectiveKind() != OpenACCDirectiveKind::Shutdown && + checkAlreadyHasClauseOfKind(SemaRef, ExistingClauses, Clause)) return nullptr; // The parser has ensured that we have a proper condition expr, so there @@ -940,6 +956,20 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitAsyncClause( Clause.getEndLoc()); } +OpenACCClause *SemaOpenACCClauseVisitor::VisitDeviceNumClause( + SemaOpenACC::OpenACCParsedClause &Clause) { + // Restrictions only properly implemented on certain constructs, so skip/treat + // as unimplemented in those cases. + if (!isDirectiveKindImplemented(Clause.getDirectiveKind())) + return isNotImplemented(); + + assert(Clause.getNumIntExprs() == 1 && + "Invalid number of expressions for device_num"); + return OpenACCDeviceNumClause::Create( + Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getIntExprs()[0], + Clause.getEndLoc()); +} + OpenACCClause *SemaOpenACCClauseVisitor::VisitPrivateClause( SemaOpenACC::OpenACCParsedClause &Clause) { // ActOnVar ensured that everything is a valid variable reference, so there @@ -1868,6 +1898,8 @@ bool PreserveLoopRAIIDepthInAssociatedStmtRAII(OpenACCDirectiveKind DK) { case OpenACCDirectiveKind::EnterData: case OpenACCDirectiveKind::ExitData: case OpenACCDirectiveKind::Wait: + case OpenACCDirectiveKind::Init: + case OpenACCDirectiveKind::Shutdown: llvm_unreachable("Doesn't have an associated stmt"); default: case OpenACCDirectiveKind::Invalid: @@ -2294,6 +2326,8 @@ void SemaOpenACC::ActOnConstruct(OpenACCDirectiveKind K, case OpenACCDirectiveKind::EnterData: case OpenACCDirectiveKind::ExitData: case OpenACCDirectiveKind::HostData: + case OpenACCDirectiveKind::Init: + case OpenACCDirectiveKind::Shutdown: // Nothing to do here, there is no real legalization that needs to happen // here as these constructs do not take any arguments. break; @@ -3682,6 +3716,14 @@ StmtResult SemaOpenACC::ActOnEndStmtDirective( getASTContext(), StartLoc, DirLoc, LParenLoc, Exprs.front(), MiscLoc, Exprs.drop_front(), RParenLoc, EndLoc, Clauses); } + case OpenACCDirectiveKind::Init: { + return OpenACCInitConstruct::Create(getASTContext(), StartLoc, DirLoc, + EndLoc, Clauses); + } + case OpenACCDirectiveKind::Shutdown: { + return OpenACCShutdownConstruct::Create(getASTContext(), StartLoc, DirLoc, + EndLoc, Clauses); + } } llvm_unreachable("Unhandled case in directive handling?"); } @@ -3695,6 +3737,8 @@ StmtResult SemaOpenACC::ActOnAssociatedStmt( case OpenACCDirectiveKind::EnterData: case OpenACCDirectiveKind::ExitData: case OpenACCDirectiveKind::Wait: + case OpenACCDirectiveKind::Init: + case OpenACCDirectiveKind::Shutdown: llvm_unreachable( "these don't have associated statements, so shouldn't get here"); case OpenACCDirectiveKind::Parallel: diff --git a/clang/lib/Sema/SemaTemplateVariadic.cpp b/clang/lib/Sema/SemaTemplateVariadic.cpp index 88a21240e1c80..c8452db6bc901 100644 --- a/clang/lib/Sema/SemaTemplateVariadic.cpp +++ b/clang/lib/Sema/SemaTemplateVariadic.cpp @@ -780,7 +780,7 @@ bool Sema::CheckParameterPacksForExpansion( } // Determine the size of this argument pack. - unsigned NewPackSize; + unsigned NewPackSize, PendingPackExpansionSize = 0; if (IsVarDeclPack) { // Figure out whether we're instantiating to an argument pack or not. typedef LocalInstantiationScope::DeclArgumentPack DeclArgumentPack; @@ -808,7 +808,25 @@ bool Sema::CheckParameterPacksForExpansion( } // Determine the size of the argument pack. - NewPackSize = TemplateArgs(Depth, Index).pack_size(); + ArrayRef Pack = + TemplateArgs(Depth, Index).getPackAsArray(); + NewPackSize = Pack.size(); + PendingPackExpansionSize = + llvm::count_if(Pack, [](const TemplateArgument &TA) { + if (!TA.isPackExpansion()) + return false; + + if (TA.getKind() == TemplateArgument::Type) + return !TA.getAsType() + ->getAs() + ->getNumExpansions(); + + if (TA.getKind() == TemplateArgument::Expression) + return !cast(TA.getAsExpr()) + ->getNumExpansions(); + + return !TA.getNumTemplateExpansions(); + }); } // C++0x [temp.arg.explicit]p9: @@ -831,7 +849,7 @@ bool Sema::CheckParameterPacksForExpansion( } if (!NumExpansions) { - // The is the first pack we've seen for which we have an argument. + // This is the first pack we've seen for which we have an argument. // Record it. NumExpansions = NewPackSize; FirstPack.first = Name; @@ -841,17 +859,44 @@ bool Sema::CheckParameterPacksForExpansion( } if (NewPackSize != *NumExpansions) { + // In some cases, we might be handling packs with unexpanded template + // arguments. For example, this can occur when substituting into a type + // alias declaration that uses its injected template parameters as + // arguments: + // + // template struct S { + // template using Alias = S; + // }; + // + // Consider an instantiation attempt like 'S::Alias', where + // Pack comes from another template parameter. 'S' is first + // instantiated, expanding the outer pack 'Outer' to . The alias + // declaration is accordingly substituted, leaving the template arguments + // as unexpanded + // ''. + // + // Since we have no idea of the size of '' until its expansion, + // we shouldn't assume its pack size for validation. However if we are + // certain that there are extra arguments beyond unexpanded packs, in + // which case the pack size is already larger than the previous expansion, + // we can complain that before instantiation. + unsigned LeastNewPackSize = NewPackSize - PendingPackExpansionSize; + if (PendingPackExpansionSize && LeastNewPackSize <= *NumExpansions) { + ShouldExpand = false; + continue; + } // C++0x [temp.variadic]p5: // All of the parameter packs expanded by a pack expansion shall have // the same number of arguments specified. if (HaveFirstPack) Diag(EllipsisLoc, diag::err_pack_expansion_length_conflict) - << FirstPack.first << Name << *NumExpansions << NewPackSize + << FirstPack.first << Name << *NumExpansions + << (LeastNewPackSize != NewPackSize) << LeastNewPackSize << SourceRange(FirstPack.second) << SourceRange(ParmPack.second); else Diag(EllipsisLoc, diag::err_pack_expansion_length_conflict_multilevel) - << Name << *NumExpansions << NewPackSize - << SourceRange(ParmPack.second); + << Name << *NumExpansions << (LeastNewPackSize != NewPackSize) + << LeastNewPackSize << SourceRange(ParmPack.second); return true; } } diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index c097465374cba..5d43d98ce49e4 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -4151,6 +4151,24 @@ class TreeTransform { SourceLocation{}, {}, SourceLocation{}, EndLoc, Clauses, StrBlock); } + StmtResult RebuildOpenACCInitConstruct(SourceLocation BeginLoc, + SourceLocation DirLoc, + SourceLocation EndLoc, + ArrayRef Clauses) { + return getSema().OpenACC().ActOnEndStmtDirective( + OpenACCDirectiveKind::Init, BeginLoc, DirLoc, SourceLocation{}, + SourceLocation{}, {}, SourceLocation{}, EndLoc, Clauses, {}); + } + + StmtResult + RebuildOpenACCShutdownConstruct(SourceLocation BeginLoc, + SourceLocation DirLoc, SourceLocation EndLoc, + ArrayRef Clauses) { + return getSema().OpenACC().ActOnEndStmtDirective( + OpenACCDirectiveKind::Shutdown, BeginLoc, DirLoc, SourceLocation{}, + SourceLocation{}, {}, SourceLocation{}, EndLoc, Clauses, {}); + } + StmtResult RebuildOpenACCWaitConstruct( SourceLocation BeginLoc, SourceLocation DirLoc, SourceLocation LParenLoc, Expr *DevNumExpr, SourceLocation QueuesLoc, ArrayRef QueueIdExprs, @@ -11859,6 +11877,29 @@ void OpenACCClauseTransform::VisitNumWorkersClause( ParsedClause.getEndLoc()); } +template +void OpenACCClauseTransform::VisitDeviceNumClause ( + const OpenACCDeviceNumClause &C) { + Expr *IntExpr = const_cast(C.getIntExpr()); + assert(IntExpr && "device_num clause constructed with invalid int expr"); + + ExprResult Res = Self.TransformExpr(IntExpr); + if (!Res.isUsable()) + return; + + Res = Self.getSema().OpenACC().ActOnIntExpr(OpenACCDirectiveKind::Invalid, + C.getClauseKind(), + C.getBeginLoc(), Res.get()); + if (!Res.isUsable()) + return; + + ParsedClause.setIntExprDetails(Res.get()); + NewClause = OpenACCDeviceNumClause::Create( + Self.getSema().getASTContext(), ParsedClause.getBeginLoc(), + ParsedClause.getLParenLoc(), ParsedClause.getIntExprs()[0], + ParsedClause.getEndLoc()); +} + template void OpenACCClauseTransform::VisitVectorLengthClause( const OpenACCVectorLengthClause &C) { @@ -12348,6 +12389,40 @@ StmtResult TreeTransform::TransformOpenACCHostDataConstruct( TransformedClauses, StrBlock); } +template +StmtResult +TreeTransform::TransformOpenACCInitConstruct(OpenACCInitConstruct *C) { + getSema().OpenACC().ActOnConstruct(C->getDirectiveKind(), C->getBeginLoc()); + + llvm::SmallVector TransformedClauses = + getDerived().TransformOpenACCClauseList(C->getDirectiveKind(), + C->clauses()); + if (getSema().OpenACC().ActOnStartStmtDirective( + C->getDirectiveKind(), C->getBeginLoc(), TransformedClauses)) + return StmtError(); + + return getDerived().RebuildOpenACCInitConstruct( + C->getBeginLoc(), C->getDirectiveLoc(), C->getEndLoc(), + TransformedClauses); +} + +template +StmtResult TreeTransform::TransformOpenACCShutdownConstruct( + OpenACCShutdownConstruct *C) { + getSema().OpenACC().ActOnConstruct(C->getDirectiveKind(), C->getBeginLoc()); + + llvm::SmallVector TransformedClauses = + getDerived().TransformOpenACCClauseList(C->getDirectiveKind(), + C->clauses()); + if (getSema().OpenACC().ActOnStartStmtDirective( + C->getDirectiveKind(), C->getBeginLoc(), TransformedClauses)) + return StmtError(); + + return getDerived().RebuildOpenACCShutdownConstruct( + C->getBeginLoc(), C->getDirectiveLoc(), C->getEndLoc(), + TransformedClauses); +} + template StmtResult TreeTransform::TransformOpenACCWaitConstruct(OpenACCWaitConstruct *C) { diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 21f6b2ecc58c4..15160b0751f83 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -12405,6 +12405,12 @@ OpenACCClause *ASTRecordReader::readOpenACCClause() { return OpenACCNumWorkersClause::Create(getContext(), BeginLoc, LParenLoc, IntExpr, EndLoc); } + case OpenACCClauseKind::DeviceNum: { + SourceLocation LParenLoc = readSourceLocation(); + Expr *IntExpr = readSubExpr(); + return OpenACCDeviceNumClause::Create(getContext(), BeginLoc, LParenLoc, + IntExpr, EndLoc); + } case OpenACCClauseKind::VectorLength: { SourceLocation LParenLoc = readSourceLocation(); Expr *IntExpr = readSubExpr(); @@ -12594,7 +12600,6 @@ OpenACCClause *ASTRecordReader::readOpenACCClause() { case OpenACCClauseKind::Host: case OpenACCClauseKind::Link: case OpenACCClauseKind::Bind: - case OpenACCClauseKind::DeviceNum: case OpenACCClauseKind::DefaultAsync: case OpenACCClauseKind::Invalid: llvm_unreachable("Clause serialization not yet implemented"); diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index 8fe0412706ce3..9e8cf19a6f0f7 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -2865,6 +2865,16 @@ void ASTStmtReader::VisitOpenACCExitDataConstruct(OpenACCExitDataConstruct *S) { VisitOpenACCConstructStmt(S); } +void ASTStmtReader::VisitOpenACCInitConstruct(OpenACCInitConstruct *S) { + VisitStmt(S); + VisitOpenACCConstructStmt(S); +} + +void ASTStmtReader::VisitOpenACCShutdownConstruct(OpenACCShutdownConstruct *S) { + VisitStmt(S); + VisitOpenACCConstructStmt(S); +} + void ASTStmtReader::VisitOpenACCHostDataConstruct(OpenACCHostDataConstruct *S) { VisitStmt(S); VisitOpenACCAssociatedStmtConstruct(S); @@ -4387,6 +4397,16 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { S = OpenACCWaitConstruct::CreateEmpty(Context, NumExprs, NumClauses); break; } + case STMT_OPENACC_INIT_CONSTRUCT: { + unsigned NumClauses = Record[ASTStmtReader::NumStmtFields]; + S = OpenACCInitConstruct::CreateEmpty(Context, NumClauses); + break; + } + case STMT_OPENACC_SHUTDOWN_CONSTRUCT: { + unsigned NumClauses = Record[ASTStmtReader::NumStmtFields]; + S = OpenACCShutdownConstruct::CreateEmpty(Context, NumClauses); + break; + } case EXPR_REQUIRES: { unsigned numLocalParameters = Record[ASTStmtReader::NumExprFields]; unsigned numRequirement = Record[ASTStmtReader::NumExprFields + 1]; diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 6db2262a7952e..4a6027943072c 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -8326,6 +8326,12 @@ void ASTRecordWriter::writeOpenACCClause(const OpenACCClause *C) { AddStmt(E); return; } + case OpenACCClauseKind::DeviceNum: { + const auto *DNC = cast(C); + writeSourceLocation(DNC->getLParenLoc()); + AddStmt(const_cast(DNC->getIntExpr())); + return; + } case OpenACCClauseKind::NumWorkers: { const auto *NWC = cast(C); writeSourceLocation(NWC->getLParenLoc()); @@ -8522,7 +8528,6 @@ void ASTRecordWriter::writeOpenACCClause(const OpenACCClause *C) { case OpenACCClauseKind::Host: case OpenACCClauseKind::Link: case OpenACCClauseKind::Bind: - case OpenACCClauseKind::DeviceNum: case OpenACCClauseKind::DefaultAsync: case OpenACCClauseKind::Invalid: llvm_unreachable("Clause serialization not yet implemented"); diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index f13443d18b612..1d42b43c3e2ca 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -2945,6 +2945,18 @@ void ASTStmtWriter::VisitOpenACCExitDataConstruct(OpenACCExitDataConstruct *S) { Code = serialization::STMT_OPENACC_EXIT_DATA_CONSTRUCT; } +void ASTStmtWriter::VisitOpenACCInitConstruct(OpenACCInitConstruct *S) { + VisitStmt(S); + VisitOpenACCConstructStmt(S); + Code = serialization::STMT_OPENACC_INIT_CONSTRUCT; +} + +void ASTStmtWriter::VisitOpenACCShutdownConstruct(OpenACCShutdownConstruct *S) { + VisitStmt(S); + VisitOpenACCConstructStmt(S); + Code = serialization::STMT_OPENACC_SHUTDOWN_CONSTRUCT; +} + void ASTStmtWriter::VisitOpenACCHostDataConstruct(OpenACCHostDataConstruct *S) { VisitStmt(S); VisitOpenACCAssociatedStmtConstruct(S); diff --git a/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp b/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp index 3f837564cf47c..6422933c8828a 100644 --- a/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp @@ -22,6 +22,7 @@ #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/PathSensitive/DynamicExtent.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" +#include "llvm/ADT/APSInt.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/FormatVariadic.h" #include "llvm/Support/raw_ostream.h" @@ -241,26 +242,25 @@ computeOffset(ProgramStateRef State, SValBuilder &SVB, SVal Location) { static std::pair getSimplifiedOffsets(NonLoc offset, nonloc::ConcreteInt extent, SValBuilder &svalBuilder) { + const llvm::APSInt &extentVal = extent.getValue(); std::optional SymVal = offset.getAs(); if (SymVal && SymVal->isExpression()) { if (const SymIntExpr *SIE = dyn_cast(SymVal->getSymbol())) { - llvm::APSInt constant = - APSIntType(extent.getValue()).convert(SIE->getRHS()); + llvm::APSInt constant = APSIntType(extentVal).convert(SIE->getRHS()); switch (SIE->getOpcode()) { case BO_Mul: // The constant should never be 0 here, becasue multiplication by zero // is simplified by the engine. - if ((extent.getValue() % constant) != 0) + if ((extentVal % constant) != 0) return std::pair(offset, extent); else return getSimplifiedOffsets( nonloc::SymbolVal(SIE->getLHS()), - svalBuilder.makeIntVal(extent.getValue() / constant), - svalBuilder); + svalBuilder.makeIntVal(extentVal / constant), svalBuilder); case BO_Add: return getSimplifiedOffsets( nonloc::SymbolVal(SIE->getLHS()), - svalBuilder.makeIntVal(extent.getValue() - constant), svalBuilder); + svalBuilder.makeIntVal(extentVal - constant), svalBuilder); default: break; } @@ -363,7 +363,7 @@ static std::string getRegionName(const SubRegion *Region) { static std::optional getConcreteValue(NonLoc SV) { if (auto ConcreteVal = SV.getAs()) { - return ConcreteVal->getValue().tryExtValue(); + return ConcreteVal->getValue()->tryExtValue(); } return std::nullopt; } diff --git a/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp b/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp index 80f128b917b20..cc089767adfee 100644 --- a/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp @@ -457,7 +457,7 @@ void CFNumberChecker::checkPreStmt(const CallExpr *CE, if (!V) return; - uint64_t NumberKind = V->getValue().getLimitedValue(); + uint64_t NumberKind = V->getValue()->getLimitedValue(); std::optional OptCFNumberSize = GetCFNumberSize(Ctx, NumberKind); // FIXME: In some cases we can emit an error. diff --git a/clang/lib/StaticAnalyzer/Checkers/BitwiseShiftChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/BitwiseShiftChecker.cpp index 17f1214195b3e..ed26ddea93a26 100644 --- a/clang/lib/StaticAnalyzer/Checkers/BitwiseShiftChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/BitwiseShiftChecker.cpp @@ -252,11 +252,11 @@ BugReportPtr BitwiseShiftValidator::checkLeftShiftOverflow() { // We should have already reported a bug if the left operand of the shift was // negative, so it cannot be negative here. - assert(Left->getValue().isNonNegative()); + assert(Left->getValue()->isNonNegative()); const unsigned LeftAvailableBitWidth = LeftBitWidth - static_cast(ShouldPreserveSignBit); - const unsigned UsedBitsInLeftOperand = Left->getValue().getActiveBits(); + const unsigned UsedBitsInLeftOperand = Left->getValue()->getActiveBits(); assert(LeftBitWidth >= UsedBitsInLeftOperand); const unsigned MaximalAllowedShift = LeftAvailableBitWidth - UsedBitsInLeftOperand; @@ -275,9 +275,9 @@ BugReportPtr BitwiseShiftValidator::checkLeftShiftOverflow() { if (const auto ConcreteRight = Right.getAs()) { // Here ConcreteRight must contain a small non-negative integer, because // otherwise one of the earlier checks should've reported a bug. - const unsigned RHS = ConcreteRight->getValue().getExtValue(); + const int64_t RHS = ConcreteRight->getValue()->getExtValue(); assert(RHS > MaximalAllowedShift); - const unsigned OverflownBits = RHS - MaximalAllowedShift; + const int64_t OverflownBits = RHS - MaximalAllowedShift; ShortMsg = formatv( "The shift '{0} << {1}' overflows the capacity of '{2}'", Left->getValue(), ConcreteRight->getValue(), LHSTy.getAsString()); diff --git a/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp index 4ab0c4c9ae7b7..cfdd3c9faa360 100644 --- a/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp @@ -155,12 +155,14 @@ BuiltinFunctionChecker::checkOverflow(CheckerContext &C, SVal RetVal, unsigned BitWidth = C.getASTContext().getIntWidth(Res); bool IsUnsigned = Res->isUnsignedIntegerType(); + SValBuilder &SVB = C.getSValBuilder(); + BasicValueFactory &VF = SVB.getBasicValueFactory(); + auto MinValType = llvm::APSInt::getMinValue(BitWidth, IsUnsigned); auto MaxValType = llvm::APSInt::getMaxValue(BitWidth, IsUnsigned); - nonloc::ConcreteInt MinVal{MinValType}; - nonloc::ConcreteInt MaxVal{MaxValType}; + nonloc::ConcreteInt MinVal{VF.getValue(MinValType)}; + nonloc::ConcreteInt MaxVal{VF.getValue(MaxValType)}; - SValBuilder &SVB = C.getSValBuilder(); ProgramStateRef State = C.getState(); SVal IsLeMax = SVB.evalBinOp(State, BO_LE, RetVal, MaxVal, Res); SVal IsGeMin = SVB.evalBinOp(State, BO_GE, RetVal, MinVal, Res); diff --git a/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp index 21a2d8828249d..1a14f38e34f0e 100644 --- a/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp @@ -1025,8 +1025,8 @@ SVal CStringChecker::getCStringLengthForRegion(CheckerContext &C, BasicValueFactory &BVF = svalBuilder.getBasicValueFactory(); const llvm::APSInt &maxValInt = BVF.getMaxValue(sizeTy); llvm::APSInt fourInt = APSIntType(maxValInt).getValue(4); - const llvm::APSInt *maxLengthInt = BVF.evalAPSInt(BO_Div, maxValInt, - fourInt); + std::optional maxLengthInt = + BVF.evalAPSInt(BO_Div, maxValInt, fourInt); NonLoc maxLength = svalBuilder.makeIntVal(*maxLengthInt); SVal evalLength = svalBuilder.evalBinOpNN(state, BO_LE, *strLn, maxLength, svalBuilder.getConditionType()); diff --git a/clang/lib/StaticAnalyzer/Checkers/CheckPlacementNew.cpp b/clang/lib/StaticAnalyzer/Checkers/CheckPlacementNew.cpp index 1b89951397cfb..3a66b0f11eb2e 100644 --- a/clang/lib/StaticAnalyzer/Checkers/CheckPlacementNew.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/CheckPlacementNew.cpp @@ -124,7 +124,7 @@ bool PlacementNewChecker::checkPlaceCapacityIsSufficient( "requires {1} bytes. Current overhead requires the size of {2} " "bytes", SizeOfPlaceCI->getValue(), SizeOfTargetCI->getValue(), - SizeOfPlaceCI->getValue() - SizeOfTargetCI->getValue())); + *SizeOfPlaceCI->getValue().get() - SizeOfTargetCI->getValue())); else if (IsArrayTypeAllocated && SizeOfPlaceCI->getValue() == SizeOfTargetCI->getValue()) Msg = std::string(llvm::formatv( diff --git a/clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp index 3096999e9fd16..5534ef86a7bef 100644 --- a/clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp @@ -486,8 +486,8 @@ class SymbolExpressor return Str; if (std::optional Str = Visit(S->getLHS())) return (*Str + " " + BinaryOperator::getOpcodeStr(S->getOpcode()) + " " + - std::to_string(S->getRHS().getLimitedValue()) + - (S->getRHS().isUnsigned() ? "U" : "")) + std::to_string(S->getRHS()->getLimitedValue()) + + (S->getRHS()->isUnsigned() ? "U" : "")) .str(); return std::nullopt; } diff --git a/clang/lib/StaticAnalyzer/Checkers/Iterator.cpp b/clang/lib/StaticAnalyzer/Checkers/Iterator.cpp index e8d35aac2efd9..ba561ddebdb69 100644 --- a/clang/lib/StaticAnalyzer/Checkers/Iterator.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/Iterator.cpp @@ -241,7 +241,7 @@ ProgramStateRef advancePosition(ProgramStateRef State, SVal Iter, // For concrete integers we can calculate the new position nonloc::ConcreteInt IntDist = *IntDistOp; - if (IntDist.getValue().isNegative()) { + if (IntDist.getValue()->isNegative()) { IntDist = nonloc::ConcreteInt(BVF.getValue(-IntDist.getValue())); BinOp = (BinOp == BO_Add) ? BO_Sub : BO_Add; } @@ -272,9 +272,9 @@ ProgramStateRef assumeNoOverflow(ProgramStateRef State, SymbolRef Sym, ProgramStateRef NewState = State; llvm::APSInt Max = AT.getMaxValue() / AT.getValue(Scale); - SVal IsCappedFromAbove = - SVB.evalBinOpNN(State, BO_LE, nonloc::SymbolVal(Sym), - nonloc::ConcreteInt(Max), SVB.getConditionType()); + SVal IsCappedFromAbove = SVB.evalBinOpNN( + State, BO_LE, nonloc::SymbolVal(Sym), + nonloc::ConcreteInt(BV.getValue(Max)), SVB.getConditionType()); if (auto DV = IsCappedFromAbove.getAs()) { NewState = NewState->assume(*DV, true); if (!NewState) @@ -282,9 +282,9 @@ ProgramStateRef assumeNoOverflow(ProgramStateRef State, SymbolRef Sym, } llvm::APSInt Min = -Max; - SVal IsCappedFromBelow = - SVB.evalBinOpNN(State, BO_GE, nonloc::SymbolVal(Sym), - nonloc::ConcreteInt(Min), SVB.getConditionType()); + SVal IsCappedFromBelow = SVB.evalBinOpNN( + State, BO_GE, nonloc::SymbolVal(Sym), + nonloc::ConcreteInt(BV.getValue(Min)), SVB.getConditionType()); if (auto DV = IsCappedFromBelow.getAs()) { NewState = NewState->assume(*DV, true); if (!NewState) diff --git a/clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp b/clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp index 5649454b4cd47..d4ce73b03acb8 100644 --- a/clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp @@ -507,8 +507,8 @@ void IteratorModeling::processComparison(CheckerContext &C, OverloadedOperatorKind Op) const { if (const auto TruthVal = RetVal.getAs()) { if ((State = relateSymbols(State, Sym1, Sym2, - (Op == OO_EqualEqual) == - (TruthVal->getValue() != 0)))) { + (Op == OO_EqualEqual) == + (TruthVal->getValue()->getBoolValue())))) { C.addTransition(State); } else { C.generateSink(State, C.getPredecessor()); diff --git a/clang/lib/StaticAnalyzer/Checkers/MmapWriteExecChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MmapWriteExecChecker.cpp index 4b8e5216550d9..9a8c128edc233 100644 --- a/clang/lib/StaticAnalyzer/Checkers/MmapWriteExecChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/MmapWriteExecChecker.cpp @@ -68,7 +68,7 @@ void MmapWriteExecChecker::checkPreCall(const CallEvent &Call, auto ProtLoc = ProtVal.getAs(); if (!ProtLoc) return; - int64_t Prot = ProtLoc->getValue().getSExtValue(); + int64_t Prot = ProtLoc->getValue()->getSExtValue(); if ((Prot & ProtWrite) && (Prot & ProtExec)) { ExplodedNode *N = C.generateNonFatalErrorNode(); diff --git a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp index 4f30b2a0e7e7d..356d63e3e8b80 100644 --- a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp @@ -1643,7 +1643,7 @@ void StdLibraryFunctionsChecker::initFunctionSummaries( public: GetMaxValue(BasicValueFactory &BVF) : BVF(BVF) {} std::optional operator()(QualType Ty) { - return BVF.getMaxValue(Ty).getLimitedValue(); + return BVF.getMaxValue(Ty)->getLimitedValue(); } std::optional operator()(std::optional Ty) { if (Ty) { @@ -1687,11 +1687,11 @@ void StdLibraryFunctionsChecker::initFunctionSummaries( const QualType SizePtrTy = getPointerTy(SizeTy); const QualType SizePtrRestrictTy = getRestrictTy(SizePtrTy); - const RangeInt IntMax = BVF.getMaxValue(IntTy).getLimitedValue(); + const RangeInt IntMax = BVF.getMaxValue(IntTy)->getLimitedValue(); const RangeInt UnsignedIntMax = - BVF.getMaxValue(UnsignedIntTy).getLimitedValue(); - const RangeInt LongMax = BVF.getMaxValue(LongTy).getLimitedValue(); - const RangeInt SizeMax = BVF.getMaxValue(SizeTy).getLimitedValue(); + BVF.getMaxValue(UnsignedIntTy)->getLimitedValue(); + const RangeInt LongMax = BVF.getMaxValue(LongTy)->getLimitedValue(); + const RangeInt SizeMax = BVF.getMaxValue(SizeTy)->getLimitedValue(); // Set UCharRangeMax to min of int or uchar maximum value. // The C standard states that the arguments of functions like isalpha must @@ -1700,7 +1700,7 @@ void StdLibraryFunctionsChecker::initFunctionSummaries( // to be true for commonly used and well tested instruction set // architectures, but not for others. const RangeInt UCharRangeMax = - std::min(BVF.getMaxValue(ACtx.UnsignedCharTy).getLimitedValue(), IntMax); + std::min(BVF.getMaxValue(ACtx.UnsignedCharTy)->getLimitedValue(), IntMax); // Get platform dependent values of some macros. // Try our best to parse this from the Preprocessor, otherwise fallback to a @@ -3704,7 +3704,7 @@ void StdLibraryFunctionsChecker::initFunctionSummaries( // Functions for testing. if (AddTestFunctions) { - const RangeInt IntMin = BVF.getMinValue(IntTy).getLimitedValue(); + const RangeInt IntMin = BVF.getMinValue(IntTy)->getLimitedValue(); addToFunctionSummaryMap( "__not_null", Signature(ArgTypes{IntPtrTy}, RetType{IntTy}), diff --git a/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp index 0a823a1126ce3..80969ce664530 100644 --- a/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp @@ -1977,7 +1977,7 @@ StreamChecker::ensureFseekWhenceCorrect(SVal WhenceVal, CheckerContext &C, if (!CI) return State; - int64_t X = CI->getValue().getSExtValue(); + int64_t X = CI->getValue()->getSExtValue(); if (X == SeekSetVal || X == SeekCurVal || X == SeekEndVal) return State; diff --git a/clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp index 8d17ba5d690b9..ba91b3632abbf 100644 --- a/clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp @@ -96,7 +96,7 @@ ProgramStateRef VLASizeChecker::checkVLA(CheckerContext &C, SValBuilder &SVB = C.getSValBuilder(); CanQualType SizeTy = Ctx.getSizeType(); uint64_t SizeMax = - SVB.getBasicValueFactory().getMaxValue(SizeTy).getZExtValue(); + SVB.getBasicValueFactory().getMaxValue(SizeTy)->getZExtValue(); // Get the element size. CharUnits EleSize = Ctx.getTypeSizeInChars(VLALast->getElementType()); diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp index 797f3e1f3fba5..5487fea1b956c 100644 --- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp @@ -125,9 +125,8 @@ bool isCtorOfRefCounted(const clang::FunctionDecl *F) { assert(F); const std::string &FunctionName = safeGetName(F); - return isRefType(FunctionName) || FunctionName == "makeRef" || - FunctionName == "makeRefPtr" || FunctionName == "UniqueRef" || - FunctionName == "makeUniqueRef" || + return isRefType(FunctionName) || FunctionName == "adoptRef" || + FunctionName == "UniqueRef" || FunctionName == "makeUniqueRef" || FunctionName == "makeUniqueRefWithoutFastMallocCheck" || FunctionName == "String" || FunctionName == "AtomString" || diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedLambdaCapturesChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedLambdaCapturesChecker.cpp index d786b02e2d7f3..da9698e327562 100644 --- a/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedLambdaCapturesChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedLambdaCapturesChecker.cpp @@ -115,7 +115,7 @@ class UncountedLambdaCapturesChecker if (ArgIndex >= CE->getNumArgs()) return true; auto *Arg = CE->getArg(ArgIndex)->IgnoreParenCasts(); - if (auto *L = dyn_cast_or_null(Arg)) { + if (auto *L = findLambdaInArg(Arg)) { LambdasToIgnore.insert(L); if (!Param->hasAttr() && !TreatAllArgsAsNoEscape) Checker->visitLambdaExpr(L, shouldCheckThis()); @@ -126,6 +126,38 @@ class UncountedLambdaCapturesChecker return true; } + LambdaExpr *findLambdaInArg(Expr *E) { + if (auto *Lambda = dyn_cast_or_null(E)) + return Lambda; + auto *TempExpr = dyn_cast_or_null(E); + if (!TempExpr) + return nullptr; + E = TempExpr->getSubExpr()->IgnoreParenCasts(); + if (!E) + return nullptr; + if (auto *Lambda = dyn_cast(E)) + return Lambda; + auto *CE = dyn_cast_or_null(E); + if (!CE || !CE->getNumArgs()) + return nullptr; + auto *CtorArg = CE->getArg(0)->IgnoreParenCasts(); + if (!CtorArg) + return nullptr; + if (auto *Lambda = dyn_cast(CtorArg)) + return Lambda; + auto *DRE = dyn_cast(CtorArg); + if (!DRE) + return nullptr; + auto *VD = dyn_cast_or_null(DRE->getDecl()); + if (!VD) + return nullptr; + auto *Init = VD->getInit(); + if (!Init) + return nullptr; + TempExpr = dyn_cast(Init->IgnoreParenCasts()); + return dyn_cast_or_null(TempExpr->getSubExpr()); + } + void checkCalleeLambda(CallExpr *CE) { auto *Callee = CE->getCallee(); if (!Callee) @@ -180,11 +212,53 @@ class UncountedLambdaCapturesChecker } else if (C.capturesThis() && shouldCheckThis) { if (ignoreParamVarDecl) // this is always a parameter to this function. continue; - reportBugOnThisPtr(C); + bool hasProtectThis = false; + for (const LambdaCapture &OtherCapture : L->captures()) { + if (!OtherCapture.capturesVariable()) + continue; + if (auto *ValueDecl = OtherCapture.getCapturedVar()) { + if (protectThis(ValueDecl)) { + hasProtectThis = true; + break; + } + } + } + if (!hasProtectThis) + reportBugOnThisPtr(C); } } } + bool protectThis(const ValueDecl *ValueDecl) const { + auto *VD = dyn_cast(ValueDecl); + if (!VD) + return false; + auto *Init = VD->getInit()->IgnoreParenCasts(); + if (!Init) + return false; + auto *BTE = dyn_cast(Init); + if (!BTE) + return false; + auto *CE = dyn_cast_or_null(BTE->getSubExpr()); + if (!CE) + return false; + auto *Ctor = CE->getConstructor(); + if (!Ctor) + return false; + auto clsName = safeGetName(Ctor->getParent()); + if (!isRefType(clsName) || !CE->getNumArgs()) + return false; + auto *Arg = CE->getArg(0)->IgnoreParenCasts(); + while (auto *UO = dyn_cast(Arg)) { + auto OpCode = UO->getOpcode(); + if (OpCode == UO_Deref || OpCode == UO_AddrOf) + Arg = UO->getSubExpr(); + else + break; + } + return isa(Arg); + } + void reportBug(const LambdaCapture &Capture, ValueDecl *CapturedVar, const QualType T) const { assert(CapturedVar); diff --git a/clang/lib/StaticAnalyzer/Core/BasicValueFactory.cpp b/clang/lib/StaticAnalyzer/Core/BasicValueFactory.cpp index 827c04143e658..02f34bc30f554 100644 --- a/clang/lib/StaticAnalyzer/Core/BasicValueFactory.cpp +++ b/clang/lib/StaticAnalyzer/Core/BasicValueFactory.cpp @@ -87,7 +87,7 @@ BasicValueFactory::~BasicValueFactory() { delete (PersistentSValPairsTy*) PersistentSValPairs; } -const llvm::APSInt& BasicValueFactory::getValue(const llvm::APSInt& X) { +APSIntPtr BasicValueFactory::getValue(const llvm::APSInt &X) { llvm::FoldingSetNodeID ID; void *InsertPos; @@ -101,23 +101,23 @@ const llvm::APSInt& BasicValueFactory::getValue(const llvm::APSInt& X) { APSIntSet.InsertNode(P, InsertPos); } - return *P; + // We own the APSInt object. It's safe here. + return APSIntPtr::unsafeConstructor(&P->getValue()); } -const llvm::APSInt& BasicValueFactory::getValue(const llvm::APInt& X, - bool isUnsigned) { +APSIntPtr BasicValueFactory::getValue(const llvm::APInt &X, bool isUnsigned) { llvm::APSInt V(X, isUnsigned); return getValue(V); } -const llvm::APSInt& BasicValueFactory::getValue(uint64_t X, unsigned BitWidth, - bool isUnsigned) { +APSIntPtr BasicValueFactory::getValue(uint64_t X, unsigned BitWidth, + bool isUnsigned) { llvm::APSInt V(BitWidth, isUnsigned); V = X; return getValue(V); } -const llvm::APSInt& BasicValueFactory::getValue(uint64_t X, QualType T) { +APSIntPtr BasicValueFactory::getValue(uint64_t X, QualType T) { return getValue(getAPSIntType(T).getValue(X)); } @@ -242,45 +242,45 @@ const PointerToMemberData *BasicValueFactory::accumCXXBase( return getPointerToMemberData(ND, BaseSpecList); } -const llvm::APSInt* -BasicValueFactory::evalAPSInt(BinaryOperator::Opcode Op, - const llvm::APSInt& V1, const llvm::APSInt& V2) { +std::optional +BasicValueFactory::evalAPSInt(BinaryOperator::Opcode Op, const llvm::APSInt &V1, + const llvm::APSInt &V2) { switch (Op) { default: llvm_unreachable("Invalid Opcode."); case BO_Mul: - return &getValue( V1 * V2 ); + return getValue(V1 * V2); case BO_Div: if (V2 == 0) // Avoid division by zero - return nullptr; - return &getValue( V1 / V2 ); + return std::nullopt; + return getValue(V1 / V2); case BO_Rem: if (V2 == 0) // Avoid division by zero - return nullptr; - return &getValue( V1 % V2 ); + return std::nullopt; + return getValue(V1 % V2); case BO_Add: - return &getValue( V1 + V2 ); + return getValue(V1 + V2); case BO_Sub: - return &getValue( V1 - V2 ); + return getValue(V1 - V2); case BO_Shl: { // FIXME: This logic should probably go higher up, where we can // test these conditions symbolically. if (V2.isNegative() || V2.getBitWidth() > 64) - return nullptr; + return std::nullopt; uint64_t Amt = V2.getZExtValue(); if (Amt >= V1.getBitWidth()) - return nullptr; + return std::nullopt; - return &getValue( V1.operator<<( (unsigned) Amt )); + return getValue(V1.operator<<((unsigned)Amt)); } case BO_Shr: { @@ -288,44 +288,44 @@ BasicValueFactory::evalAPSInt(BinaryOperator::Opcode Op, // test these conditions symbolically. if (V2.isNegative() || V2.getBitWidth() > 64) - return nullptr; + return std::nullopt; uint64_t Amt = V2.getZExtValue(); if (Amt >= V1.getBitWidth()) - return nullptr; + return std::nullopt; - return &getValue( V1.operator>>( (unsigned) Amt )); + return getValue(V1.operator>>((unsigned)Amt)); } case BO_LT: - return &getTruthValue( V1 < V2 ); + return getTruthValue(V1 < V2); case BO_GT: - return &getTruthValue( V1 > V2 ); + return getTruthValue(V1 > V2); case BO_LE: - return &getTruthValue( V1 <= V2 ); + return getTruthValue(V1 <= V2); case BO_GE: - return &getTruthValue( V1 >= V2 ); + return getTruthValue(V1 >= V2); case BO_EQ: - return &getTruthValue( V1 == V2 ); + return getTruthValue(V1 == V2); case BO_NE: - return &getTruthValue( V1 != V2 ); + return getTruthValue(V1 != V2); // Note: LAnd, LOr, Comma are handled specially by higher-level logic. case BO_And: - return &getValue( V1 & V2 ); + return getValue(V1 & V2); case BO_Or: - return &getValue( V1 | V2 ); + return getValue(V1 | V2); case BO_Xor: - return &getValue( V1 ^ V2 ); + return getValue(V1 ^ V2); } } diff --git a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp index c4479db14b791..a9b4dbb39b5bd 100644 --- a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp +++ b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp @@ -264,7 +264,7 @@ getConcreteIntegerValue(const Expr *CondVarExpr, const ExplodedNode *N) { if (std::optional V = getSValForVar(CondVarExpr, N)) if (auto CI = V->getAs()) - return &CI->getValue(); + return CI->getValue().get(); return std::nullopt; } diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp index 0a74a80a6a62f..db385e891e762 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -1830,6 +1830,8 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, case Stmt::OpenACCExitDataConstructClass: case Stmt::OpenACCHostDataConstructClass: case Stmt::OpenACCWaitConstructClass: + case Stmt::OpenACCInitConstructClass: + case Stmt::OpenACCShutdownConstructClass: case Stmt::OMPUnrollDirectiveClass: case Stmt::OMPMetaDirectiveClass: case Stmt::HLSLOutArgExprClass: { diff --git a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp index bbf2303b9f6ef..559c80634c12e 100644 --- a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp +++ b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp @@ -743,7 +743,7 @@ std::string MemRegion::getDescriptiveName(bool UseQuotes) const { // Index is a ConcreteInt. if (auto CI = ER->getIndex().getAs()) { llvm::SmallString<2> Idx; - CI->getValue().toString(Idx); + CI->getValue()->toString(Idx); ArrayIndices = (llvm::Twine("[") + Idx.str() + "]" + ArrayIndices).str(); } // Index is symbolic, but may have a descriptive name. @@ -1458,9 +1458,7 @@ RegionRawOffset ElementRegion::getAsArrayOffset() const { SVal index = ER->getIndex(); if (auto CI = index.getAs()) { // Update the offset. - int64_t i = CI->getValue().getSExtValue(); - - if (i != 0) { + if (int64_t i = CI->getValue()->getSExtValue(); i != 0) { QualType elemType = ER->getElementType(); // If we are pointing to an incomplete type, go no further. @@ -1632,7 +1630,7 @@ static RegionOffset calculateOffset(const MemRegion *R) { if (SymbolicOffsetBase) continue; - int64_t i = CI->getValue().getSExtValue(); + int64_t i = CI->getValue()->getSExtValue(); // This type size is in bits. Offset += i * R->getContext().getTypeSize(EleTy); } else { diff --git a/clang/lib/StaticAnalyzer/Core/ProgramState.cpp b/clang/lib/StaticAnalyzer/Core/ProgramState.cpp index d4f56342d934c..34ab2388cbd2f 100644 --- a/clang/lib/StaticAnalyzer/Core/ProgramState.cpp +++ b/clang/lib/StaticAnalyzer/Core/ProgramState.cpp @@ -288,12 +288,10 @@ SVal ProgramState::getSVal(Loc location, QualType T) const { // The symbolic value stored to 'x' is actually the conjured // symbol for the call to foo(); the type of that symbol is 'char', // not unsigned. - const llvm::APSInt &NewV = getBasicVals().Convert(T, *Int); - + APSIntPtr NewV = getBasicVals().Convert(T, *Int); if (V.getAs()) return loc::ConcreteInt(NewV); - else - return nonloc::ConcreteInt(NewV); + return nonloc::ConcreteInt(NewV); } } } diff --git a/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp b/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp index 92e9d24552034..2b85580186381 100644 --- a/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp +++ b/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp @@ -76,17 +76,13 @@ DefinedOrUnknownSVal SValBuilder::makeZeroVal(QualType type) { nonloc::SymbolVal SValBuilder::makeNonLoc(const SymExpr *lhs, BinaryOperator::Opcode op, - const llvm::APSInt &rhs, - QualType type) { - // The Environment ensures we always get a persistent APSInt in - // BasicValueFactory, so we don't need to get the APSInt from - // BasicValueFactory again. + APSIntPtr rhs, QualType type) { assert(lhs); assert(!Loc::isLocType(type)); return nonloc::SymbolVal(SymMgr.getSymIntExpr(lhs, op, rhs, type)); } -nonloc::SymbolVal SValBuilder::makeNonLoc(const llvm::APSInt &lhs, +nonloc::SymbolVal SValBuilder::makeNonLoc(APSIntPtr lhs, BinaryOperator::Opcode op, const SymExpr *rhs, QualType type) { assert(rhs); @@ -671,7 +667,7 @@ class EvalCastVisitor : public SValVisitor { SVal VisitConcreteInt(loc::ConcreteInt V) { // Pointer to bool. if (CastTy->isBooleanType()) - return VB.makeTruthVal(V.getValue().getBoolValue(), CastTy); + return VB.makeTruthVal(V.getValue()->getBoolValue(), CastTy); // Pointer to integer. if (CastTy->isIntegralOrEnumerationType()) { @@ -875,7 +871,7 @@ class EvalCastVisitor : public SValVisitor { // Integer to bool. if (CastTy->isBooleanType()) - return VB.makeTruthVal(V.getValue().getBoolValue(), CastTy); + return VB.makeTruthVal(V.getValue()->getBoolValue(), CastTy); // Integer to pointer. if (CastTy->isIntegralOrEnumerationType()) diff --git a/clang/lib/StaticAnalyzer/Core/SVals.cpp b/clang/lib/StaticAnalyzer/Core/SVals.cpp index d009552965eca..3ab01a04dcec4 100644 --- a/clang/lib/StaticAnalyzer/Core/SVals.cpp +++ b/clang/lib/StaticAnalyzer/Core/SVals.cpp @@ -111,9 +111,9 @@ SymbolRef SVal::getAsSymbol(bool IncludeBaseRegions) const { const llvm::APSInt *SVal::getAsInteger() const { if (auto CI = getAs()) - return &CI->getValue(); + return CI->getValue().get(); if (auto CI = getAs()) - return &CI->getValue(); + return CI->getValue().get(); return nullptr; } @@ -249,9 +249,9 @@ bool SVal::isConstant() const { bool SVal::isConstant(int I) const { if (std::optional LV = getAs()) - return LV->getValue() == I; + return *LV->getValue().get() == I; if (std::optional NV = getAs()) - return NV->getValue() == I; + return *NV->getValue().get() == I; return false; } @@ -314,9 +314,9 @@ void SVal::dumpToStream(raw_ostream &os) const { void NonLoc::dumpToStream(raw_ostream &os) const { switch (getKind()) { case nonloc::ConcreteIntKind: { - const auto &Value = castAs().getValue(); - os << Value << ' ' << (Value.isSigned() ? 'S' : 'U') << Value.getBitWidth() - << 'b'; + APSIntPtr Value = castAs().getValue(); + os << Value << ' ' << (Value->isSigned() ? 'S' : 'U') + << Value->getBitWidth() << 'b'; break; } case nonloc::SymbolValKind: @@ -380,7 +380,7 @@ void NonLoc::dumpToStream(raw_ostream &os) const { void Loc::dumpToStream(raw_ostream &os) const { switch (getKind()) { case loc::ConcreteIntKind: - os << castAs().getValue().getZExtValue() << " (Loc)"; + os << castAs().getValue()->getZExtValue() << " (Loc)"; break; case loc::GotoLabelKind: os << "&&" << castAs().getLabel()->getName(); diff --git a/clang/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp b/clang/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp index 8ca2cdb9d3ab7..3c5c992fa8dbc 100644 --- a/clang/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp +++ b/clang/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp @@ -75,7 +75,7 @@ ProgramStateRef SimpleConstraintManager::assumeAux(ProgramStateRef State, } case nonloc::ConcreteIntKind: { - bool b = Cond.castAs().getValue() != 0; + bool b = *Cond.castAs().getValue().get() != 0; bool isFeasible = b ? Assumption : !Assumption; return isFeasible ? State : nullptr; } diff --git a/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp b/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp index 229169f848e22..455621739f693 100644 --- a/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp +++ b/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp @@ -10,10 +10,11 @@ // //===----------------------------------------------------------------------===// -#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/APSIntPtr.h" #include "clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SValVisitor.h" #include @@ -179,8 +180,7 @@ SVal SimpleSValBuilder::MakeSymIntVal(const SymExpr *LHS, if (RHS == 0) isIdempotent = true; else if (RHS.isAllOnes()) { - const llvm::APSInt &Result = BasicVals.Convert(resultTy, RHS); - return nonloc::ConcreteInt(Result); + return nonloc::ConcreteInt(BasicVals.Convert(resultTy, RHS)); } break; } @@ -193,7 +193,7 @@ SVal SimpleSValBuilder::MakeSymIntVal(const SymExpr *LHS, // If we reach this point, the expression cannot be simplified. // Make a SymbolVal for the entire expression, after converting the RHS. - const llvm::APSInt *ConvertedRHS = &RHS; + std::optional ConvertedRHS = BasicVals.getValue(RHS); if (BinaryOperator::isComparisonOp(op)) { // We're looking for a type big enough to compare the symbolic value // with the given constant. @@ -205,13 +205,13 @@ SVal SimpleSValBuilder::MakeSymIntVal(const SymExpr *LHS, if (ValWidth < TypeWidth) { // If the value is too small, extend it. - ConvertedRHS = &BasicVals.Convert(SymbolType, RHS); + ConvertedRHS = BasicVals.Convert(SymbolType, RHS); } else if (ValWidth == TypeWidth) { // If the value is signed but the symbol is unsigned, do the comparison // in unsigned space. [C99 6.3.1.8] // (For the opposite case, the value is already unsigned.) if (RHS.isSigned() && !SymbolType->isSignedIntegerOrEnumerationType()) - ConvertedRHS = &BasicVals.Convert(SymbolType, RHS); + ConvertedRHS = BasicVals.Convert(SymbolType, RHS); } } else if (BinaryOperator::isAdditiveOp(op) && RHS.isNegative()) { // Change a+(-N) into a-N, and a-(-N) into a+N @@ -219,13 +219,13 @@ SVal SimpleSValBuilder::MakeSymIntVal(const SymExpr *LHS, // subtraction/addition of the negated value. APSIntType resultIntTy = BasicVals.getAPSIntType(resultTy); if (isNegationValuePreserving(RHS, resultIntTy)) { - ConvertedRHS = &BasicVals.getValue(-resultIntTy.convert(RHS)); + ConvertedRHS = BasicVals.getValue(-resultIntTy.convert(RHS)); op = (op == BO_Add) ? BO_Sub : BO_Add; } else { - ConvertedRHS = &BasicVals.Convert(resultTy, RHS); + ConvertedRHS = BasicVals.Convert(resultTy, RHS); } } else - ConvertedRHS = &BasicVals.Convert(resultTy, RHS); + ConvertedRHS = BasicVals.Convert(resultTy, RHS); return makeNonLoc(LHS, op, *ConvertedRHS, resultTy); } @@ -234,9 +234,10 @@ SVal SimpleSValBuilder::MakeSymIntVal(const SymExpr *LHS, static bool isInRelation(BinaryOperator::Opcode Rel, SymbolRef Sym, llvm::APSInt Bound, ProgramStateRef State) { SValBuilder &SVB = State->getStateManager().getSValBuilder(); - SVal Result = - SVB.evalBinOpNN(State, Rel, nonloc::SymbolVal(Sym), - nonloc::ConcreteInt(Bound), SVB.getConditionType()); + BasicValueFactory &BV = SVB.getBasicValueFactory(); + SVal Result = SVB.evalBinOpNN(State, Rel, nonloc::SymbolVal(Sym), + nonloc::ConcreteInt(BV.getValue(Bound)), + SVB.getConditionType()); if (auto DV = Result.getAs()) { return !State->assume(*DV, false); } @@ -273,14 +274,14 @@ static bool isWithinConstantOverflowBounds(llvm::APSInt I) { return (I <= Max) && (I >= -Max); } -static std::pair -decomposeSymbol(SymbolRef Sym, BasicValueFactory &BV) { +static std::pair decomposeSymbol(SymbolRef Sym, + BasicValueFactory &BV) { if (const auto *SymInt = dyn_cast(Sym)) if (BinaryOperator::isAdditiveOp(SymInt->getOpcode())) return std::make_pair(SymInt->getLHS(), - (SymInt->getOpcode() == BO_Add) ? - (SymInt->getRHS()) : - (-SymInt->getRHS())); + (SymInt->getOpcode() == BO_Add) + ? BV.getValue(SymInt->getRHS()) + : BV.getValue(-SymInt->getRHS())); // Fail to decompose: "reduce" the problem to the "$x + 0" case. return std::make_pair(Sym, BV.getValue(0, Sym->getType())); @@ -314,8 +315,9 @@ static NonLoc doRearrangeUnchecked(ProgramStateRef State, llvm_unreachable("Operation not suitable for unchecked rearrangement!"); if (LSym == RSym) - return SVB.evalBinOpNN(State, Op, nonloc::ConcreteInt(LInt), - nonloc::ConcreteInt(RInt), ResultTy) + return SVB + .evalBinOpNN(State, Op, nonloc::ConcreteInt(BV.getValue(LInt)), + nonloc::ConcreteInt(BV.getValue(RInt)), ResultTy) .castAs(); SymbolRef ResultSym = nullptr; @@ -347,7 +349,7 @@ static NonLoc doRearrangeUnchecked(ProgramStateRef State, return nonloc::SymbolVal(ResultSym); } } - const llvm::APSInt &PersistentResultInt = BV.getValue(ResultInt); + APSIntPtr PersistentResultInt = BV.getValue(ResultInt); return nonloc::SymbolVal( SymMgr.getSymIntExpr(ResultSym, ResultOp, PersistentResultInt, ResultTy)); } @@ -541,8 +543,8 @@ SVal SimpleSValBuilder::evalBinOpNN(ProgramStateRef state, IntType.apply(RHSValue); } - const llvm::APSInt *Result = - BasicVals.evalAPSInt(op, LHSValue, RHSValue); + std::optional Result = + BasicVals.evalAPSInt(op, LHSValue, RHSValue); if (!Result) { if (op == BO_Shl || op == BO_Shr) { // FIXME: At this point the constant folding claims that the result @@ -682,7 +684,7 @@ SVal SimpleSValBuilder::evalBinOpNN(ProgramStateRef state, // as consequence x+1U-10 produces x-9U, instead // of x+4294967287U, that would be produced without this // additional check. - const llvm::APSInt *newRHS; + std::optional newRHS; if (lop == op) { newRHS = BasicVals.evalAPSInt(BO_Add, first, second); } else if (first >= second) { @@ -874,7 +876,7 @@ SVal SimpleSValBuilder::evalBinOpLL(ProgramStateRef state, if (std::optional rInt = rhs.getAs()) { assert(BinaryOperator::isComparisonOp(op) || op == BO_Sub); - if (const auto *ResultInt = + if (std::optional ResultInt = BasicVals.evalAPSInt(op, L.getValue(), rInt->getValue())) return evalCast(nonloc::ConcreteInt(*ResultInt), resultTy, QualType{}); return UnknownVal(); @@ -1208,10 +1210,10 @@ const llvm::APSInt *SimpleSValBuilder::getConstValue(ProgramStateRef state, const llvm::APSInt *SimpleSValBuilder::getConcreteValue(SVal V) { if (std::optional X = V.getAs()) - return &X->getValue(); + return X->getValue().get(); if (std::optional X = V.getAs()) - return &X->getValue(); + return X->getValue().get(); return nullptr; } diff --git a/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp b/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp index 9025e11a3f51a..f21e5c3ad7bd7 100644 --- a/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp +++ b/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp @@ -261,8 +261,7 @@ SymbolManager::getCastSymbol(const SymExpr *Op, const SymIntExpr *SymbolManager::getSymIntExpr(const SymExpr *lhs, BinaryOperator::Opcode op, - const llvm::APSInt& v, - QualType t) { + APSIntPtr v, QualType t) { llvm::FoldingSetNodeID ID; SymIntExpr::Profile(ID, lhs, op, v, t); void *InsertPos; @@ -276,10 +275,9 @@ const SymIntExpr *SymbolManager::getSymIntExpr(const SymExpr *lhs, return cast(data); } -const IntSymExpr *SymbolManager::getIntSymExpr(const llvm::APSInt& lhs, +const IntSymExpr *SymbolManager::getIntSymExpr(APSIntPtr lhs, BinaryOperator::Opcode op, - const SymExpr *rhs, - QualType t) { + const SymExpr *rhs, QualType t) { llvm::FoldingSetNodeID ID; IntSymExpr::Profile(ID, lhs, op, rhs, t); void *InsertPos; diff --git a/clang/lib/StaticAnalyzer/Core/TextDiagnostics.cpp b/clang/lib/StaticAnalyzer/Core/TextDiagnostics.cpp index 71268af22e242..e8cf367b83346 100644 --- a/clang/lib/StaticAnalyzer/Core/TextDiagnostics.cpp +++ b/clang/lib/StaticAnalyzer/Core/TextDiagnostics.cpp @@ -81,7 +81,7 @@ class TextDiagnostics : public PathDiagnosticConsumer { if (llvm::Error Err = Repls.add(Repl)) { llvm::errs() << "Error applying replacement " << Repl.toString() - << ": " << Err << "\n"; + << ": " << llvm::toString(std::move(Err)) << "\n"; } } }; diff --git a/clang/test/AST/ByteCode/builtin-functions.cpp b/clang/test/AST/ByteCode/builtin-functions.cpp index 5906cb970f06c..c1fd1bc138150 100644 --- a/clang/test/AST/ByteCode/builtin-functions.cpp +++ b/clang/test/AST/ByteCode/builtin-functions.cpp @@ -1222,6 +1222,28 @@ namespace BuiltinMemcpy { static_assert(test_memcpy(1, 2, sizeof(int)) == 1334); static_assert(test_memcpy(0, 1, sizeof(int) * 2) == 2334); // both-error {{not an integral constant expression}} \ // both-note {{in call}} + + /// Both memcpy and memmove must support pointers. + constexpr bool moveptr() { + int a = 0; + void *x = &a; + void *z = nullptr; + + __builtin_memmove(&z, &x, sizeof(void*)); + return z == x; + } + static_assert(moveptr()); + + constexpr bool cpyptr() { + int a = 0; + void *x = &a; + void *z = nullptr; + + __builtin_memcpy(&z, &x, sizeof(void*)); + return z == x; + } + static_assert(cpyptr()); + } namespace Memcmp { diff --git a/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl b/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl index 6cb4379ef5f55..fd4aa58f5891b 100644 --- a/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl +++ b/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl @@ -50,6 +50,14 @@ // EMPTY: ClassTemplateDecl 0x{{[0-9A-Fa-f]+}} <> implicit [[RESOURCE]] // EMPTY-NEXT: TemplateTypeParmDecl 0x{{[0-9A-Fa-f]+}} <> typename depth 0 index 0 element_type +// EMPTY-NEXT: ConceptSpecializationExpr 0x{{[0-9A-Fa-f]+}} <> 'bool' Concept 0x{{[0-9A-Fa-f]+}} '__is_structured_resource_element_compatible' +// EMPTY-NEXT: ImplicitConceptSpecializationDecl 0x{{[0-9A-Fa-f]+}} <> +// EMPTY-NEXT: TemplateArgument type 'type-parameter-0-0' +// EMPTY-NEXT: TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'type-parameter-0-0' dependent depth 0 index 0 +// EMPTY-NEXT: TemplateTypeParm 0x{{[0-9A-Fa-f]+}} '' +// EMPTY-NEXT: TemplateArgument type 'element_type':'type-parameter-0-0' +// EMPTY-NEXT: TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'element_type' dependent depth 0 index 0 +// EMPTY-NEXT: TemplateTypeParm 0x{{[0-9A-Fa-f]+}} 'element_type' // EMPTY-NEXT: CXXRecordDecl 0x{{[0-9A-Fa-f]+}} <> implicit class [[RESOURCE]] // EMPTY-NEXT: FinalAttr 0x{{[0-9A-Fa-f]+}} <> Implicit final @@ -64,6 +72,14 @@ RESOURCE Buffer; // CHECK: ClassTemplateDecl 0x{{[0-9A-Fa-f]+}} <> implicit [[RESOURCE]] // CHECK-NEXT: TemplateTypeParmDecl 0x{{[0-9A-Fa-f]+}} <> typename depth 0 index 0 element_type +// CHECK-NEXT: ConceptSpecializationExpr 0x{{[0-9A-Fa-f]+}} <> 'bool' Concept 0x{{[0-9A-Fa-f]+}} '__is_structured_resource_element_compatible' +// CHECK-NEXT: ImplicitConceptSpecializationDecl 0x{{[0-9A-Fa-f]+}} <> +// CHECK-NEXT: TemplateArgument type 'type-parameter-0-0' +// CHECK-NEXT: TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'type-parameter-0-0' dependent depth 0 index 0 +// CHECK-NEXT: TemplateTypeParm 0x{{[0-9A-Fa-f]+}} '' +// CHECK-NEXT: TemplateArgument type 'element_type':'type-parameter-0-0' +// CHECK-NEXT: TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'element_type' dependent depth 0 index 0 +// CHECK-NEXT: TemplateTypeParm 0x{{[0-9A-Fa-f]+}} 'element_type' // CHECK-NEXT: CXXRecordDecl 0x{{[0-9A-Fa-f]+}} <> implicit class [[RESOURCE]] definition // CHECK: FinalAttr 0x{{[0-9A-Fa-f]+}} <> Implicit final diff --git a/clang/test/AST/HLSL/is_structured_resource_element_compatible_concept.hlsl b/clang/test/AST/HLSL/is_structured_resource_element_compatible_concept.hlsl new file mode 100644 index 0000000000000..2ecd102d524c8 --- /dev/null +++ b/clang/test/AST/HLSL/is_structured_resource_element_compatible_concept.hlsl @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -ast-dump -ast-dump-filter=__is_structured_resource_element_compatible %s | FileCheck %s + +// CHECK: ConceptDecl 0x{{[0-9a-f]+}} <> __is_structured_resource_element_compatible +// CHECK: |-TemplateTypeParmDecl 0x{{[0-9a-f]+}} <> referenced typename depth 0 index 0 element_type +// CHECK: `-BinaryOperator 0x{{[0-9a-f]+}} <> 'bool' lvalue '&&' +// CHECK: |-UnaryOperator 0x{{[0-9a-f]+}} <> 'bool' lvalue prefix '!' cannot overflow +// CHECK: | `-TypeTraitExpr 0x{{[0-9a-f]+}} <> 'bool' __builtin_hlsl_is_intangible +// CHECK: | `-TemplateTypeParmType 0x{{[0-9a-f]+}} 'element_type' dependent depth 0 index 0 +// CHECK: | `-TemplateTypeParm 0x{{[0-9a-f]+}} 'element_type' +// CHECK: `-BinaryOperator 0x{{[0-9a-f]+}} <> 'bool' lvalue '>=' +// CHECK: |-UnaryExprOrTypeTraitExpr 0x{{[0-9a-f]+}} <> 'bool' sizeof 'element_type' +// CHECK: `-IntegerLiteral 0x{{[0-9a-f]+}} <> 'unsigned long' 1 + + +StructuredBuffer Buffer; diff --git a/clang/test/AST/ast-print-openacc-init-construct.cpp b/clang/test/AST/ast-print-openacc-init-construct.cpp new file mode 100644 index 0000000000000..0cfcbc99ab145 --- /dev/null +++ b/clang/test/AST/ast-print-openacc-init-construct.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -fopenacc -ast-print %s -o - | FileCheck %s + +unsigned Int; + +void uses() { +// CHECK: #pragma acc init device_type(*) device_num(Int) if(Int == 5) +#pragma acc init device_type(*) device_num(Int) if (Int == 5) +// CHECK: #pragma acc init device_type(*) device_num(Int) +#pragma acc init device_type(*) device_num(Int) +// CHECK: #pragma acc init device_type(*) if(Int == 5) +#pragma acc init device_type(*) if (Int == 5) +// CHECK: #pragma acc init device_type(SomeName) +#pragma acc init device_type(SomeName) +} diff --git a/clang/test/AST/ast-print-openacc-shutdown-construct.cpp b/clang/test/AST/ast-print-openacc-shutdown-construct.cpp new file mode 100644 index 0000000000000..4e2529658d418 --- /dev/null +++ b/clang/test/AST/ast-print-openacc-shutdown-construct.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -fopenacc -ast-print %s -o - | FileCheck %s + +unsigned Int; + +void uses() { +// CHECK: #pragma acc shutdown device_type(*) device_num(Int) if(Int == 5) +#pragma acc shutdown device_type(*) device_num(Int) if (Int == 5) +// CHECK: #pragma acc shutdown device_type(*) device_num(Int) +#pragma acc shutdown device_type(*) device_num(Int) +// CHECK: #pragma acc shutdown device_type(*) if(Int == 5) +#pragma acc shutdown device_type(*) if (Int == 5) +// CHECK: #pragma acc shutdown device_type(SomeName) +#pragma acc shutdown device_type(SomeName) +} diff --git a/clang/test/Analysis/Checkers/WebKit/call-args.cpp b/clang/test/Analysis/Checkers/WebKit/call-args.cpp index 2146eae9975b9..b4613d5090f29 100644 --- a/clang/test/Analysis/Checkers/WebKit/call-args.cpp +++ b/clang/test/Analysis/Checkers/WebKit/call-args.cpp @@ -376,3 +376,21 @@ namespace call_with_explicit_temporary_obj { namespace call_with_explicit_construct { } + +namespace call_with_adopt_ref { + class Obj { + public: + void ref() const; + void deref() const; + void method(); + }; + + // This is needed due to rdar://141692212. + struct dummy { + RefPtr any; + }; + + void foo() { + adoptRef(new Obj)->method(); + } +} diff --git a/clang/test/Analysis/Checkers/WebKit/mock-types.h b/clang/test/Analysis/Checkers/WebKit/mock-types.h index f3bd20f8bcf60..85397c2d25951 100644 --- a/clang/test/Analysis/Checkers/WebKit/mock-types.h +++ b/clang/test/Analysis/Checkers/WebKit/mock-types.h @@ -74,7 +74,10 @@ template struct DefaultRefDerefTraits { template , typename RefDerefTraits = DefaultRefDerefTraits> struct Ref { typename PtrTraits::StorageType t; + enum AdoptTag { Adopt }; + Ref() : t{} {}; + Ref(T &t, AdoptTag) : t(&t) { } Ref(T &t) : t(&RefDerefTraits::ref(t)) { } Ref(const Ref& o) : t(RefDerefTraits::refIfNotNull(PtrTraits::unwrap(o.t))) { } Ref(Ref&& o) : t(o.leakRef()) { } @@ -101,10 +104,19 @@ template , typename RefDerefTra T* leakRef() { return PtrTraits::exchange(t, nullptr); } }; +template Ref adoptRef(T& t) { + using Ref = Ref; + return Ref(t, Ref::Adopt); +} + +template class RefPtr; +template RefPtr adoptRef(T*); + template struct RefPtr { T *t; - RefPtr() : t(new T) {} + RefPtr() : t(nullptr) { } + RefPtr(T *t) : t(t) { if (t) @@ -113,6 +125,26 @@ template struct RefPtr { RefPtr(Ref&& o) : t(o.leakRef()) { } + RefPtr(RefPtr&& o) + : t(o.t) + { + o.t = nullptr; + } + RefPtr(const RefPtr& o) + : t(o.t) + { + if (t) + t->ref(); + } + RefPtr operator=(const RefPtr& o) + { + if (t) + t->deref(); + t = o.t; + if (t) + t->ref(); + return *this; + } ~RefPtr() { if (t) t->deref(); @@ -138,8 +170,19 @@ template struct RefPtr { return *this; } operator bool() const { return t; } + +private: + friend RefPtr adoptRef(T*); + + // call_with_adopt_ref in call-args.cpp requires this method to be private. + enum AdoptTag { Adopt }; + RefPtr(T *t, AdoptTag) : t(t) { } }; +template RefPtr adoptRef(T* t) { + return RefPtr(t, RefPtr::Adopt); +} + template bool operator==(const RefPtr &, const RefPtr &) { return false; } diff --git a/clang/test/Analysis/Checkers/WebKit/ref-cntbl-crtp-base-no-virtual-dtor.cpp b/clang/test/Analysis/Checkers/WebKit/ref-cntbl-crtp-base-no-virtual-dtor.cpp index 33c60ea8ca64d..4209db14eaa52 100644 --- a/clang/test/Analysis/Checkers/WebKit/ref-cntbl-crtp-base-no-virtual-dtor.cpp +++ b/clang/test/Analysis/Checkers/WebKit/ref-cntbl-crtp-base-no-virtual-dtor.cpp @@ -61,14 +61,6 @@ template Function adopt(Detail::Callab return Function(impl, Function::Adopt); } -template, typename RefDerefTraits = DefaultRefDerefTraits> Ref adoptRef(T&); - -template -inline Ref adoptRef(T& reference) -{ - return Ref(reference); -} - enum class DestructionThread : unsigned char { Any, Main, MainRunLoop }; void ensureOnMainThread(Function&&); // Sync if called on main thread, async otherwise. void ensureOnMainRunLoop(Function&&); // Sync if called on main run loop, async otherwise. diff --git a/clang/test/Analysis/Checkers/WebKit/uncounted-lambda-captures.cpp b/clang/test/Analysis/Checkers/WebKit/uncounted-lambda-captures.cpp index daff32e9940c8..2173245bc7af3 100644 --- a/clang/test/Analysis/Checkers/WebKit/uncounted-lambda-captures.cpp +++ b/clang/test/Analysis/Checkers/WebKit/uncounted-lambda-captures.cpp @@ -207,6 +207,58 @@ struct RefCountableWithLambdaCapturingThis { }; call(lambda); } + + void method_captures_this_unsafe_capture_local_var_explicitly() { + RefCountable* x = make_obj(); + call([this, protectedThis = RefPtr { this }, x]() { + // expected-warning@-1{{Captured raw-pointer 'x' to ref-counted type or CheckedPtr-capable type is unsafe [webkit.UncountedLambdaCapturesChecker]}} + nonTrivial(); + x->method(); + }); + } + + void method_captures_this_with_other_protected_var() { + RefCountable* x = make_obj(); + call([this, protectedX = RefPtr { x }]() { + // expected-warning@-1{{Captured raw-pointer 'this' to ref-counted type or CheckedPtr-capable type is unsafe [webkit.UncountedLambdaCapturesChecker]}} + nonTrivial(); + protectedX->method(); + }); + } + + void method_captures_this_unsafe_capture_local_var_explicitly_with_deref() { + RefCountable* x = make_obj(); + call([this, protectedThis = Ref { *this }, x]() { + // expected-warning@-1{{Captured raw-pointer 'x' to ref-counted type or CheckedPtr-capable type is unsafe [webkit.UncountedLambdaCapturesChecker]}} + nonTrivial(); + x->method(); + }); + } + + void method_captures_this_unsafe_local_var_via_vardecl() { + RefCountable* x = make_obj(); + auto lambda = [this, protectedThis = Ref { *this }, x]() { + // expected-warning@-1{{Captured raw-pointer 'x' to ref-counted type or CheckedPtr-capable type is unsafe [webkit.UncountedLambdaCapturesChecker]}} + nonTrivial(); + x->method(); + }; + call(lambda); + } + + void method_captures_this_with_guardian() { + auto lambda = [this, protectedThis = Ref { *this }]() { + nonTrivial(); + }; + call(lambda); + } + + void method_captures_this_with_guardian_refPtr() { + auto lambda = [this, protectedThis = RefPtr { &*this }]() { + nonTrivial(); + }; + call(lambda); + } + }; struct NonRefCountableWithLambdaCapturingThis { diff --git a/clang/test/CodeGen/AArch64/fmv-mix-explicit-implicit-default.c b/clang/test/CodeGen/AArch64/fmv-mix-explicit-implicit-default.c new file mode 100644 index 0000000000000..032738fb9664d --- /dev/null +++ b/clang/test/CodeGen/AArch64/fmv-mix-explicit-implicit-default.c @@ -0,0 +1,221 @@ +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature -fmv -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK-NOFMV + +int implicit_default_decl_first(void); +__attribute__((target_version("default"))) int implicit_default_decl_first(void) { return 1; } +int caller1(void) { return implicit_default_decl_first(); } + +__attribute__((target_version("default"))) int explicit_default_def_first(void) { return 2; } +int explicit_default_def_first(void); +int caller2(void) { return explicit_default_def_first(); } + +int implicit_default_def_first(void) { return 3; } +__attribute__((target_version("default"))) int implicit_default_def_first(void); +int caller3(void) { return implicit_default_def_first(); } + +__attribute__((target_version("default"))) int explicit_default_decl_first(void); +int explicit_default_decl_first(void) { return 4; } +int caller4(void) { return explicit_default_decl_first(); } + +int no_def_implicit_default_first(void); +__attribute__((target_version("default"))) int no_def_implicit_default_first(void); +int caller5(void) { return no_def_implicit_default_first(); } + +__attribute__((target_version("default"))) int no_def_explicit_default_first(void); +int no_def_explicit_default_first(void); +int caller6(void) { return no_def_explicit_default_first(); } +//. +// CHECK: @implicit_default_decl_first = weak_odr ifunc i32 (), ptr @implicit_default_decl_first.resolver +// CHECK: @explicit_default_def_first = weak_odr ifunc i32 (), ptr @explicit_default_def_first.resolver +// CHECK: @implicit_default_def_first = weak_odr ifunc i32 (), ptr @implicit_default_def_first.resolver +// CHECK: @explicit_default_decl_first = weak_odr ifunc i32 (), ptr @explicit_default_decl_first.resolver +//. +// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: define {{[^@]+}}@implicit_default_decl_first.default +// CHECK-SAME: () #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 1 +// +// +// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: define {{[^@]+}}@caller1 +// CHECK-SAME: () #[[ATTR1:[0-9]+]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[CALL:%.*]] = call i32 @implicit_default_decl_first() +// CHECK-NEXT: ret i32 [[CALL]] +// +// +// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: define {{[^@]+}}@explicit_default_def_first.default +// CHECK-SAME: () #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 2 +// +// +// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: define {{[^@]+}}@caller2 +// CHECK-SAME: () #[[ATTR1]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[CALL:%.*]] = call i32 @explicit_default_def_first() +// CHECK-NEXT: ret i32 [[CALL]] +// +// +// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: define {{[^@]+}}@implicit_default_def_first.default +// CHECK-SAME: () #[[ATTR1]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 3 +// +// +// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: define {{[^@]+}}@caller3 +// CHECK-SAME: () #[[ATTR1]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[CALL:%.*]] = call i32 @implicit_default_def_first() +// CHECK-NEXT: ret i32 [[CALL]] +// +// +// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: define {{[^@]+}}@explicit_default_decl_first.default +// CHECK-SAME: () #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 4 +// +// +// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: define {{[^@]+}}@caller4 +// CHECK-SAME: () #[[ATTR1]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[CALL:%.*]] = call i32 @explicit_default_decl_first() +// CHECK-NEXT: ret i32 [[CALL]] +// +// +// CHECK: declare i32 @no_def_implicit_default_first() #[[ATTR2:[0-9]+]] +// +// +// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: define {{[^@]+}}@caller5 +// CHECK-SAME: () #[[ATTR1]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[CALL:%.*]] = call i32 @no_def_implicit_default_first() +// CHECK-NEXT: ret i32 [[CALL]] +// +// +// CHECK: declare i32 @no_def_explicit_default_first() #[[ATTR2]] +// +// +// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: define {{[^@]+}}@caller6 +// CHECK-SAME: () #[[ATTR1]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[CALL:%.*]] = call i32 @no_def_explicit_default_first() +// CHECK-NEXT: ret i32 [[CALL]] +// +// +// CHECK-LABEL: define {{[^@]+}}@implicit_default_decl_first.resolver() comdat { +// CHECK-NEXT: resolver_entry: +// CHECK-NEXT: ret ptr @implicit_default_decl_first.default +// +// +// CHECK-LABEL: define {{[^@]+}}@explicit_default_def_first.resolver() comdat { +// CHECK-NEXT: resolver_entry: +// CHECK-NEXT: ret ptr @explicit_default_def_first.default +// +// +// CHECK-LABEL: define {{[^@]+}}@implicit_default_def_first.resolver() comdat { +// CHECK-NEXT: resolver_entry: +// CHECK-NEXT: ret ptr @implicit_default_def_first.default +// +// +// CHECK-LABEL: define {{[^@]+}}@explicit_default_decl_first.resolver() comdat { +// CHECK-NEXT: resolver_entry: +// CHECK-NEXT: ret ptr @explicit_default_decl_first.default +// +// +// CHECK: declare i32 @no_def_implicit_default_first.default() #[[ATTR2]] +// +// +// CHECK: declare i32 @no_def_explicit_default_first.default() #[[ATTR2]] +// +// +// CHECK-NOFMV: Function Attrs: noinline nounwind optnone +// CHECK-NOFMV-LABEL: define {{[^@]+}}@caller1 +// CHECK-NOFMV-SAME: () #[[ATTR0:[0-9]+]] { +// CHECK-NOFMV-NEXT: entry: +// CHECK-NOFMV-NEXT: [[CALL:%.*]] = call i32 @implicit_default_decl_first() +// CHECK-NOFMV-NEXT: ret i32 [[CALL]] +// +// +// CHECK-NOFMV: Function Attrs: noinline nounwind optnone +// CHECK-NOFMV-LABEL: define {{[^@]+}}@implicit_default_decl_first +// CHECK-NOFMV-SAME: () #[[ATTR1:[0-9]+]] { +// CHECK-NOFMV-NEXT: entry: +// CHECK-NOFMV-NEXT: ret i32 1 +// +// +// CHECK-NOFMV: Function Attrs: noinline nounwind optnone +// CHECK-NOFMV-LABEL: define {{[^@]+}}@caller2 +// CHECK-NOFMV-SAME: () #[[ATTR0]] { +// CHECK-NOFMV-NEXT: entry: +// CHECK-NOFMV-NEXT: [[CALL:%.*]] = call i32 @explicit_default_def_first() +// CHECK-NOFMV-NEXT: ret i32 [[CALL]] +// +// +// CHECK-NOFMV: Function Attrs: noinline nounwind optnone +// CHECK-NOFMV-LABEL: define {{[^@]+}}@explicit_default_def_first +// CHECK-NOFMV-SAME: () #[[ATTR1]] { +// CHECK-NOFMV-NEXT: entry: +// CHECK-NOFMV-NEXT: ret i32 2 +// +// +// CHECK-NOFMV: Function Attrs: noinline nounwind optnone +// CHECK-NOFMV-LABEL: define {{[^@]+}}@implicit_default_def_first +// CHECK-NOFMV-SAME: () #[[ATTR0]] { +// CHECK-NOFMV-NEXT: entry: +// CHECK-NOFMV-NEXT: ret i32 3 +// +// +// CHECK-NOFMV: Function Attrs: noinline nounwind optnone +// CHECK-NOFMV-LABEL: define {{[^@]+}}@caller3 +// CHECK-NOFMV-SAME: () #[[ATTR0]] { +// CHECK-NOFMV-NEXT: entry: +// CHECK-NOFMV-NEXT: [[CALL:%.*]] = call i32 @implicit_default_def_first() +// CHECK-NOFMV-NEXT: ret i32 [[CALL]] +// +// +// CHECK-NOFMV: Function Attrs: noinline nounwind optnone +// CHECK-NOFMV-LABEL: define {{[^@]+}}@caller4 +// CHECK-NOFMV-SAME: () #[[ATTR0]] { +// CHECK-NOFMV-NEXT: entry: +// CHECK-NOFMV-NEXT: [[CALL:%.*]] = call i32 @explicit_default_decl_first() +// CHECK-NOFMV-NEXT: ret i32 [[CALL]] +// +// +// CHECK-NOFMV: Function Attrs: noinline nounwind optnone +// CHECK-NOFMV-LABEL: define {{[^@]+}}@explicit_default_decl_first +// CHECK-NOFMV-SAME: () #[[ATTR1]] { +// CHECK-NOFMV-NEXT: entry: +// CHECK-NOFMV-NEXT: ret i32 4 +// +// +// CHECK-NOFMV: Function Attrs: noinline nounwind optnone +// CHECK-NOFMV-LABEL: define {{[^@]+}}@caller5 +// CHECK-NOFMV-SAME: () #[[ATTR0]] { +// CHECK-NOFMV-NEXT: entry: +// CHECK-NOFMV-NEXT: [[CALL:%.*]] = call i32 @no_def_implicit_default_first() +// CHECK-NOFMV-NEXT: ret i32 [[CALL]] +// +// +// CHECK-NOFMV: declare i32 @no_def_implicit_default_first() #[[ATTR2:[0-9]+]] +// +// +// CHECK-NOFMV: Function Attrs: noinline nounwind optnone +// CHECK-NOFMV-LABEL: define {{[^@]+}}@caller6 +// CHECK-NOFMV-SAME: () #[[ATTR0]] { +// CHECK-NOFMV-NEXT: entry: +// CHECK-NOFMV-NEXT: [[CALL:%.*]] = call i32 @no_def_explicit_default_first() +// CHECK-NOFMV-NEXT: ret i32 [[CALL]] +// +// +// CHECK-NOFMV: declare i32 @no_def_explicit_default_first() #[[ATTR2]] +//. diff --git a/clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_st1_single.c b/clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_st1_single.c index 6c1969c446248..058ff81bdf126 100644 --- a/clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_st1_single.c +++ b/clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_st1_single.c @@ -30,14 +30,14 @@ // CHECK-NEXT: tail call void @llvm.aarch64.sve.st1wq.nxv4i32( [[ZT]], [[TMP0]], ptr [[BASE]]) // CHECK-NEXT: ret void // -// CPP-CHECK-LABEL: define dso_local void @_Z16test_svst1wq_u32u10__SVBool_tPKju12__SVUint32_t +// CPP-CHECK-LABEL: define dso_local void @_Z16test_svst1wq_u32u10__SVBool_tPju12__SVUint32_t // CPP-CHECK-SAME: ( [[PRED:%.*]], ptr noundef [[BASE:%.*]], [[ZT:%.*]]) #[[ATTR0:[0-9]+]] { // CPP-CHECK-NEXT: entry: // CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PRED]]) // CPP-CHECK-NEXT: tail call void @llvm.aarch64.sve.st1wq.nxv4i32( [[ZT]], [[TMP0]], ptr [[BASE]]) // CPP-CHECK-NEXT: ret void // -void test_svst1wq_u32(svbool_t pred, uint32_t const * base, svuint32_t zt) { +void test_svst1wq_u32(svbool_t pred, uint32_t *base, svuint32_t zt) { SVE_ACLE_FUNC(svst1wq, _u32, , )(pred, base, zt); } @@ -51,7 +51,7 @@ void test_svst1wq_u32(svbool_t pred, uint32_t const * base, svuint32_t zt) { // CHECK-NEXT: tail call void @llvm.aarch64.sve.st1wq.nxv4i32( [[ZT]], [[TMP0]], ptr [[TMP3]]) // CHECK-NEXT: ret void // -// CPP-CHECK-LABEL: define dso_local void @_Z21test_svst1wq_vnum_u32u10__SVBool_tPKju12__SVUint32_t +// CPP-CHECK-LABEL: define dso_local void @_Z21test_svst1wq_vnum_u32u10__SVBool_tPju12__SVUint32_t // CPP-CHECK-SAME: ( [[PRED:%.*]], ptr noundef [[BASE:%.*]], [[ZT:%.*]]) #[[ATTR0]] { // CPP-CHECK-NEXT: entry: // CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PRED]]) @@ -61,7 +61,7 @@ void test_svst1wq_u32(svbool_t pred, uint32_t const * base, svuint32_t zt) { // CPP-CHECK-NEXT: tail call void @llvm.aarch64.sve.st1wq.nxv4i32( [[ZT]], [[TMP0]], ptr [[TMP3]]) // CPP-CHECK-NEXT: ret void // -void test_svst1wq_vnum_u32(svbool_t pred, uint32_t const * base, svuint32_t zt) { +void test_svst1wq_vnum_u32(svbool_t pred, uint32_t *base, svuint32_t zt) { SVE_ACLE_FUNC(svst1wq_vnum, _u32, , )(pred, base, 1, zt); } @@ -72,14 +72,14 @@ void test_svst1wq_vnum_u32(svbool_t pred, uint32_t const * base, svuint32_t zt) // CHECK-NEXT: tail call void @llvm.aarch64.sve.st1wq.nxv4i32( [[ZT]], [[TMP0]], ptr [[BASE]]) // CHECK-NEXT: ret void // -// CPP-CHECK-LABEL: define dso_local void @_Z16test_svst1wq_s32u10__SVBool_tPKiu11__SVInt32_t +// CPP-CHECK-LABEL: define dso_local void @_Z16test_svst1wq_s32u10__SVBool_tPiu11__SVInt32_t // CPP-CHECK-SAME: ( [[PRED:%.*]], ptr noundef [[BASE:%.*]], [[ZT:%.*]]) #[[ATTR0]] { // CPP-CHECK-NEXT: entry: // CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PRED]]) // CPP-CHECK-NEXT: tail call void @llvm.aarch64.sve.st1wq.nxv4i32( [[ZT]], [[TMP0]], ptr [[BASE]]) // CPP-CHECK-NEXT: ret void // -void test_svst1wq_s32(svbool_t pred, int32_t const * base, svint32_t zt) { +void test_svst1wq_s32(svbool_t pred, int32_t *base, svint32_t zt) { SVE_ACLE_FUNC(svst1wq, _s32, , )(pred, base, zt); } @@ -93,7 +93,7 @@ void test_svst1wq_s32(svbool_t pred, int32_t const * base, svint32_t zt) { // CHECK-NEXT: tail call void @llvm.aarch64.sve.st1wq.nxv4i32( [[ZT]], [[TMP0]], ptr [[TMP3]]) // CHECK-NEXT: ret void // -// CPP-CHECK-LABEL: define dso_local void @_Z21test_svst1wq_vnum_s32u10__SVBool_tPKiu11__SVInt32_t +// CPP-CHECK-LABEL: define dso_local void @_Z21test_svst1wq_vnum_s32u10__SVBool_tPiu11__SVInt32_t // CPP-CHECK-SAME: ( [[PRED:%.*]], ptr noundef [[BASE:%.*]], [[ZT:%.*]]) #[[ATTR0]] { // CPP-CHECK-NEXT: entry: // CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PRED]]) @@ -103,7 +103,7 @@ void test_svst1wq_s32(svbool_t pred, int32_t const * base, svint32_t zt) { // CPP-CHECK-NEXT: tail call void @llvm.aarch64.sve.st1wq.nxv4i32( [[ZT]], [[TMP0]], ptr [[TMP3]]) // CPP-CHECK-NEXT: ret void // -void test_svst1wq_vnum_s32(svbool_t pred, int32_t const * base, svint32_t zt) { +void test_svst1wq_vnum_s32(svbool_t pred, int32_t *base, svint32_t zt) { SVE_ACLE_FUNC(svst1wq_vnum, _s32, , )(pred, base, 1, zt); } @@ -114,14 +114,14 @@ void test_svst1wq_vnum_s32(svbool_t pred, int32_t const * base, svint32_t zt) { // CHECK-NEXT: tail call void @llvm.aarch64.sve.st1wq.nxv4f32( [[ZT]], [[TMP0]], ptr [[BASE]]) // CHECK-NEXT: ret void // -// CPP-CHECK-LABEL: define dso_local void @_Z16test_svst1wq_f32u10__SVBool_tPKfu13__SVFloat32_t +// CPP-CHECK-LABEL: define dso_local void @_Z16test_svst1wq_f32u10__SVBool_tPfu13__SVFloat32_t // CPP-CHECK-SAME: ( [[PRED:%.*]], ptr noundef [[BASE:%.*]], [[ZT:%.*]]) #[[ATTR0]] { // CPP-CHECK-NEXT: entry: // CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PRED]]) // CPP-CHECK-NEXT: tail call void @llvm.aarch64.sve.st1wq.nxv4f32( [[ZT]], [[TMP0]], ptr [[BASE]]) // CPP-CHECK-NEXT: ret void // -void test_svst1wq_f32(svbool_t pred, float32_t const * base, svfloat32_t zt) { +void test_svst1wq_f32(svbool_t pred, float32_t *base, svfloat32_t zt) { SVE_ACLE_FUNC(svst1wq, _f32, , )(pred, base, zt); } @@ -135,7 +135,7 @@ void test_svst1wq_f32(svbool_t pred, float32_t const * base, svfloat32_t zt) { // CHECK-NEXT: tail call void @llvm.aarch64.sve.st1wq.nxv4f32( [[ZT]], [[TMP0]], ptr [[TMP3]]) // CHECK-NEXT: ret void // -// CPP-CHECK-LABEL: define dso_local void @_Z21test_svst1wq_vnum_f32u10__SVBool_tPKfu13__SVFloat32_t +// CPP-CHECK-LABEL: define dso_local void @_Z21test_svst1wq_vnum_f32u10__SVBool_tPfu13__SVFloat32_t // CPP-CHECK-SAME: ( [[PRED:%.*]], ptr noundef [[BASE:%.*]], [[ZT:%.*]]) #[[ATTR0]] { // CPP-CHECK-NEXT: entry: // CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PRED]]) @@ -145,7 +145,7 @@ void test_svst1wq_f32(svbool_t pred, float32_t const * base, svfloat32_t zt) { // CPP-CHECK-NEXT: tail call void @llvm.aarch64.sve.st1wq.nxv4f32( [[ZT]], [[TMP0]], ptr [[TMP3]]) // CPP-CHECK-NEXT: ret void // -void test_svst1wq_vnum_f32(svbool_t pred, float32_t const * base, svfloat32_t zt) { +void test_svst1wq_vnum_f32(svbool_t pred, float32_t *base, svfloat32_t zt) { SVE_ACLE_FUNC(svst1wq_vnum, _f32, , )(pred, base, 1, zt); } @@ -159,14 +159,14 @@ void test_svst1wq_vnum_f32(svbool_t pred, float32_t const * base, svfloat32_t zt // CHECK-NEXT: tail call void @llvm.aarch64.sve.st1dq.nxv2i64( [[ZT]], [[TMP0]], ptr [[BASE]]) // CHECK-NEXT: ret void // -// CPP-CHECK-LABEL: define dso_local void @_Z16test_svst1dq_u64u10__SVBool_tPKmu12__SVUint64_t +// CPP-CHECK-LABEL: define dso_local void @_Z16test_svst1dq_u64u10__SVBool_tPmu12__SVUint64_t // CPP-CHECK-SAME: ( [[PRED:%.*]], ptr noundef [[BASE:%.*]], [[ZT:%.*]]) #[[ATTR0]] { // CPP-CHECK-NEXT: entry: // CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PRED]]) // CPP-CHECK-NEXT: tail call void @llvm.aarch64.sve.st1dq.nxv2i64( [[ZT]], [[TMP0]], ptr [[BASE]]) // CPP-CHECK-NEXT: ret void // -void test_svst1dq_u64(svbool_t pred, uint64_t const * base, svuint64_t zt) { +void test_svst1dq_u64(svbool_t pred, uint64_t *base, svuint64_t zt) { SVE_ACLE_FUNC(svst1dq, _u64, , )(pred, base, zt); } @@ -180,7 +180,7 @@ void test_svst1dq_u64(svbool_t pred, uint64_t const * base, svuint64_t zt) { // CHECK-NEXT: tail call void @llvm.aarch64.sve.st1dq.nxv2i64( [[ZT]], [[TMP0]], ptr [[TMP2]]) // CHECK-NEXT: ret void // -// CPP-CHECK-LABEL: define dso_local void @_Z21test_svst1dq_vnum_u64u10__SVBool_tPKmu12__SVUint64_t +// CPP-CHECK-LABEL: define dso_local void @_Z21test_svst1dq_vnum_u64u10__SVBool_tPmu12__SVUint64_t // CPP-CHECK-SAME: ( [[PRED:%.*]], ptr noundef [[BASE:%.*]], [[ZT:%.*]]) #[[ATTR0]] { // CPP-CHECK-NEXT: entry: // CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PRED]]) @@ -190,7 +190,7 @@ void test_svst1dq_u64(svbool_t pred, uint64_t const * base, svuint64_t zt) { // CPP-CHECK-NEXT: tail call void @llvm.aarch64.sve.st1dq.nxv2i64( [[ZT]], [[TMP0]], ptr [[TMP2]]) // CPP-CHECK-NEXT: ret void // -void test_svst1dq_vnum_u64(svbool_t pred, uint64_t const * base, svuint64_t zt) { +void test_svst1dq_vnum_u64(svbool_t pred, uint64_t *base, svuint64_t zt) { SVE_ACLE_FUNC(svst1dq_vnum, _u64, , )(pred, base, -8, zt); } @@ -201,14 +201,14 @@ void test_svst1dq_vnum_u64(svbool_t pred, uint64_t const * base, svuint64_t zt) // CHECK-NEXT: tail call void @llvm.aarch64.sve.st1dq.nxv2i64( [[ZT]], [[TMP0]], ptr [[BASE]]) // CHECK-NEXT: ret void // -// CPP-CHECK-LABEL: define dso_local void @_Z16test_svst1dq_s64u10__SVBool_tPKlu11__SVInt64_t +// CPP-CHECK-LABEL: define dso_local void @_Z16test_svst1dq_s64u10__SVBool_tPlu11__SVInt64_t // CPP-CHECK-SAME: ( [[PRED:%.*]], ptr noundef [[BASE:%.*]], [[ZT:%.*]]) #[[ATTR0]] { // CPP-CHECK-NEXT: entry: // CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PRED]]) // CPP-CHECK-NEXT: tail call void @llvm.aarch64.sve.st1dq.nxv2i64( [[ZT]], [[TMP0]], ptr [[BASE]]) // CPP-CHECK-NEXT: ret void // -void test_svst1dq_s64(svbool_t pred, int64_t const * base, svint64_t zt) { +void test_svst1dq_s64(svbool_t pred, int64_t *base, svint64_t zt) { SVE_ACLE_FUNC(svst1dq, _s64, , )(pred, base, zt); } @@ -222,7 +222,7 @@ void test_svst1dq_s64(svbool_t pred, int64_t const * base, svint64_t zt) { // CHECK-NEXT: tail call void @llvm.aarch64.sve.st1dq.nxv2i64( [[ZT]], [[TMP0]], ptr [[TMP2]]) // CHECK-NEXT: ret void // -// CPP-CHECK-LABEL: define dso_local void @_Z21test_svst1dq_vnum_s64u10__SVBool_tPKlu11__SVInt64_t +// CPP-CHECK-LABEL: define dso_local void @_Z21test_svst1dq_vnum_s64u10__SVBool_tPlu11__SVInt64_t // CPP-CHECK-SAME: ( [[PRED:%.*]], ptr noundef [[BASE:%.*]], [[ZT:%.*]]) #[[ATTR0]] { // CPP-CHECK-NEXT: entry: // CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PRED]]) @@ -232,7 +232,7 @@ void test_svst1dq_s64(svbool_t pred, int64_t const * base, svint64_t zt) { // CPP-CHECK-NEXT: tail call void @llvm.aarch64.sve.st1dq.nxv2i64( [[ZT]], [[TMP0]], ptr [[TMP2]]) // CPP-CHECK-NEXT: ret void // -void test_svst1dq_vnum_s64(svbool_t pred, int64_t const * base, svint64_t zt) { +void test_svst1dq_vnum_s64(svbool_t pred, int64_t *base, svint64_t zt) { SVE_ACLE_FUNC(svst1dq_vnum, _s64, , )(pred, base, -8, zt); } @@ -243,14 +243,14 @@ void test_svst1dq_vnum_s64(svbool_t pred, int64_t const * base, svint64_t zt) { // CHECK-NEXT: tail call void @llvm.aarch64.sve.st1dq.nxv2f64( [[ZT]], [[TMP0]], ptr [[BASE]]) // CHECK-NEXT: ret void // -// CPP-CHECK-LABEL: define dso_local void @_Z16test_svst1dq_f64u10__SVBool_tPKdu13__SVFloat64_t +// CPP-CHECK-LABEL: define dso_local void @_Z16test_svst1dq_f64u10__SVBool_tPdu13__SVFloat64_t // CPP-CHECK-SAME: ( [[PRED:%.*]], ptr noundef [[BASE:%.*]], [[ZT:%.*]]) #[[ATTR0]] { // CPP-CHECK-NEXT: entry: // CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PRED]]) // CPP-CHECK-NEXT: tail call void @llvm.aarch64.sve.st1dq.nxv2f64( [[ZT]], [[TMP0]], ptr [[BASE]]) // CPP-CHECK-NEXT: ret void // -void test_svst1dq_f64(svbool_t pred, float64_t const * base, svfloat64_t zt) { +void test_svst1dq_f64(svbool_t pred, float64_t *base, svfloat64_t zt) { SVE_ACLE_FUNC(svst1dq, _f64, , )(pred, base, zt); } @@ -264,7 +264,7 @@ void test_svst1dq_f64(svbool_t pred, float64_t const * base, svfloat64_t zt) { // CHECK-NEXT: tail call void @llvm.aarch64.sve.st1dq.nxv2f64( [[ZT]], [[TMP0]], ptr [[TMP2]]) // CHECK-NEXT: ret void // -// CPP-CHECK-LABEL: define dso_local void @_Z21test_svst1dq_vnum_f64u10__SVBool_tPKdu13__SVFloat64_t +// CPP-CHECK-LABEL: define dso_local void @_Z21test_svst1dq_vnum_f64u10__SVBool_tPdu13__SVFloat64_t // CPP-CHECK-SAME: ( [[PRED:%.*]], ptr noundef [[BASE:%.*]], [[ZT:%.*]]) #[[ATTR0]] { // CPP-CHECK-NEXT: entry: // CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PRED]]) @@ -274,6 +274,6 @@ void test_svst1dq_f64(svbool_t pred, float64_t const * base, svfloat64_t zt) { // CPP-CHECK-NEXT: tail call void @llvm.aarch64.sve.st1dq.nxv2f64( [[ZT]], [[TMP0]], ptr [[TMP2]]) // CPP-CHECK-NEXT: ret void // -void test_svst1dq_vnum_f64(svbool_t pred, float64_t const * base, svfloat64_t zt) { +void test_svst1dq_vnum_f64(svbool_t pred, float64_t *base, svfloat64_t zt) { SVE_ACLE_FUNC(svst1dq_vnum, _f64, , )(pred, base, -8, zt); } diff --git a/clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_store.c b/clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_store.c index 657787e851ee2..b91780304dacb 100644 --- a/clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_store.c +++ b/clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_store.c @@ -1931,6 +1931,22 @@ void test_svst1q_scatter_u64index_s16(svbool_t pg, int16_t *base, svuint64_t idx SVE_ACLE_FUNC(svst1q_scatter_, u64, index, _s16)(pg, base, idx, data); } +// CHECK-LABEL: @test_svst1q_scatter_s64index_s16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PG:%.*]]) +// CHECK-NEXT: tail call void @llvm.aarch64.sve.st1q.scatter.index.nxv8i16( [[DATA:%.*]], [[TMP0]], ptr [[BASE:%.*]], [[IDX:%.*]]) +// CHECK-NEXT: ret void +// +// CPP-CHECK-LABEL: @_Z32test_svst1q_scatter_s64index_s16u10__SVBool_tPsu11__SVInt64_tu11__SVInt16_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PG:%.*]]) +// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sve.st1q.scatter.index.nxv8i16( [[DATA:%.*]], [[TMP0]], ptr [[BASE:%.*]], [[IDX:%.*]]) +// CPP-CHECK-NEXT: ret void +// +void test_svst1q_scatter_s64index_s16(svbool_t pg, int16_t *base, svint64_t idx, svint16_t data) { + SVE_ACLE_FUNC(svst1q_scatter_, s64, index, _s16)(pg, base, idx, data); +} + // CHECK-LABEL: @test_svst1q_scatter_u64index_u16( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PG:%.*]]) @@ -1947,6 +1963,22 @@ void test_svst1q_scatter_u64index_u16(svbool_t pg, uint16_t *base, svuint64_t id SVE_ACLE_FUNC(svst1q_scatter_, u64, index, _u16)(pg, base, idx, data); } +// CHECK-LABEL: @test_svst1q_scatter_s64index_u16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PG:%.*]]) +// CHECK-NEXT: tail call void @llvm.aarch64.sve.st1q.scatter.index.nxv8i16( [[DATA:%.*]], [[TMP0]], ptr [[BASE:%.*]], [[IDX:%.*]]) +// CHECK-NEXT: ret void +// +// CPP-CHECK-LABEL: @_Z32test_svst1q_scatter_s64index_u16u10__SVBool_tPtu11__SVInt64_tu12__SVUint16_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PG:%.*]]) +// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sve.st1q.scatter.index.nxv8i16( [[DATA:%.*]], [[TMP0]], ptr [[BASE:%.*]], [[IDX:%.*]]) +// CPP-CHECK-NEXT: ret void +// +void test_svst1q_scatter_s64index_u16(svbool_t pg, uint16_t *base, svint64_t idx, svuint16_t data) { + SVE_ACLE_FUNC(svst1q_scatter_, s64, index, _u16)(pg, base, idx, data); +} + // CHECK-LABEL: @test_svst1q_scatter_u64index_s32( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PG:%.*]]) @@ -1963,6 +1995,22 @@ void test_svst1q_scatter_u64index_s32(svbool_t pg, int32_t *base, svuint64_t idx SVE_ACLE_FUNC(svst1q_scatter_, u64, index, _s32)(pg, base, idx, data); } +// CHECK-LABEL: @test_svst1q_scatter_s64index_s32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PG:%.*]]) +// CHECK-NEXT: tail call void @llvm.aarch64.sve.st1q.scatter.index.nxv4i32( [[DATA:%.*]], [[TMP0]], ptr [[BASE:%.*]], [[IDX:%.*]]) +// CHECK-NEXT: ret void +// +// CPP-CHECK-LABEL: @_Z32test_svst1q_scatter_s64index_s32u10__SVBool_tPiu11__SVInt64_tu11__SVInt32_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PG:%.*]]) +// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sve.st1q.scatter.index.nxv4i32( [[DATA:%.*]], [[TMP0]], ptr [[BASE:%.*]], [[IDX:%.*]]) +// CPP-CHECK-NEXT: ret void +// +void test_svst1q_scatter_s64index_s32(svbool_t pg, int32_t *base, svint64_t idx, svint32_t data) { + SVE_ACLE_FUNC(svst1q_scatter_, s64, index, _s32)(pg, base, idx, data); +} + // CHECK-LABEL: @test_svst1q_scatter_u64index_u32( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PG:%.*]]) @@ -1979,6 +2027,22 @@ void test_svst1q_scatter_u64index_u32(svbool_t pg, uint32_t *base, svuint64_t id SVE_ACLE_FUNC(svst1q_scatter_, u64, index, _u32)(pg, base, idx, data); } +// CHECK-LABEL: @test_svst1q_scatter_s64index_u32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PG:%.*]]) +// CHECK-NEXT: tail call void @llvm.aarch64.sve.st1q.scatter.index.nxv4i32( [[DATA:%.*]], [[TMP0]], ptr [[BASE:%.*]], [[IDX:%.*]]) +// CHECK-NEXT: ret void +// +// CPP-CHECK-LABEL: @_Z32test_svst1q_scatter_s64index_u32u10__SVBool_tPju11__SVInt64_tu12__SVUint32_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PG:%.*]]) +// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sve.st1q.scatter.index.nxv4i32( [[DATA:%.*]], [[TMP0]], ptr [[BASE:%.*]], [[IDX:%.*]]) +// CPP-CHECK-NEXT: ret void +// +void test_svst1q_scatter_s64index_u32(svbool_t pg, uint32_t *base, svint64_t idx, svuint32_t data) { + SVE_ACLE_FUNC(svst1q_scatter_, s64, index, _u32)(pg, base, idx, data); +} + // CHECK-LABEL: @test_svst1q_scatter_u64index_s64( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PG:%.*]]) @@ -1995,6 +2059,22 @@ void test_svst1q_scatter_u64index_s64(svbool_t pg, int64_t *base, svuint64_t idx SVE_ACLE_FUNC(svst1q_scatter_, u64, index, _s64)(pg, base, idx, data); } +// CHECK-LABEL: @test_svst1q_scatter_s64index_s64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PG:%.*]]) +// CHECK-NEXT: tail call void @llvm.aarch64.sve.st1q.scatter.index.nxv2i64( [[DATA:%.*]], [[TMP0]], ptr [[BASE:%.*]], [[IDX:%.*]]) +// CHECK-NEXT: ret void +// +// CPP-CHECK-LABEL: @_Z32test_svst1q_scatter_s64index_s64u10__SVBool_tPlu11__SVInt64_tS1_( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PG:%.*]]) +// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sve.st1q.scatter.index.nxv2i64( [[DATA:%.*]], [[TMP0]], ptr [[BASE:%.*]], [[IDX:%.*]]) +// CPP-CHECK-NEXT: ret void +// +void test_svst1q_scatter_s64index_s64(svbool_t pg, int64_t *base, svint64_t idx, svint64_t data) { + SVE_ACLE_FUNC(svst1q_scatter_, s64, index, _s64)(pg, base, idx, data); +} + // CHECK-LABEL: @test_svst1q_scatter_u64index_u64( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PG:%.*]]) @@ -2011,6 +2091,22 @@ void test_svst1q_scatter_u64index_u64(svbool_t pg, uint64_t *base, svuint64_t id SVE_ACLE_FUNC(svst1q_scatter_, u64, index, _u64)(pg, base, idx, data); } +// CHECK-LABEL: @test_svst1q_scatter_s64index_u64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PG:%.*]]) +// CHECK-NEXT: tail call void @llvm.aarch64.sve.st1q.scatter.index.nxv2i64( [[DATA:%.*]], [[TMP0]], ptr [[BASE:%.*]], [[IDX:%.*]]) +// CHECK-NEXT: ret void +// +// CPP-CHECK-LABEL: @_Z32test_svst1q_scatter_s64index_u64u10__SVBool_tPmu11__SVInt64_tu12__SVUint64_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PG:%.*]]) +// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sve.st1q.scatter.index.nxv2i64( [[DATA:%.*]], [[TMP0]], ptr [[BASE:%.*]], [[IDX:%.*]]) +// CPP-CHECK-NEXT: ret void +// +void test_svst1q_scatter_s64index_u64(svbool_t pg, uint64_t *base, svint64_t idx, svuint64_t data) { + SVE_ACLE_FUNC(svst1q_scatter_, s64, index, _u64)(pg, base, idx, data); +} + // CHECK-LABEL: @test_svst1q_scatter_u64index_bf16( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PG:%.*]]) @@ -2027,6 +2123,22 @@ void test_svst1q_scatter_u64index_bf16(svbool_t pg, bfloat16_t *base, svuint64_t SVE_ACLE_FUNC(svst1q_scatter_, u64, index, _bf16)(pg, base, idx, data); } +// CHECK-LABEL: @test_svst1q_scatter_s64index_bf16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PG:%.*]]) +// CHECK-NEXT: tail call void @llvm.aarch64.sve.st1q.scatter.index.nxv8bf16( [[DATA:%.*]], [[TMP0]], ptr [[BASE:%.*]], [[IDX:%.*]]) +// CHECK-NEXT: ret void +// +// CPP-CHECK-LABEL: @_Z33test_svst1q_scatter_s64index_bf16u10__SVBool_tPu6__bf16u11__SVInt64_tu14__SVBfloat16_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PG:%.*]]) +// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sve.st1q.scatter.index.nxv8bf16( [[DATA:%.*]], [[TMP0]], ptr [[BASE:%.*]], [[IDX:%.*]]) +// CPP-CHECK-NEXT: ret void +// +void test_svst1q_scatter_s64index_bf16(svbool_t pg, bfloat16_t *base, svint64_t idx, svbfloat16_t data) { + SVE_ACLE_FUNC(svst1q_scatter_, s64, index, _bf16)(pg, base, idx, data); +} + // CHECK-LABEL: @test_svst1q_scatter_u64index_f16( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PG:%.*]]) @@ -2043,6 +2155,22 @@ void test_svst1q_scatter_u64index_f16(svbool_t pg, float16_t *base, svuint64_t i SVE_ACLE_FUNC(svst1q_scatter_, u64, index, _f16)(pg, base, idx, data); } +// CHECK-LABEL: @test_svst1q_scatter_s64index_f16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PG:%.*]]) +// CHECK-NEXT: tail call void @llvm.aarch64.sve.st1q.scatter.index.nxv8f16( [[DATA:%.*]], [[TMP0]], ptr [[BASE:%.*]], [[IDX:%.*]]) +// CHECK-NEXT: ret void +// +// CPP-CHECK-LABEL: @_Z32test_svst1q_scatter_s64index_f16u10__SVBool_tPDhu11__SVInt64_tu13__SVFloat16_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PG:%.*]]) +// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sve.st1q.scatter.index.nxv8f16( [[DATA:%.*]], [[TMP0]], ptr [[BASE:%.*]], [[IDX:%.*]]) +// CPP-CHECK-NEXT: ret void +// +void test_svst1q_scatter_s64index_f16(svbool_t pg, float16_t *base, svint64_t idx, svfloat16_t data) { + SVE_ACLE_FUNC(svst1q_scatter_, s64, index, _f16)(pg, base, idx, data); +} + // CHECK-LABEL: @test_svst1q_scatter_u64index_f32( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PG:%.*]]) @@ -2059,6 +2187,22 @@ void test_svst1q_scatter_u64index_f32(svbool_t pg, float32_t *base, svuint64_t i SVE_ACLE_FUNC(svst1q_scatter_, u64, index, _f32)(pg, base, idx, data); } +// CHECK-LABEL: @test_svst1q_scatter_s64index_f32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PG:%.*]]) +// CHECK-NEXT: tail call void @llvm.aarch64.sve.st1q.scatter.index.nxv4f32( [[DATA:%.*]], [[TMP0]], ptr [[BASE:%.*]], [[IDX:%.*]]) +// CHECK-NEXT: ret void +// +// CPP-CHECK-LABEL: @_Z32test_svst1q_scatter_s64index_f32u10__SVBool_tPfu11__SVInt64_tu13__SVFloat32_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PG:%.*]]) +// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sve.st1q.scatter.index.nxv4f32( [[DATA:%.*]], [[TMP0]], ptr [[BASE:%.*]], [[IDX:%.*]]) +// CPP-CHECK-NEXT: ret void +// +void test_svst1q_scatter_s64index_f32(svbool_t pg, float32_t *base, svint64_t idx, svfloat32_t data) { + SVE_ACLE_FUNC(svst1q_scatter_, s64, index, _f32)(pg, base, idx, data); +} + // CHECK-LABEL: @test_svst1q_scatter_u64index_f64( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PG:%.*]]) @@ -2075,6 +2219,22 @@ void test_svst1q_scatter_u64index_f64(svbool_t pg, float64_t *base, svuint64_t i SVE_ACLE_FUNC(svst1q_scatter_, u64, index, _f64)(pg, base, idx, data); } +// CHECK-LABEL: @test_svst1q_scatter_s64index_f64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PG:%.*]]) +// CHECK-NEXT: tail call void @llvm.aarch64.sve.st1q.scatter.index.nxv2f64( [[DATA:%.*]], [[TMP0]], ptr [[BASE:%.*]], [[IDX:%.*]]) +// CHECK-NEXT: ret void +// +// CPP-CHECK-LABEL: @_Z32test_svst1q_scatter_s64index_f64u10__SVBool_tPdu11__SVInt64_tu13__SVFloat64_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PG:%.*]]) +// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sve.st1q.scatter.index.nxv2f64( [[DATA:%.*]], [[TMP0]], ptr [[BASE:%.*]], [[IDX:%.*]]) +// CPP-CHECK-NEXT: ret void +// +void test_svst1q_scatter_s64index_f64(svbool_t pg, float64_t *base, svint64_t idx, svfloat64_t data) { + SVE_ACLE_FUNC(svst1q_scatter_, s64, index, _f64)(pg, base, idx, data); +} + // CHECK-LABEL: @test_svst1q_scatter_u64base_index_s16( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PG:%.*]]) @@ -2271,6 +2431,22 @@ void test_svst1q_scatter_u64offset_s8(svbool_t pg, int8_t *base, svuint64_t off, SVE_ACLE_FUNC(svst1q_scatter_,u64,offset,_s8)(pg, base, off, data); } +// CHECK-LABEL: @test_svst1q_scatter_s64offset_s8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PG:%.*]]) +// CHECK-NEXT: tail call void @llvm.aarch64.sve.st1q.scatter.vector.offset.nxv16i8( [[DATA:%.*]], [[TMP0]], ptr [[BASE:%.*]], [[OFF:%.*]]) +// CHECK-NEXT: ret void +// +// CPP-CHECK-LABEL: @_Z32test_svst1q_scatter_s64offset_s8u10__SVBool_tPau11__SVInt64_tu10__SVInt8_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PG:%.*]]) +// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sve.st1q.scatter.vector.offset.nxv16i8( [[DATA:%.*]], [[TMP0]], ptr [[BASE:%.*]], [[OFF:%.*]]) +// CPP-CHECK-NEXT: ret void +// +void test_svst1q_scatter_s64offset_s8(svbool_t pg, int8_t *base, svint64_t off, svint8_t data) { + SVE_ACLE_FUNC(svst1q_scatter_,s64,offset,_s8)(pg, base, off, data); +} + // CHECK-LABEL: @test_svst1q_scatter_u64offset_u8( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PG:%.*]]) @@ -2287,6 +2463,22 @@ void test_svst1q_scatter_u64offset_u8(svbool_t pg, uint8_t *base, svuint64_t off SVE_ACLE_FUNC(svst1q_scatter_,u64,offset,_u8)(pg, base, off, data); } +// CHECK-LABEL: @test_svst1q_scatter_s64offset_u8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PG:%.*]]) +// CHECK-NEXT: tail call void @llvm.aarch64.sve.st1q.scatter.vector.offset.nxv16i8( [[DATA:%.*]], [[TMP0]], ptr [[BASE:%.*]], [[OFF:%.*]]) +// CHECK-NEXT: ret void +// +// CPP-CHECK-LABEL: @_Z32test_svst1q_scatter_s64offset_u8u10__SVBool_tPhu11__SVInt64_tu11__SVUint8_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PG:%.*]]) +// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sve.st1q.scatter.vector.offset.nxv16i8( [[DATA:%.*]], [[TMP0]], ptr [[BASE:%.*]], [[OFF:%.*]]) +// CPP-CHECK-NEXT: ret void +// +void test_svst1q_scatter_s64offset_u8(svbool_t pg, uint8_t *base, svint64_t off, svuint8_t data) { + SVE_ACLE_FUNC(svst1q_scatter_,s64,offset,_u8)(pg, base, off, data); +} + // CHECK-LABEL: @test_svst1q_scatter_u64offset_s16( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PG:%.*]]) @@ -2303,6 +2495,22 @@ void test_svst1q_scatter_u64offset_s16(svbool_t pg, int16_t *base, svuint64_t of SVE_ACLE_FUNC(svst1q_scatter_,u64,offset,_s16)(pg, base, off, data); } +// CHECK-LABEL: @test_svst1q_scatter_s64offset_s16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PG:%.*]]) +// CHECK-NEXT: tail call void @llvm.aarch64.sve.st1q.scatter.vector.offset.nxv8i16( [[DATA:%.*]], [[TMP0]], ptr [[BASE:%.*]], [[OFF:%.*]]) +// CHECK-NEXT: ret void +// +// CPP-CHECK-LABEL: @_Z33test_svst1q_scatter_s64offset_s16u10__SVBool_tPsu11__SVInt64_tu11__SVInt16_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PG:%.*]]) +// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sve.st1q.scatter.vector.offset.nxv8i16( [[DATA:%.*]], [[TMP0]], ptr [[BASE:%.*]], [[OFF:%.*]]) +// CPP-CHECK-NEXT: ret void +// +void test_svst1q_scatter_s64offset_s16(svbool_t pg, int16_t *base, svint64_t off, svint16_t data) { + SVE_ACLE_FUNC(svst1q_scatter_,s64,offset,_s16)(pg, base, off, data); +} + // CHECK-LABEL: @test_svst1q_scatter_u64offset_u16( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PG:%.*]]) @@ -2319,6 +2527,22 @@ void test_svst1q_scatter_u64offset_u16(svbool_t pg, uint16_t *base, svuint64_t o SVE_ACLE_FUNC(svst1q_scatter_,u64,offset,_u16)(pg, base, off, data); } +// CHECK-LABEL: @test_svst1q_scatter_s64offset_u16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PG:%.*]]) +// CHECK-NEXT: tail call void @llvm.aarch64.sve.st1q.scatter.vector.offset.nxv8i16( [[DATA:%.*]], [[TMP0]], ptr [[BASE:%.*]], [[OFF:%.*]]) +// CHECK-NEXT: ret void +// +// CPP-CHECK-LABEL: @_Z33test_svst1q_scatter_s64offset_u16u10__SVBool_tPtu11__SVInt64_tu12__SVUint16_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PG:%.*]]) +// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sve.st1q.scatter.vector.offset.nxv8i16( [[DATA:%.*]], [[TMP0]], ptr [[BASE:%.*]], [[OFF:%.*]]) +// CPP-CHECK-NEXT: ret void +// +void test_svst1q_scatter_s64offset_u16(svbool_t pg, uint16_t *base, svint64_t off, svuint16_t data) { + SVE_ACLE_FUNC(svst1q_scatter_,s64,offset,_u16)(pg, base, off, data); +} + // CHECK-LABEL: @test_svst1q_scatter_u64offset_s32( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PG:%.*]]) @@ -2335,6 +2559,22 @@ void test_svst1q_scatter_u64offset_s32(svbool_t pg, int32_t *base, svuint64_t of SVE_ACLE_FUNC(svst1q_scatter_,u64,offset,_s32)(pg, base, off, data); } +// CHECK-LABEL: @test_svst1q_scatter_s64offset_s32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PG:%.*]]) +// CHECK-NEXT: tail call void @llvm.aarch64.sve.st1q.scatter.vector.offset.nxv4i32( [[DATA:%.*]], [[TMP0]], ptr [[BASE:%.*]], [[OFF:%.*]]) +// CHECK-NEXT: ret void +// +// CPP-CHECK-LABEL: @_Z33test_svst1q_scatter_s64offset_s32u10__SVBool_tPiu11__SVInt64_tu11__SVInt32_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PG:%.*]]) +// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sve.st1q.scatter.vector.offset.nxv4i32( [[DATA:%.*]], [[TMP0]], ptr [[BASE:%.*]], [[OFF:%.*]]) +// CPP-CHECK-NEXT: ret void +// +void test_svst1q_scatter_s64offset_s32(svbool_t pg, int32_t *base, svint64_t off, svint32_t data) { + SVE_ACLE_FUNC(svst1q_scatter_,s64,offset,_s32)(pg, base, off, data); +} + // CHECK-LABEL: @test_svst1q_scatter_u64offset_u32( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PG:%.*]]) @@ -2351,6 +2591,22 @@ void test_svst1q_scatter_u64offset_u32(svbool_t pg, uint32_t *base, svuint64_t o SVE_ACLE_FUNC(svst1q_scatter_,u64,offset,_u32)(pg, base, off, data); } +// CHECK-LABEL: @test_svst1q_scatter_s64offset_u32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PG:%.*]]) +// CHECK-NEXT: tail call void @llvm.aarch64.sve.st1q.scatter.vector.offset.nxv4i32( [[DATA:%.*]], [[TMP0]], ptr [[BASE:%.*]], [[OFF:%.*]]) +// CHECK-NEXT: ret void +// +// CPP-CHECK-LABEL: @_Z33test_svst1q_scatter_s64offset_u32u10__SVBool_tPju11__SVInt64_tu12__SVUint32_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PG:%.*]]) +// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sve.st1q.scatter.vector.offset.nxv4i32( [[DATA:%.*]], [[TMP0]], ptr [[BASE:%.*]], [[OFF:%.*]]) +// CPP-CHECK-NEXT: ret void +// +void test_svst1q_scatter_s64offset_u32(svbool_t pg, uint32_t *base, svint64_t off, svuint32_t data) { + SVE_ACLE_FUNC(svst1q_scatter_,s64,offset,_u32)(pg, base, off, data); +} + // CHECK-LABEL: @test_svst1q_scatter_u64offset_s64( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PG:%.*]]) @@ -2367,6 +2623,22 @@ void test_svst1q_scatter_u64offset_s64(svbool_t pg, int64_t *base, svuint64_t of SVE_ACLE_FUNC(svst1q_scatter_,u64,offset,_s64)(pg, base, off, data); } +// CHECK-LABEL: @test_svst1q_scatter_s64offset_s64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PG:%.*]]) +// CHECK-NEXT: tail call void @llvm.aarch64.sve.st1q.scatter.vector.offset.nxv2i64( [[DATA:%.*]], [[TMP0]], ptr [[BASE:%.*]], [[OFF:%.*]]) +// CHECK-NEXT: ret void +// +// CPP-CHECK-LABEL: @_Z33test_svst1q_scatter_s64offset_s64u10__SVBool_tPlu11__SVInt64_tS1_( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PG:%.*]]) +// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sve.st1q.scatter.vector.offset.nxv2i64( [[DATA:%.*]], [[TMP0]], ptr [[BASE:%.*]], [[OFF:%.*]]) +// CPP-CHECK-NEXT: ret void +// +void test_svst1q_scatter_s64offset_s64(svbool_t pg, int64_t *base, svint64_t off, svint64_t data) { + SVE_ACLE_FUNC(svst1q_scatter_,s64,offset,_s64)(pg, base, off, data); +} + // CHECK-LABEL: @test_svst1q_scatter_u64offset_u64( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PG:%.*]]) @@ -2383,6 +2655,22 @@ void test_svst1q_scatter_u64offset_u64(svbool_t pg, uint64_t *base, svuint64_t o SVE_ACLE_FUNC(svst1q_scatter_,u64,offset,_u64)(pg, base, off, data); } +// CHECK-LABEL: @test_svst1q_scatter_s64offset_u64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PG:%.*]]) +// CHECK-NEXT: tail call void @llvm.aarch64.sve.st1q.scatter.vector.offset.nxv2i64( [[DATA:%.*]], [[TMP0]], ptr [[BASE:%.*]], [[OFF:%.*]]) +// CHECK-NEXT: ret void +// +// CPP-CHECK-LABEL: @_Z33test_svst1q_scatter_s64offset_u64u10__SVBool_tPmu11__SVInt64_tu12__SVUint64_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PG:%.*]]) +// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sve.st1q.scatter.vector.offset.nxv2i64( [[DATA:%.*]], [[TMP0]], ptr [[BASE:%.*]], [[OFF:%.*]]) +// CPP-CHECK-NEXT: ret void +// +void test_svst1q_scatter_s64offset_u64(svbool_t pg, uint64_t *base, svint64_t off, svuint64_t data) { + SVE_ACLE_FUNC(svst1q_scatter_,s64,offset,_u64)(pg, base, off, data); +} + // CHECK-LABEL: @test_svst1q_scatter_u64offset_bf16( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PG:%.*]]) @@ -2399,6 +2687,22 @@ void test_svst1q_scatter_u64offset_bf16(svbool_t pg, bfloat16_t *base, svuint64_ SVE_ACLE_FUNC(svst1q_scatter_,u64,offset,_bf16)(pg, base, off, data); } +// CHECK-LABEL: @test_svst1q_scatter_s64offset_bf16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PG:%.*]]) +// CHECK-NEXT: tail call void @llvm.aarch64.sve.st1q.scatter.vector.offset.nxv8bf16( [[DATA:%.*]], [[TMP0]], ptr [[BASE:%.*]], [[OFF:%.*]]) +// CHECK-NEXT: ret void +// +// CPP-CHECK-LABEL: @_Z34test_svst1q_scatter_s64offset_bf16u10__SVBool_tPu6__bf16u11__SVInt64_tu14__SVBfloat16_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PG:%.*]]) +// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sve.st1q.scatter.vector.offset.nxv8bf16( [[DATA:%.*]], [[TMP0]], ptr [[BASE:%.*]], [[OFF:%.*]]) +// CPP-CHECK-NEXT: ret void +// +void test_svst1q_scatter_s64offset_bf16(svbool_t pg, bfloat16_t *base, svint64_t off, svbfloat16_t data) { + SVE_ACLE_FUNC(svst1q_scatter_,s64,offset,_bf16)(pg, base, off, data); +} + // CHECK-LABEL: @test_svst1q_scatter_u64offset_f16( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PG:%.*]]) @@ -2415,6 +2719,22 @@ void test_svst1q_scatter_u64offset_f16(svbool_t pg, float16_t *base, svuint64_t SVE_ACLE_FUNC(svst1q_scatter_,u64,offset,_f16)(pg, base, off, data); } +// CHECK-LABEL: @test_svst1q_scatter_s64offset_f16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PG:%.*]]) +// CHECK-NEXT: tail call void @llvm.aarch64.sve.st1q.scatter.vector.offset.nxv8f16( [[DATA:%.*]], [[TMP0]], ptr [[BASE:%.*]], [[OFF:%.*]]) +// CHECK-NEXT: ret void +// +// CPP-CHECK-LABEL: @_Z33test_svst1q_scatter_s64offset_f16u10__SVBool_tPDhu11__SVInt64_tu13__SVFloat16_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PG:%.*]]) +// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sve.st1q.scatter.vector.offset.nxv8f16( [[DATA:%.*]], [[TMP0]], ptr [[BASE:%.*]], [[OFF:%.*]]) +// CPP-CHECK-NEXT: ret void +// +void test_svst1q_scatter_s64offset_f16(svbool_t pg, float16_t *base, svint64_t off, svfloat16_t data) { + SVE_ACLE_FUNC(svst1q_scatter_,s64,offset,_f16)(pg, base, off, data); +} + // CHECK-LABEL: @test_svst1q_scatter_u64offset_f32( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PG:%.*]]) @@ -2431,6 +2751,22 @@ void test_svst1q_scatter_u64offset_f32(svbool_t pg, float32_t *base, svuint64_t SVE_ACLE_FUNC(svst1q_scatter_,u64,offset,_f32)(pg, base, off, data); } +// CHECK-LABEL: @test_svst1q_scatter_s64offset_f32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PG:%.*]]) +// CHECK-NEXT: tail call void @llvm.aarch64.sve.st1q.scatter.vector.offset.nxv4f32( [[DATA:%.*]], [[TMP0]], ptr [[BASE:%.*]], [[OFF:%.*]]) +// CHECK-NEXT: ret void +// +// CPP-CHECK-LABEL: @_Z33test_svst1q_scatter_s64offset_f32u10__SVBool_tPfu11__SVInt64_tu13__SVFloat32_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PG:%.*]]) +// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sve.st1q.scatter.vector.offset.nxv4f32( [[DATA:%.*]], [[TMP0]], ptr [[BASE:%.*]], [[OFF:%.*]]) +// CPP-CHECK-NEXT: ret void +// +void test_svst1q_scatter_s64offset_f32(svbool_t pg, float32_t *base, svint64_t off, svfloat32_t data) { + SVE_ACLE_FUNC(svst1q_scatter_,s64,offset,_f32)(pg, base, off, data); +} + // CHECK-LABEL: @test_svst1q_scatter_u64offset_f64( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PG:%.*]]) @@ -2446,3 +2782,19 @@ void test_svst1q_scatter_u64offset_f32(svbool_t pg, float32_t *base, svuint64_t void test_svst1q_scatter_u64offset_f64(svbool_t pg, float64_t *base, svuint64_t off, svfloat64_t data) { SVE_ACLE_FUNC(svst1q_scatter_,u64,offset,_f64)(pg, base, off, data); } + +// CHECK-LABEL: @test_svst1q_scatter_s64offset_f64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PG:%.*]]) +// CHECK-NEXT: tail call void @llvm.aarch64.sve.st1q.scatter.vector.offset.nxv2f64( [[DATA:%.*]], [[TMP0]], ptr [[BASE:%.*]], [[OFF:%.*]]) +// CHECK-NEXT: ret void +// +// CPP-CHECK-LABEL: @_Z33test_svst1q_scatter_s64offset_f64u10__SVBool_tPdu11__SVInt64_tu13__SVFloat64_t( +// CPP-CHECK-NEXT: entry: +// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call @llvm.aarch64.sve.convert.from.svbool.nxv1i1( [[PG:%.*]]) +// CPP-CHECK-NEXT: tail call void @llvm.aarch64.sve.st1q.scatter.vector.offset.nxv2f64( [[DATA:%.*]], [[TMP0]], ptr [[BASE:%.*]], [[OFF:%.*]]) +// CPP-CHECK-NEXT: ret void +// +void test_svst1q_scatter_s64offset_f64(svbool_t pg, float64_t *base, svint64_t off, svfloat64_t data) { + SVE_ACLE_FUNC(svst1q_scatter_,s64,offset,_f64)(pg, base, off, data); +} diff --git a/clang/test/CodeGen/attr-target-version.c b/clang/test/CodeGen/attr-target-version.c index 428e7937d8d39..951401c498deb 100644 --- a/clang/test/CodeGen/attr-target-version.c +++ b/clang/test/CodeGen/attr-target-version.c @@ -143,10 +143,12 @@ int caller(void) { return used_def_without_default_decl() + used_decl_without_de // CHECK: @fmv_d = internal ifunc i32 (), ptr @fmv_d.resolver // CHECK: @fmv_c = weak_odr ifunc void (), ptr @fmv_c.resolver // CHECK: @fmv_inline = weak_odr ifunc i32 (), ptr @fmv_inline.resolver +// CHECK: @reca = weak_odr ifunc void (), ptr @reca.resolver // CHECK: @unused_with_default_def = weak_odr ifunc i32 (), ptr @unused_with_default_def.resolver // CHECK: @unused_with_implicit_default_def = weak_odr ifunc i32 (), ptr @unused_with_implicit_default_def.resolver // CHECK: @unused_with_implicit_forward_default_def = weak_odr ifunc i32 (), ptr @unused_with_implicit_forward_default_def.resolver // CHECK: @default_def_with_version_decls = weak_odr ifunc i32 (), ptr @default_def_with_version_decls.resolver +// CHECK: @recb = weak_odr ifunc void (), ptr @recb.resolver //. // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv._MflagmMfp16fmlMrng @@ -287,8 +289,15 @@ int caller(void) { return used_def_without_default_decl() + used_decl_without_de // // // CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: define {{[^@]+}}@fmv_default.default +// CHECK-SAME: () #[[ATTR9]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 111 +// +// +// CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv_c._Mssbs -// CHECK-SAME: () #[[ATTR16:[0-9]+]] { +// CHECK-SAME: () #[[ATTR17:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret void // @@ -313,13 +322,6 @@ int caller(void) { return used_def_without_default_decl() + used_decl_without_de // // // CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: define {{[^@]+}}@fmv_default -// CHECK-SAME: () #[[ATTR9]] { -// CHECK-NEXT: entry: -// CHECK-NEXT: ret i32 111 -// -// -// CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@recur // CHECK-SAME: () #[[ATTR15]] { // CHECK-NEXT: entry: @@ -895,6 +897,19 @@ int caller(void) { return used_def_without_default_decl() + used_decl_without_de // CHECK-NEXT: ret ptr @fmv_inline.default // // +// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: define {{[^@]+}}@reca.default +// CHECK-SAME: () #[[ATTR9]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: call void @recb() +// CHECK-NEXT: ret void +// +// +// CHECK-LABEL: define {{[^@]+}}@reca.resolver() comdat { +// CHECK-NEXT: resolver_entry: +// CHECK-NEXT: ret ptr @reca.default +// +// // CHECK-LABEL: define {{[^@]+}}@unused_with_default_def.resolver() comdat { // CHECK-NEXT: resolver_entry: // CHECK-NEXT: call void @__init_cpu_features_resolver() @@ -959,6 +974,26 @@ int caller(void) { return used_def_without_default_decl() + used_decl_without_de // CHECK-NEXT: ret ptr @default_def_with_version_decls.default // // +// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: define {{[^@]+}}@recb.default +// CHECK-SAME: () #[[ATTR9]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: call void @func() +// CHECK-NEXT: ret void +// +// +// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: define {{[^@]+}}@func +// CHECK-SAME: () #[[ATTR15]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: ret void +// +// +// CHECK-LABEL: define {{[^@]+}}@recb.resolver() comdat { +// CHECK-NEXT: resolver_entry: +// CHECK-NEXT: ret ptr @recb.default +// +// // CHECK-NOFMV: Function Attrs: noinline nounwind optnone // CHECK-NOFMV-LABEL: define {{[^@]+}}@foo // CHECK-NOFMV-SAME: () #[[ATTR0:[0-9]+]] { diff --git a/clang/test/CodeGen/bounds-checking.c b/clang/test/CodeGen/bounds-checking.c index f6c4880e70a15..f9319ca61670c 100644 --- a/clang/test/CodeGen/bounds-checking.c +++ b/clang/test/CodeGen/bounds-checking.c @@ -1,7 +1,15 @@ -// RUN: %clang_cc1 -fsanitize=local-bounds -emit-llvm -triple x86_64-apple-darwin10 %s -o - | FileCheck %s -// RUN: %clang_cc1 -fsanitize=array-bounds -O -fsanitize-trap=array-bounds -emit-llvm -triple x86_64-apple-darwin10 -DNO_DYNAMIC %s -o - | FileCheck %s -// RUN: %clang_cc1 -fsanitize=local-bounds -fsanitize-trap=local-bounds -O3 -mllvm -bounds-checking-unique-traps -emit-llvm -triple x86_64-apple-darwin10 %s -o - | FileCheck %s --check-prefixes=NOOPTLOCAL -// RUN: %clang_cc1 -fsanitize=array-bounds -fsanitize-trap=array-bounds -O3 -mllvm -ubsan-unique-traps -emit-llvm -triple x86_64-apple-darwin10 %s -o - | FileCheck %s --check-prefixes=NOOPTARRAY +// RUN: %clang_cc1 -fsanitize=local-bounds -fsanitize-trap=local-bounds -emit-llvm -triple x86_64-apple-darwin10 %s -o - | FileCheck %s +// RUN: %clang_cc1 -fsanitize=array-bounds -O -emit-llvm -triple x86_64-apple-darwin10 %s -o - | not FileCheck %s +// RUN: %clang_cc1 -fsanitize=array-bounds -O -fsanitize-trap=array-bounds -emit-llvm -triple x86_64-apple-darwin10 -DNO_DYNAMIC %s -o - | FileCheck %s +// +// RUN: %clang_cc1 -fsanitize=local-bounds -fsanitize-trap=local-bounds -O3 -mllvm -bounds-checking-unique-traps -emit-llvm -triple x86_64-apple-darwin10 %s -o - | FileCheck %s --check-prefixes=NOOPTLOCAL +// RUN: %clang_cc1 -fsanitize=local-bounds -fsanitize-trap=local-bounds -O3 -emit-llvm -triple x86_64-apple-darwin10 %s -o - | not FileCheck %s --check-prefixes=NOOPTLOCAL +// +// N.B. The clang driver defaults to -fsanitize-merge but clang_cc1 effectively +// defaults to -fno-sanitize-merge. +// RUN: %clang_cc1 -fsanitize=array-bounds -fsanitize-trap=array-bounds -O3 -emit-llvm -triple x86_64-apple-darwin10 %s -o - | FileCheck %s --check-prefixes=NOOPTARRAY +// RUN: %clang_cc1 -fsanitize=array-bounds -fsanitize-trap=array-bounds -fno-sanitize-merge -O3 -emit-llvm -triple x86_64-apple-darwin10 %s -o - | FileCheck %s --check-prefixes=NOOPTARRAY +// RUN: %clang_cc1 -fsanitize=array-bounds -fsanitize-trap=array-bounds -fsanitize-merge=array-bounds -O3 -emit-llvm -triple x86_64-apple-darwin10 %s -o - | not FileCheck %s --check-prefixes=NOOPTARRAY // // REQUIRES: x86-registered-target @@ -43,7 +51,7 @@ int f4(int i) { return b[i]; } -// Union flexible-array memebers are a C99 extension. All array members with a +// Union flexible-array members are a C99 extension. All array members with a // constant size should be considered FAMs. union U { int a[0]; int b[1]; int c[2]; }; @@ -72,13 +80,17 @@ int f7(union U *u, int i) { char B[10]; char B2[10]; // CHECK-LABEL: @f8 +// Check the label to prevent spuriously matching ubsantraps from other +// functions. +// NOOPTLOCAL-LABEL: @f8 +// NOOPTARRAY-LABEL: @f8 void f8(int i, int k) { - // NOOPTLOCAL: call void @llvm.ubsantrap(i8 3) - // NOOPTARRAY: call void @llvm.ubsantrap(i8 18) + // NOOPTLOCAL: call void @llvm.ubsantrap(i8 3) #[[ATTR1:[0-9]+]] + // NOOPTARRAY: call void @llvm.ubsantrap(i8 18) #[[ATTR2:[0-9]+]] B[i] = '\0'; - // NOOPTLOCAL: call void @llvm.ubsantrap(i8 5) - // NOOPTARRAY: call void @llvm.ubsantrap(i8 18) + // NOOPTLOCAL: call void @llvm.ubsantrap(i8 5) #[[ATTR1:[0-9]+]] + // NOOPTARRAY: call void @llvm.ubsantrap(i8 18) #[[ATTR2:[0-9]+]] B2[k] = '\0'; } @@ -90,3 +102,5 @@ struct S { struct S *f9(int i) { return &s[i]; } +// NOOPTLOCAL: attributes #[[ATTR1]] = { nomerge noreturn nounwind } +// NOOPTARRAY: attributes #[[ATTR2]] = { nomerge noreturn nounwind } diff --git a/clang/test/CodeGen/sanitize-type-globals.cpp b/clang/test/CodeGen/sanitize-type-globals.cpp new file mode 100644 index 0000000000000..7cb8de8b238cc --- /dev/null +++ b/clang/test/CodeGen/sanitize-type-globals.cpp @@ -0,0 +1,58 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --check-globals all --filter-out "attributes" --filter-out "attributes #" --version 5 +// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -o - %s -fsanitize=type | FileCheck -check-prefix=CHECK %s + +//. +// CHECK: @x = global %struct.CompleteS zeroinitializer, align 8 +// CHECK: @y = external global %struct.S, align 1 +// CHECK: @__tysan_shadow_memory_address = external global i64 +// CHECK: @__tysan_app_memory_mask = external global i64 +// CHECK: @__tysan_v1_Simple_20C_2b_2b_20TBAA = linkonce_odr constant { i64, i64, [16 x i8] } { i64 2, i64 0, [16 x i8] c"Simple C++ TBAA\00" }, comdat +// CHECK: @__tysan_v1_omnipotent_20char = linkonce_odr constant { i64, i64, ptr, i64, [16 x i8] } { i64 2, i64 1, ptr @__tysan_v1_Simple_20C_2b_2b_20TBAA, i64 0, [16 x i8] c"omnipotent char\00" }, comdat +// CHECK: @__tysan_v1_int = linkonce_odr constant { i64, i64, ptr, i64, [4 x i8] } { i64 2, i64 1, ptr @__tysan_v1_omnipotent_20char, i64 0, [4 x i8] c"int\00" }, comdat +// CHECK: @__tysan_v1_any_20pointer = linkonce_odr constant { i64, i64, ptr, i64, [12 x i8] } { i64 2, i64 1, ptr @__tysan_v1_omnipotent_20char, i64 0, [12 x i8] c"any pointer\00" }, comdat +// CHECK: @__tysan_v1_p1_20int = linkonce_odr constant { i64, i64, ptr, i64, [7 x i8] } { i64 2, i64 1, ptr @__tysan_v1_any_20pointer, i64 0, [7 x i8] c"p1 int\00" }, comdat +// CHECK: @__tysan_v1___ZTS9CompleteS = linkonce_odr constant { i64, i64, ptr, i64, ptr, i64, [15 x i8] } { i64 2, i64 2, ptr @__tysan_v1_int, i64 0, ptr @__tysan_v1_p1_20int, i64 8, [15 x i8] c"_ZTS9CompleteS\00" }, comdat +// CHECK: @llvm.used = appending global [7 x ptr] [ptr @tysan.module_ctor, ptr @__tysan_v1_Simple_20C_2b_2b_20TBAA, ptr @__tysan_v1_omnipotent_20char, ptr @__tysan_v1_int, ptr @__tysan_v1_any_20pointer, ptr @__tysan_v1_p1_20int, ptr @__tysan_v1___ZTS9CompleteS], section "llvm.metadata" +// CHECK: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 0, ptr @tysan.module_ctor, ptr null }] +//. +struct CompleteS { + int x; + int *ptr; +}; + +void f(CompleteS *); +CompleteS x; +// CHECK-LABEL: define dso_local void @_Z1gv( +// CHECK-SAME: ) #[[ATTR0:[0-9]+]] { +// CHECK: [[ENTRY:.*:]] +// CHECK: call void @_Z1fP9CompleteS(ptr noundef @x) +// CHECK: ret void +// +void g() { f(&x); } + +typedef struct S IncompleteS; +void f(IncompleteS *); +extern IncompleteS y; +// CHECK-LABEL: define dso_local void @_Z1hv( +// CHECK-SAME: ) #[[ATTR0]] { +// CHECK: [[ENTRY:.*:]] +// CHECK: call void @_Z1fP1S(ptr noundef @y) +// CHECK: ret void +// +void h() { f(&y); } +//. +// CHECK: attributes #[[ATTR0]] = { mustprogress noinline nounwind optnone sanitize_type "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+cx8,+mmx,+sse,+sse2,+x87" } +// CHECK: attributes #[[ATTR1:[0-9]+]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+cx8,+mmx,+sse,+sse2,+x87" } +// CHECK: attributes #[[ATTR2:[0-9]+]] = { nounwind "target-features"="+cx8,+mmx,+sse,+sse2,+x87" } +// CHECK: attributes #[[ATTR3:[0-9]+]] = { nounwind } +//. +// CHECK: [[META0:![0-9]+]] = !{ptr @x, [[META1:![0-9]+]]} +// CHECK: [[META1]] = !{!"_ZTS9CompleteS", [[META2:![0-9]+]], i64 0, [[META5:![0-9]+]], i64 8} +// CHECK: [[META2]] = !{!"int", [[META3:![0-9]+]], i64 0} +// CHECK: [[META3]] = !{!"omnipotent char", [[META4:![0-9]+]], i64 0} +// CHECK: [[META4]] = !{!"Simple C++ TBAA"} +// CHECK: [[META5]] = !{!"p1 int", [[META6:![0-9]+]], i64 0} +// CHECK: [[META6]] = !{!"any pointer", [[META3]], i64 0} +// CHECK: [[META7:![0-9]+]] = !{i32 1, !"wchar_size", i32 4} +// CHECK: [[META8:![0-9]+]] = !{!"{{.*}}clang version {{.*}}"} +//. diff --git a/clang/test/CodeGen/ubsan-trap-merge.c b/clang/test/CodeGen/ubsan-trap-merge.c index f211150a09cb6..486aa55f5b811 100644 --- a/clang/test/CodeGen/ubsan-trap-merge.c +++ b/clang/test/CodeGen/ubsan-trap-merge.c @@ -10,10 +10,6 @@ // RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -fsanitize=signed-integer-overflow -O3 %s -o - | FileCheck %s --check-prefixes=HANDLER-NOMERGE // RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -fsanitize=signed-integer-overflow -O3 %s -o - -fsanitize-minimal-runtime | FileCheck %s --check-prefixes=MINRT-NOMERGE // -// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -fsanitize=signed-integer-overflow -O3 -mllvm -ubsan-unique-traps %s -o - -fsanitize-trap=signed-integer-overflow | FileCheck %s --check-prefixes=TRAP-NOMERGE -// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -fsanitize=signed-integer-overflow -O3 -mllvm -ubsan-unique-traps %s -o - | FileCheck %s --check-prefixes=HANDLER-NOMERGE -// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -fsanitize=signed-integer-overflow -O3 -mllvm -ubsan-unique-traps %s -o - -fsanitize-minimal-runtime | FileCheck %s --check-prefixes=MINRT-NOMERGE -// // RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -fsanitize=signed-integer-overflow -O3 -fno-sanitize-merge=signed-integer-overflow %s -o - -fsanitize-trap=signed-integer-overflow | FileCheck %s --check-prefixes=TRAP-NOMERGE // RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -fsanitize=signed-integer-overflow -O3 -fno-sanitize-merge=signed-integer-overflow %s -o - | FileCheck %s --check-prefixes=HANDLER-NOMERGE // RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -fsanitize=signed-integer-overflow -O3 -fno-sanitize-merge=signed-integer-overflow %s -o - -fsanitize-minimal-runtime | FileCheck %s --check-prefixes=MINRT-NOMERGE diff --git a/clang/test/CodeGenCXX/fmv-namespace.cpp b/clang/test/CodeGenCXX/fmv-namespace.cpp index 1a76ee0356524..75f29e1c77975 100644 --- a/clang/test/CodeGenCXX/fmv-namespace.cpp +++ b/clang/test/CodeGenCXX/fmv-namespace.cpp @@ -28,34 +28,40 @@ __attribute((target_version("mops"))) int bar() { return 1; } // CHECK: @_ZN4Name3fooEv = weak_odr ifunc i32 (), ptr @_ZN4Name3fooEv.resolver // CHECK: @_ZN3Foo3barEv = weak_odr ifunc i32 (), ptr @_ZN3Foo3barEv.resolver //. -// CHECK-LABEL: define dso_local noundef i32 @_ZN4Name3fooEv._Msve( +// CHECK-LABEL: define dso_local noundef i32 @_ZN4Name3fooEv.default( // CHECK-SAME: ) #[[ATTR0:[0-9]+]] { // CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: ret i32 0 +// +// +// CHECK-LABEL: define dso_local noundef i32 @_ZN4Name3fooEv._Msve( +// CHECK-SAME: ) #[[ATTR1:[0-9]+]] { +// CHECK-NEXT: [[ENTRY:.*:]] // CHECK-NEXT: ret i32 1 // // // CHECK-LABEL: define dso_local noundef i32 @_Z3barv( -// CHECK-SAME: ) #[[ATTR1:[0-9]+]] { +// CHECK-SAME: ) #[[ATTR2:[0-9]+]] { // CHECK-NEXT: [[ENTRY:.*:]] // CHECK-NEXT: [[CALL:%.*]] = call noundef i32 @_ZN4Name3fooEv() // CHECK-NEXT: ret i32 [[CALL]] // // // CHECK-LABEL: define dso_local noundef i32 @_ZN9OtherName3fooEv._Msve( -// CHECK-SAME: ) #[[ATTR0]] { +// CHECK-SAME: ) #[[ATTR1]] { // CHECK-NEXT: [[ENTRY:.*:]] // CHECK-NEXT: ret i32 2 // // // CHECK-LABEL: define dso_local noundef i32 @_Z3bazv( -// CHECK-SAME: ) #[[ATTR1]] { +// CHECK-SAME: ) #[[ATTR2]] { // CHECK-NEXT: [[ENTRY:.*:]] // CHECK-NEXT: [[CALL:%.*]] = call noundef i32 @_ZN9OtherName3fooEv() // CHECK-NEXT: ret i32 [[CALL]] // // // CHECK-LABEL: define dso_local noundef i32 @_ZN3Foo3barEv.default( -// CHECK-SAME: ) #[[ATTR3:[0-9]+]] { +// CHECK-SAME: ) #[[ATTR0]] { // CHECK-NEXT: [[ENTRY:.*:]] // CHECK-NEXT: ret i32 0 // @@ -66,12 +72,6 @@ __attribute((target_version("mops"))) int bar() { return 1; } // CHECK-NEXT: ret i32 1 // // -// CHECK-LABEL: define dso_local noundef i32 @_ZN4Name3fooEv.default( -// CHECK-SAME: ) #[[ATTR3]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: ret i32 0 -// -// // CHECK-LABEL: define weak_odr ptr @_ZN4Name3fooEv.resolver() comdat { // CHECK-NEXT: [[RESOLVER_ENTRY:.*:]] // CHECK-NEXT: call void @__init_cpu_features_resolver() diff --git a/clang/test/CodeGenHLSL/builtins/ByteAddressBuffers-constructors.hlsl b/clang/test/CodeGenHLSL/builtins/ByteAddressBuffers-constructors.hlsl index 45e135427ba9c..7507e741a9c9b 100644 --- a/clang/test/CodeGenHLSL/builtins/ByteAddressBuffers-constructors.hlsl +++ b/clang/test/CodeGenHLSL/builtins/ByteAddressBuffers-constructors.hlsl @@ -21,9 +21,9 @@ RasterizerOrderedByteAddressBuffer Buffer2: register(u3, space4); // CHECK: define internal void @_init_resource_bindings() { // CHECK-NEXT: entry: -// CHECK-DXIL-NEXT: %Buffer0_h = call target("dx.RawBuffer", i8, 0, 0) @llvm.dx.handle.fromBinding.tdx.RawBuffer_i8_0_0t(i32 0, i32 0, i32 1, i32 0, i1 false) +// CHECK-DXIL-NEXT: %Buffer0_h = call target("dx.RawBuffer", i8, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i8_0_0t(i32 0, i32 0, i32 1, i32 0, i1 false) // CHECK-DXIL-NEXT: store target("dx.RawBuffer", i8, 0, 0) %Buffer0_h, ptr @Buffer0, align 4 -// CHECK-DXIL-NEXT: %Buffer1_h = call target("dx.RawBuffer", i8, 1, 0) @llvm.dx.handle.fromBinding.tdx.RawBuffer_i8_1_0t(i32 2, i32 1, i32 1, i32 0, i1 false) +// CHECK-DXIL-NEXT: %Buffer1_h = call target("dx.RawBuffer", i8, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i8_1_0t(i32 2, i32 1, i32 1, i32 0, i1 false) // CHECK-DXIL-NEXT: store target("dx.RawBuffer", i8, 1, 0) %Buffer1_h, ptr @Buffer1, align 4 -// CHECK-DXIL-NEXT: %Buffer2_h = call target("dx.RawBuffer", i8, 1, 1) @llvm.dx.handle.fromBinding.tdx.RawBuffer_i8_1_1t(i32 4, i32 3, i32 1, i32 0, i1 false) +// CHECK-DXIL-NEXT: %Buffer2_h = call target("dx.RawBuffer", i8, 1, 1) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i8_1_1t(i32 4, i32 3, i32 1, i32 0, i1 false) // CHECK-DXIL-NEXT: store target("dx.RawBuffer", i8, 1, 1) %Buffer2_h, ptr @Buffer2, align 4 diff --git a/clang/test/CodeGenHLSL/builtins/RWBuffer-constructor-opt.hlsl b/clang/test/CodeGenHLSL/builtins/RWBuffer-constructor-opt.hlsl index d834a22917c1f..237b97394024c 100644 --- a/clang/test/CodeGenHLSL/builtins/RWBuffer-constructor-opt.hlsl +++ b/clang/test/CodeGenHLSL/builtins/RWBuffer-constructor-opt.hlsl @@ -11,10 +11,10 @@ void main() { // CHECK: define void @main() // CHECK-NEXT: entry: -// CHECK-SPIRV-NEXT: %Buf_h.i = tail call target("spirv.Image", float, 5, 2, 0, 0, 2, 0) @llvm.spv.handle.fromBinding.tspirv.Image_f32_5_2_0_0_2_0t(i32 3, i32 5, i32 1, i32 0, i1 false) +// CHECK-SPIRV-NEXT: %Buf_h.i = tail call target("spirv.Image", float, 5, 2, 0, 0, 2, 0) @llvm.spv.resource.handlefrombinding.tspirv.Image_f32_5_2_0_0_2_0t(i32 3, i32 5, i32 1, i32 0, i1 false) // CHECK-SPIRV-NEXT: store target("spirv.Image", float, 5, 2, 0, 0, 2, 0) %Buf_h.i, ptr @Buf, align 8 -// CHECK-DXIL-NEXT: %Buf_h.i = tail call target("dx.TypedBuffer", float, 1, 0, 0) @llvm.dx.handle.fromBinding.tdx.TypedBuffer_f32_1_0_0t(i32 3, i32 5, i32 1, i32 0, i1 false) +// CHECK-DXIL-NEXT: %Buf_h.i = tail call target("dx.TypedBuffer", float, 1, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0_0t(i32 3, i32 5, i32 1, i32 0, i1 false) // CHECK-DXIL-NEXT: store target("dx.TypedBuffer", float, 1, 0, 0) %Buf_h.i, ptr @Buf, align 4 // CHECK-NEXT: ret void diff --git a/clang/test/CodeGenHLSL/builtins/RWBuffer-constructor.hlsl b/clang/test/CodeGenHLSL/builtins/RWBuffer-constructor.hlsl index c2db56e2b2bdd..e4226abf71b8e 100644 --- a/clang/test/CodeGenHLSL/builtins/RWBuffer-constructor.hlsl +++ b/clang/test/CodeGenHLSL/builtins/RWBuffer-constructor.hlsl @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-DXIL -// FIXME: SPIR-V codegen of llvm.spv.handle.fromBinding is not yet implemented +// FIXME: SPIR-V codegen of llvm.spv.resource.handlefrombinding is not yet implemented // RUN-DISABLED: %clang_cc1 -triple spirv-vulkan-library -x hlsl -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-SPIRV // NOTE: SPIRV codegen for resource types is not yet implemented @@ -19,7 +19,7 @@ RWBuffer Buf : register(u5, space3); // CHECK: define internal void @_init_resource_bindings() { // CHECK-NEXT: entry: -// CHECK-DXIL-NEXT: %Buf_h = call target("dx.TypedBuffer", float, 1, 0, 0) @llvm.dx.handle.fromBinding.tdx.TypedBuffer_f32_1_0_0t(i32 3, i32 5, i32 1, i32 0, i1 false) +// CHECK-DXIL-NEXT: %Buf_h = call target("dx.TypedBuffer", float, 1, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0_0t(i32 3, i32 5, i32 1, i32 0, i1 false) // CHECK-DXIL-NEXT: store target("dx.TypedBuffer", float, 1, 0, 0) %Buf_h, ptr @Buf, align 4 -// CHECK-SPIRV-NEXT: %Buf_h = call target("dx.TypedBuffer", float, 1, 0, 0) @llvm.spv.handle.fromBinding.tdx.TypedBuffer_f32_1_0_0t(i32 3, i32 5, i32 1, i32 0, i1 false) +// CHECK-SPIRV-NEXT: %Buf_h = call target("dx.TypedBuffer", float, 1, 0, 0) @llvm.spv.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0_0t(i32 3, i32 5, i32 1, i32 0, i1 false) // CHECK-SPIRV-NEXT: store target("dx.TypedBuffer", float, 1, 0, 0) %Buf_h, ptr @Buf, align 4 diff --git a/clang/test/CodeGenHLSL/builtins/StructuredBuffers-constructors.hlsl b/clang/test/CodeGenHLSL/builtins/StructuredBuffers-constructors.hlsl index d84e92242ffb4..16f4f80231dae 100644 --- a/clang/test/CodeGenHLSL/builtins/StructuredBuffers-constructors.hlsl +++ b/clang/test/CodeGenHLSL/builtins/StructuredBuffers-constructors.hlsl @@ -37,24 +37,24 @@ RasterizerOrderedStructuredBuffer Buf5 : register(u1, space2); // CHECK: define internal void @_init_resource_bindings() { // CHECK-NEXT: entry: -// CHECK-DXIL-NEXT: %Buf_h = call target("dx.RawBuffer", float, 0, 0) @llvm.dx.handle.fromBinding.tdx.RawBuffer_f32_0_0t(i32 0, i32 10, i32 1, i32 0, i1 false) +// CHECK-DXIL-NEXT: %Buf_h = call target("dx.RawBuffer", float, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_f32_0_0t(i32 0, i32 10, i32 1, i32 0, i1 false) // CHECK-DXIL-NEXT: store target("dx.RawBuffer", float, 0, 0) %Buf_h, ptr @Buf, align 4 -// CHECK-DXIL-NEXT: %Buf2_h = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.handle.fromBinding.tdx.RawBuffer_f32_1_0t(i32 1, i32 5, i32 1, i32 0, i1 false) +// CHECK-DXIL-NEXT: %Buf2_h = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_f32_1_0t(i32 1, i32 5, i32 1, i32 0, i1 false) // CHECK-DXIL-NEXT: store target("dx.RawBuffer", float, 1, 0) %Buf2_h, ptr @Buf2, align 4 -// CHECK-DXIL-NEXT: %Buf3_h = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.handle.fromBinding.tdx.RawBuffer_f32_1_0t(i32 0, i32 3, i32 1, i32 0, i1 false) +// CHECK-DXIL-NEXT: %Buf3_h = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_f32_1_0t(i32 0, i32 3, i32 1, i32 0, i1 false) // CHECK-DXIL-NEXT: store target("dx.RawBuffer", float, 1, 0) %Buf3_h, ptr @Buf3, align 4 -// CHECK-DXIL-NEXT: %Buf4_h = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.handle.fromBinding.tdx.RawBuffer_f32_1_0t(i32 0, i32 4, i32 1, i32 0, i1 false) +// CHECK-DXIL-NEXT: %Buf4_h = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_f32_1_0t(i32 0, i32 4, i32 1, i32 0, i1 false) // CHECK-DXIL-NEXT: store target("dx.RawBuffer", float, 1, 0) %Buf4_h, ptr @Buf4, align 4 -// CHECK-DXIL-NEXT: %Buf5_h = call target("dx.RawBuffer", float, 1, 1) @llvm.dx.handle.fromBinding.tdx.RawBuffer_f32_1_1t(i32 2, i32 1, i32 1, i32 0, i1 false) +// CHECK-DXIL-NEXT: %Buf5_h = call target("dx.RawBuffer", float, 1, 1) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_f32_1_1t(i32 2, i32 1, i32 1, i32 0, i1 false) // CHECK-DXIL-NEXT: store target("dx.RawBuffer", float, 1, 1) %Buf5_h, ptr @Buf5, align 4 -// CHECK-SPIRV-NEXT: %Buf_h = call target("dx.RawBuffer", float, 0, 0) @llvm.spv.handle.fromBinding.tdx.RawBuffer_f32_0_0t(i32 0, i32 10, i32 1, i32 0, i1 false) +// CHECK-SPIRV-NEXT: %Buf_h = call target("dx.RawBuffer", float, 0, 0) @llvm.spv.resource.handlefrombinding.tdx.RawBuffer_f32_0_0t(i32 0, i32 10, i32 1, i32 0, i1 false) // CHECK-SPIRV-NEXT: store target("dx.RawBuffer", float, 0, 0) %Buf_h, ptr @Buf", align 4 -// CHECK-SPIRV-NEXT: %Buf2_h = call target("dx.RawBuffer", float, 1, 0) @llvm.spv.handle.fromBinding.tdx.RawBuffer_f32_1_0t(i32 1, i32 5, i32 1, i32 0, i1 false) +// CHECK-SPIRV-NEXT: %Buf2_h = call target("dx.RawBuffer", float, 1, 0) @llvm.spv.resource.handlefrombinding.tdx.RawBuffer_f32_1_0t(i32 1, i32 5, i32 1, i32 0, i1 false) // CHECK-SPIRV-NEXT: store target("dx.RawBuffer", float, 1, 0) %Buf2_h, ptr @Buf2", align 4 -// CHECK-SPIRV-NEXT: %Buf3_h = call target("dx.RawBuffer", float, 0, 0) @llvm.spv.handle.fromBinding.tdx.RawBuffer_f32_1_0t(i32 0, i32 3, i32 1, i32 0, i1 false) +// CHECK-SPIRV-NEXT: %Buf3_h = call target("dx.RawBuffer", float, 0, 0) @llvm.spv.resource.handlefrombinding.tdx.RawBuffer_f32_1_0t(i32 0, i32 3, i32 1, i32 0, i1 false) // CHECK-SPIRV-NEXT: store target("dx.RawBuffer", float, 0, 0) %Buf3_h, ptr @Buf3, align 4 -// CHECK-SPIRV-NEXT: %Buf4_h = call target("dx.RawBuffer", float, 1, 0) @llvm.spv.handle.fromBinding.tdx.RawBuffer_f32_1_0t(i32 0, i32 4, i32 1, i32 0, i1 false) +// CHECK-SPIRV-NEXT: %Buf4_h = call target("dx.RawBuffer", float, 1, 0) @llvm.spv.resource.handlefrombinding.tdx.RawBuffer_f32_1_0t(i32 0, i32 4, i32 1, i32 0, i1 false) // CHECK-SPIRV-NEXT: store target("dx.RawBuffer", float, 1, 0) %Buf4_h, ptr @Buf4, align 4 -// CHECK-SPIRV-NEXT: %Buf5_h = call target("dx.RawBuffer", float, 1, 1) @llvm.spv.handle.fromBinding.tdx.RawBuffer_f32_1_1t(i32 2, i32 1, i32 1, i32 0, i1 false) +// CHECK-SPIRV-NEXT: %Buf5_h = call target("dx.RawBuffer", float, 1, 1) @llvm.spv.resource.handlefrombinding.tdx.RawBuffer_f32_1_1t(i32 2, i32 1, i32 1, i32 0, i1 false) // CHECK-SPIRV-NEXT: store target("dx.RawBuffer", float, 1, 1) %Buf5_h, ptr @Buf5, align 4 diff --git a/clang/test/CodeGenHLSL/builtins/StructuredBuffers-methods-lib.hlsl b/clang/test/CodeGenHLSL/builtins/StructuredBuffers-methods-lib.hlsl index 53abdc71bdd4b..5fc2d2ead564d 100644 --- a/clang/test/CodeGenHLSL/builtins/StructuredBuffers-methods-lib.hlsl +++ b/clang/test/CodeGenHLSL/builtins/StructuredBuffers-methods-lib.hlsl @@ -15,14 +15,14 @@ export int TestIncrementCounter() { } // CHECK: define noundef i32 @_Z20TestIncrementCounterv() -// CHECK-DXIL: %[[INDEX:.*]] = call i32 @llvm.dx.bufferUpdateCounter.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0) %{{[0-9]+}}, i8 1) +// CHECK-DXIL: %[[INDEX:.*]] = call i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0) %{{[0-9]+}}, i8 1) // CHECK-DXIL: ret i32 %[[INDEX]] export int TestDecrementCounter() { return RWSB2.DecrementCounter(); } // CHECK: define noundef i32 @_Z20TestDecrementCounterv() -// CHECK-DXIL: %[[INDEX:.*]] = call i32 @llvm.dx.bufferUpdateCounter.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0) %{{[0-9]+}}, i8 -1) +// CHECK-DXIL: %[[INDEX:.*]] = call i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0) %{{[0-9]+}}, i8 -1) // CHECK-DXIL: ret i32 %[[INDEX]] export void TestAppend(float value) { @@ -31,7 +31,7 @@ export void TestAppend(float value) { // CHECK: define void @_Z10TestAppendf(float noundef %value) // CHECK-DXIL: %[[VALUE:.*]] = load float, ptr %value.addr, align 4 -// CHECK-DXIL: %[[INDEX:.*]] = call i32 @llvm.dx.bufferUpdateCounter.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0) %{{[0-9]+}}, i8 1) +// CHECK-DXIL: %[[INDEX:.*]] = call i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0) %{{[0-9]+}}, i8 1) // CHECK-DXIL: %[[RESPTR:.*]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0) %{{[0-9]+}}, i32 %[[INDEX]]) // CHECK-DXIL: store float %[[VALUE]], ptr %[[RESPTR]], align 4 @@ -40,10 +40,10 @@ export float TestConsume() { } // CHECK: define noundef float @_Z11TestConsumev() -// CHECK-DXIL: %[[INDEX:.*]] = call i32 @llvm.dx.bufferUpdateCounter.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0) %1, i8 -1) +// CHECK-DXIL: %[[INDEX:.*]] = call i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0) %1, i8 -1) // CHECK-DXIL: %[[RESPTR:.*]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0) %0, i32 %[[INDEX]]) // CHECK-DXIL: %[[VALUE:.*]] = load float, ptr %[[RESPTR]], align 4 // CHECK-DXIL: ret float %[[VALUE]] -// CHECK: declare i32 @llvm.dx.bufferUpdateCounter.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0), i8) +// CHECK: declare i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0), i8) // CHECK: declare ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0), i32) diff --git a/clang/test/CodeGenHLSL/builtins/StructuredBuffers-methods-ps.hlsl b/clang/test/CodeGenHLSL/builtins/StructuredBuffers-methods-ps.hlsl index f6959b5cefb7c..f7c091084d3ed 100644 --- a/clang/test/CodeGenHLSL/builtins/StructuredBuffers-methods-ps.hlsl +++ b/clang/test/CodeGenHLSL/builtins/StructuredBuffers-methods-ps.hlsl @@ -10,19 +10,19 @@ RasterizerOrderedStructuredBuffer ROSB1, ROSB2; export void TestIncrementCounter() { // CHECK: define void @_Z20TestIncrementCounterv() -// CHECK-DXIL: call i32 @llvm.dx.bufferUpdateCounter.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0) %{{[0-9]+}}, i8 1) -// CHECK-DXIL: call i32 @llvm.dx.bufferUpdateCounter.tdx.RawBuffer_f32_1_1t(target("dx.RawBuffer", float, 1, 1) %{{[0-9]+}}, i8 1) +// CHECK-DXIL: call i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0) %{{[0-9]+}}, i8 1) +// CHECK-DXIL: call i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_1t(target("dx.RawBuffer", float, 1, 1) %{{[0-9]+}}, i8 1) RWSB1.IncrementCounter(); ROSB1.IncrementCounter(); } export void TestDecrementCounter() { // CHECK: define void @_Z20TestDecrementCounterv() -// CHECK-DXIL: call i32 @llvm.dx.bufferUpdateCounter.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0) %{{[0-9]+}}, i8 -1) -// CHECK-DXIL: call i32 @llvm.dx.bufferUpdateCounter.tdx.RawBuffer_f32_1_1t(target("dx.RawBuffer", float, 1, 1) %{{[0-9]+}}, i8 -1) +// CHECK-DXIL: call i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0) %{{[0-9]+}}, i8 -1) +// CHECK-DXIL: call i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_1t(target("dx.RawBuffer", float, 1, 1) %{{[0-9]+}}, i8 -1) RWSB2.DecrementCounter(); ROSB2.DecrementCounter(); } -// CHECK: declare i32 @llvm.dx.bufferUpdateCounter.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0), i8) -// CHECK: declare i32 @llvm.dx.bufferUpdateCounter.tdx.RawBuffer_f32_1_1t(target("dx.RawBuffer", float, 1, 1), i8) +// CHECK: declare i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0), i8) +// CHECK: declare i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_1t(target("dx.RawBuffer", float, 1, 1), i8) diff --git a/clang/test/CodeGenHLSL/resource-bindings.hlsl b/clang/test/CodeGenHLSL/resource-bindings.hlsl index d4e6308210653..4049a87a8ab71 100644 --- a/clang/test/CodeGenHLSL/resource-bindings.hlsl +++ b/clang/test/CodeGenHLSL/resource-bindings.hlsl @@ -2,18 +2,18 @@ // CHECK: define internal void @_init_resource_bindings() { -// CHECK: %U0S0_h = call target("dx.TypedBuffer", <4 x float>, 1, 0, 0) @llvm.dx.handle.fromBinding.tdx.TypedBuffer_v4f32_1_0_0t(i32 0, i32 0, i32 1, i32 0, i1 false) +// CHECK: %U0S0_h = call target("dx.TypedBuffer", <4 x float>, 1, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_v4f32_1_0_0t(i32 0, i32 0, i32 1, i32 0, i1 false) RWBuffer U0S0 : register(u0); -// CHECK: %U5S3_h = call target("dx.TypedBuffer", float, 1, 0, 0) @llvm.dx.handle.fromBinding.tdx.TypedBuffer_f32_1_0_0t(i32 3, i32 5, i32 1, i32 0, i1 false) +// CHECK: %U5S3_h = call target("dx.TypedBuffer", float, 1, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0_0t(i32 3, i32 5, i32 1, i32 0, i1 false) RWBuffer U5S3 : register(u5, space3); -// CHECK: %T2S2_h = call target("dx.RawBuffer", i32, 0, 0) @llvm.dx.handle.fromBinding.tdx.RawBuffer_i32_0_0t(i32 2, i32 2, i32 1, i32 0, i1 false) +// CHECK: %T2S2_h = call target("dx.RawBuffer", i32, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i32_0_0t(i32 2, i32 2, i32 1, i32 0, i1 false) StructuredBuffer T2S2 : register(t2, space2); struct S { float4 f; int i; }; -// CHECK: %T3S0_h = call target("dx.RawBuffer", %struct.S, 0, 0) @llvm.dx.handle.fromBinding.tdx.RawBuffer_s_struct.Ss_0_0t(i32 0, i32 3, i32 1, i32 0, i1 false) +// CHECK: %T3S0_h = call target("dx.RawBuffer", %struct.S, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_s_struct.Ss_0_0t(i32 0, i32 3, i32 1, i32 0, i1 false) StructuredBuffer T3S0 : register(t3); diff --git a/clang/test/Driver/ps5-linker.c b/clang/test/Driver/ps5-linker.c index 62aa3a40e455a..53f89a914f4fa 100644 --- a/clang/test/Driver/ps5-linker.c +++ b/clang/test/Driver/ps5-linker.c @@ -172,29 +172,27 @@ // CHECK-SYSROOT: {{ld(\.exe)?}}" // CHECK-SYSROOT-SAME: "--sysroot=mysdk" -// Test that "." is always added to library search paths. This is long-standing -// behavior, unique to PlayStation toolchains. - -// RUN: %clang --target=x64_64-sie-ps5 %s -### 2>&1 | FileCheck --check-prefixes=CHECK-LDOT %s - -// CHECK-LDOT: {{ld(\.exe)?}}" -// CHECK-LDOT-SAME: "-L." - -// Test that /target/lib is added to library search paths, if it -// exists and no --sysroot is specified. Also confirm that CRT objects are -// found there. +// Test implicit library search paths are supplied to the linker, after any +// search paths specified by the user. /target/lib is implicitly +// added if it exists and no --sysroot is specified. CRT objects are found +// there. "." is always implicitly added to library search paths. This is +// long-standing behavior, unique to PlayStation toolchains. // RUN: rm -rf %t.dir && mkdir %t.dir -// RUN: env SCE_PROSPERO_SDK_DIR=%t.dir %clang --target=x64_64-sie-ps5 %s -### 2>&1 | FileCheck --check-prefixes=CHECK-NO-TARGETLIB %s -// RUN: env SCE_PROSPERO_SDK_DIR=%t.dir %clang --target=x64_64-sie-ps5 %s -### --sysroot=%t.dir 2>&1 | FileCheck --check-prefixes=CHECK-NO-TARGETLIB %s +// RUN: env SCE_PROSPERO_SDK_DIR=%t.dir %clang --target=x64_64-sie-ps5 %s -### -Luser 2>&1 | FileCheck --check-prefixes=CHECK-NO-TARGETLIB %s +// RUN: env SCE_PROSPERO_SDK_DIR=%t.dir %clang --target=x64_64-sie-ps5 %s -### -Luser --sysroot=%t.dir 2>&1 | FileCheck --check-prefixes=CHECK-NO-TARGETLIB %s // CHECK-NO-TARGETLIB: {{ld(\.exe)?}}" +// CHECK-NO-TARGETLIB-SAME: "-Luser" // CHECK-NO-TARGETLIB-NOT: "-L{{.*[/\\]}}target/lib" +// CHECK-NO-TARGETLIB-SAME: "-L." // RUN: mkdir -p %t.dir/target/lib // RUN: touch %t.dir/target/lib/crti.o -// RUN: env SCE_PROSPERO_SDK_DIR=%t.dir %clang --target=x64_64-sie-ps5 %s -### 2>&1 | FileCheck --check-prefixes=CHECK-TARGETLIB %s +// RUN: env SCE_PROSPERO_SDK_DIR=%t.dir %clang --target=x64_64-sie-ps5 %s -### -Luser 2>&1 | FileCheck --check-prefixes=CHECK-TARGETLIB %s // CHECK-TARGETLIB: {{ld(\.exe)?}}" +// CHECK-TARGETLIB-SAME: "-Luser" // CHECK-TARGETLIB-SAME: "-L{{.*[/\\]}}target/lib" +// CHECK-TARGETLIB-SAME: "-L." // CHECK-TARGETLIB-SAME: "{{.*[/\\]}}target{{/|\\\\}}lib{{/|\\\\}}crti.o" diff --git a/clang/test/Driver/sanitizer-ld.c b/clang/test/Driver/sanitizer-ld.c index 60d60a6047b0f..8347f9c45935d 100644 --- a/clang/test/Driver/sanitizer-ld.c +++ b/clang/test/Driver/sanitizer-ld.c @@ -132,18 +132,78 @@ // RUN: -resource-dir=%S/Inputs/empty_resource_dir \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-ASAN-LINUX-CXX %s -// + +// RUN: %clangxx -### %s 2>&1 \ +// RUN: --target=i386-unknown-linux -fuse-ld=ld -stdlib=platform -fsanitize=address \ +// RUN: -resource-dir=%S/Inputs/empty_resource_dir \ +// RUN: --sysroot=%S/Inputs/basic_linux_tree \ +// RUN: -fsanitize-link-c++-runtime \ +// RUN: | FileCheck --check-prefix=CHECK-ASAN-LINUX-CXX %s + // CHECK-ASAN-LINUX-CXX: "{{(.*[^-.0-9A-Z_a-z])?}}ld{{(.exe)?}}" -// CHECK-ASAN-LINUX-CXX-NOT: "-lc" -// CHECK-ASAN-LINUX-CXX: "--whole-archive" "{{.*}}libclang_rt.asan.a" "--no-whole-archive" -// CHECK-ASAN-LINUX-CXX: "--whole-archive" "{{.*}}libclang_rt.asan_cxx.a" "--no-whole-archive" +// CHECK-ASAN-LINUX-CXX-SAME: "--whole-archive" "{{.*}}libclang_rt.asan.a" "--no-whole-archive" +// CHECK-ASAN-LINUX-CXX-SAME: "--whole-archive" "{{.*}}libclang_rt.asan_cxx.a" "--no-whole-archive" // CHECK-ASAN-LINUX-CXX-NOT: "--dynamic-list" -// CHECK-ASAN-LINUX-CXX: "--export-dynamic" -// CHECK-ASAN-LINUX-CXX: stdc++ -// CHECK-ASAN-LINUX-CXX: "-lpthread" -// CHECK-ASAN-LINUX-CXX: "-lrt" -// CHECK-ASAN-LINUX-CXX: "-ldl" -// CHECK-ASAN-LINUX-CXX: "-lresolv" +// CHECK-ASAN-LINUX-CXX-SAME: "--export-dynamic" +// CHECK-ASAN-LINUX-CXX-SAME: "-lstdc++" +// CHECK-ASAN-LINUX-CXX-SAME: "-lpthread" +// CHECK-ASAN-LINUX-CXX-SAME: "-lrt" +// CHECK-ASAN-LINUX-CXX-SAME: "-ldl" +// CHECK-ASAN-LINUX-CXX-SAME: "-lresolv" +// CHECK-ASAN-LINUX-CXX-SAME: "-lc" + +// RUN: %clang -### %s 2>&1 \ +// RUN: --target=i386-unknown-linux -fuse-ld=ld -stdlib=platform -fsanitize=address \ +// RUN: -resource-dir=%S/Inputs/empty_resource_dir \ +// RUN: --sysroot=%S/Inputs/basic_linux_tree \ +// RUN: -fno-sanitize-link-c++-runtime \ +// RUN: | FileCheck --check-prefix=CHECK-ASAN-LINUX-CNOCXX %s + +// CHECK-ASAN-LINUX-CNOCXX: "{{(.*[^-.0-9A-Z_a-z])?}}ld{{(.exe)?}}" +// CHECK-ASAN-LINUX-CNOCXX-SAME: "--whole-archive" "{{.*}}libclang_rt.asan.a" "--no-whole-archive" +// CHECK-ASAN-LINUX-CNOCXX-NOT: libclang_rt.asan_cxx +// CHECK-ASAN-LINUX-CNOCXX-SAME: "--export-dynamic" +// CHECK-ASAN-LINUX-CNOCXX-NOT: stdc++ +// CHECK-ASAN-LINUX-CNOCXX-SAME: "-lpthread" +// CHECK-ASAN-LINUX-CNOCXX-SAME: "-lrt" +// CHECK-ASAN-LINUX-CNOCXX-SAME: "-ldl" +// CHECK-ASAN-LINUX-CNOCXX-SAME: "-lresolv" +// CHECK-ASAN-LINUX-CNOCXX-SAME: "-lc" + +// RUN: %clangxx -### %s 2>&1 \ +// RUN: --target=i386-unknown-linux -fuse-ld=ld -stdlib=platform -fsanitize=address \ +// RUN: -resource-dir=%S/Inputs/empty_resource_dir \ +// RUN: --sysroot=%S/Inputs/basic_linux_tree \ +// RUN: -fno-sanitize-link-c++-runtime \ +// RUN: | FileCheck --check-prefix=CHECK-ASAN-LINUX-NOCXX %s + +// CHECK-ASAN-LINUX-NOCXX: "{{(.*[^-.0-9A-Z_a-z])?}}ld{{(.exe)?}}" +// CHECK-ASAN-LINUX-NOCXX-SAME: "--whole-archive" "{{.*}}libclang_rt.asan.a" "--no-whole-archive" +// CHECK-ASAN-LINUX-NOCXX-NOT: libclang_rt.asan_cxx +// CHECK-ASAN-LINUX-NOCXX-SAME: "--export-dynamic" +// CHECK-ASAN-LINUX-NOCXX-SAME: "-lstdc++" +// CHECK-ASAN-LINUX-NOCXX-SAME: "-lpthread" +// CHECK-ASAN-LINUX-NOCXX-SAME: "-lrt" +// CHECK-ASAN-LINUX-NOCXX-SAME: "-ldl" +// CHECK-ASAN-LINUX-NOCXX-SAME: "-lresolv" +// CHECK-ASAN-LINUX-NOCXX-SAME: "-lc" + +// RUN: %clangxx -### %s 2>&1 \ +// RUN: --target=i386-unknown-linux -fuse-ld=ld -stdlib=platform -fsanitize=address \ +// RUN: -resource-dir=%S/Inputs/empty_resource_dir \ +// RUN: --sysroot=%S/Inputs/basic_linux_tree \ +// RUN: -nostdlib++ \ +// RUN: | FileCheck --check-prefix=CHECK-ASAN-LINUX-NOSTDCXX %s + +// CHECK-ASAN-LINUX-NOSTDCXX: "{{(.*[^-.0-9A-Z_a-z])?}}ld{{(.exe)?}}" +// CHECK-ASAN-LINUX-NOSTDCXX-SAME: "--whole-archive" "{{.*}}libclang_rt.asan.a" "--no-whole-archive" +// CHECK-ASAN-LINUX-NOSTDCXX-SAME: libclang_rt.asan_cxx +// CHECK-ASAN-LINUX-NOSTDCXX-SAME: "--export-dynamic" +// CHECK-ASAN-LINUX-NOSTDCXX-SAME: "-lpthread" +// CHECK-ASAN-LINUX-NOSTDCXX-SAME: "-lrt" +// CHECK-ASAN-LINUX-NOSTDCXX-SAME: "-ldl" +// CHECK-ASAN-LINUX-NOSTDCXX-SAME: "-lresolv" +// CHECK-ASAN-LINUX-NOSTDCXX-SAME: "-lc" // RUN: %clang -### %s -o /dev/null -fsanitize=address \ // RUN: --target=i386-unknown-linux -fuse-ld=ld -stdlib=platform \ diff --git a/clang/test/ParserOpenACC/parse-clauses.c b/clang/test/ParserOpenACC/parse-clauses.c index 2e884c472c2ec..8a404a5a1987d 100644 --- a/clang/test/ParserOpenACC/parse-clauses.c +++ b/clang/test/ParserOpenACC/parse-clauses.c @@ -803,29 +803,21 @@ void IntExprParsing() { #pragma acc parallel num_workers(returns_int()) {} - // expected-error@+2{{expected '('}} - // expected-warning@+1{{OpenACC construct 'init' not yet implemented, pragma ignored}} + // expected-error@+1{{expected '('}} #pragma acc init device_num - // expected-error@+2{{expected expression}} - // expected-warning@+1{{OpenACC construct 'init' not yet implemented, pragma ignored}} + // expected-error@+1{{expected expression}} #pragma acc init device_num() - // expected-error@+2{{use of undeclared identifier 'invalid'}} - // expected-warning@+1{{OpenACC construct 'init' not yet implemented, pragma ignored}} + // expected-error@+1{{use of undeclared identifier 'invalid'}} #pragma acc init device_num(invalid) - // expected-error@+3{{expected ')'}} - // expected-note@+2{{to match this '('}} - // expected-warning@+1{{OpenACC construct 'init' not yet implemented, pragma ignored}} + // expected-error@+2{{expected ')'}} + // expected-note@+1{{to match this '('}} #pragma acc init device_num(5, 4) - // expected-warning@+2{{OpenACC clause 'device_num' not yet implemented, clause ignored}} - // expected-warning@+1{{OpenACC construct 'init' not yet implemented, pragma ignored}} #pragma acc init device_num(5) - // expected-warning@+2{{OpenACC clause 'device_num' not yet implemented, clause ignored}} - // expected-warning@+1{{OpenACC construct 'init' not yet implemented, pragma ignored}} #pragma acc init device_num(returns_int()) // expected-error@+2{{expected '('}} diff --git a/clang/test/ParserOpenACC/parse-constructs.c b/clang/test/ParserOpenACC/parse-constructs.c index 4a6c31cc9b0a9..878c38e8bedc7 100644 --- a/clang/test/ParserOpenACC/parse-constructs.c +++ b/clang/test/ParserOpenACC/parse-constructs.c @@ -141,12 +141,10 @@ void func() { // expected-warning@+1{{OpenACC construct 'declare' not yet implemented, pragma ignored}} #pragma acc declare clause list for(;;){} - // expected-error@+2{{invalid OpenACC clause 'clause'}} - // expected-warning@+1{{OpenACC construct 'init' not yet implemented, pragma ignored}} + // expected-error@+1{{invalid OpenACC clause 'clause'}} #pragma acc init clause list for(;;){} - // expected-error@+2{{invalid OpenACC clause 'clause'}} - // expected-warning@+1{{OpenACC construct 'shutdown' not yet implemented, pragma ignored}} + // expected-error@+1{{invalid OpenACC clause 'clause'}} #pragma acc shutdown clause list for(;;){} // expected-error@+2{{invalid OpenACC clause 'clause'}} diff --git a/clang/test/Sema/attr-target-version.c b/clang/test/Sema/attr-target-version.c index 5ea370aa980f1..096d2f003a004 100644 --- a/clang/test/Sema/attr-target-version.c +++ b/clang/test/Sema/attr-target-version.c @@ -102,13 +102,17 @@ int __attribute__((target_version("sha2"))) combine(void) { return 1; } // expected-error@+1 {{multiversioned function declaration has a different calling convention}} int __attribute__((aarch64_vector_pcs, target_version("sha3"))) combine(void) { return 2; } +// expected-error@+1 {{multiversioned function must have a prototype}} int __attribute__((target_version("fp+aes+rcpc"))) unspec_args() { return -1; } // expected-error@-1 {{multiversioned function must have a prototype}} +// expected-note@+1 {{function multiversioning caused by this declaration}} int __attribute__((target_version("default"))) unspec_args() { return 0; } int cargs() { return unspec_args(); } +// expected-error@+1 {{multiversioned function must have a prototype}} int unspec_args_implicit_default_first(); // expected-error@-1 {{multiversioned function must have a prototype}} // expected-note@+1 {{function multiversioning caused by this declaration}} int __attribute__((target_version("aes"))) unspec_args_implicit_default_first() { return -1; } +// expected-note@+1 {{function multiversioning caused by this declaration}} int __attribute__((target_version("default"))) unspec_args_implicit_default_first() { return 0; } diff --git a/clang/test/Sema/builtin-assume-aligned-downgrade.c b/clang/test/Sema/builtin-assume-aligned-downgrade.c new file mode 100644 index 0000000000000..93631e7364373 --- /dev/null +++ b/clang/test/Sema/builtin-assume-aligned-downgrade.c @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -fsyntax-only -Wno-int-conversion -triple x86_64-linux -verify %s + +// Check that the pointer->int conversion error is not downgradable for the +// pointer argument to __builtin_assume_aligned. + +int test(int *a, int b) { + a = (int *)__builtin_assume_aligned(b, 32); // expected-error {{non-pointer argument to '__builtin_assume_aligned' is not allowed}} + int *y = __builtin_assume_aligned(1, 1); // expected-error {{non-pointer argument to '__builtin_assume_aligned' is not allowed}} +} diff --git a/clang/test/Sema/builtin-assume-aligned.c b/clang/test/Sema/builtin-assume-aligned.c index 33e8557845152..57378a3426524 100644 --- a/clang/test/Sema/builtin-assume-aligned.c +++ b/clang/test/Sema/builtin-assume-aligned.c @@ -74,7 +74,7 @@ int test13(int *a) { } int test14(int *a, int b) { - a = (int *)__builtin_assume_aligned(b, 32); // expected-error {{incompatible integer to pointer conversion passing 'int' to parameter of type 'const void *}} + a = (int *)__builtin_assume_aligned(b, 32); // expected-error {{non-pointer argument to '__builtin_assume_aligned' is not allowed}} } int test15(int *b) { diff --git a/clang/test/Sema/tautological-pointer-comparison.c b/clang/test/Sema/tautological-pointer-comparison.c index 19cd20e5f7d21..1c5973b01a30d 100644 --- a/clang/test/Sema/tautological-pointer-comparison.c +++ b/clang/test/Sema/tautological-pointer-comparison.c @@ -1,4 +1,7 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -fwrapv -verify=fwrapv %s + +// fwrapv-no-diagnostics int add_ptr_idx_ult_ptr(const char *ptr, unsigned index) { return ptr + index < ptr; // expected-warning {{pointer comparison always evaluates to false}} diff --git a/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp b/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp index 45b4dc838f44e..4c19367bb7f3d 100644 --- a/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp +++ b/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp @@ -777,3 +777,32 @@ void test4() { } } // namespace LifetimeboundInterleave + +namespace GH120206 { +struct S { + std::string_view s; +}; + +struct [[gsl::Owner]] Q1 { + const S* get() const [[clang::lifetimebound]]; +}; +std::string_view test1(int c, std::string_view sv) { + std::string_view k = c > 1 ? Q1().get()->s : sv; + if (c == 1) + return c > 1 ? Q1().get()->s : sv; + Q1 q; + return c > 1 ? q.get()->s : sv; +} + +struct Q2 { + const S* get() const [[clang::lifetimebound]]; +}; +std::string_view test2(int c, std::string_view sv) { + std::string_view k = c > 1 ? Q2().get()->s : sv; + if (c == 1) + return c > 1 ? Q2().get()->s : sv; + Q2 q; + return c > 1 ? q.get()->s : sv; +} + +} // namespace GH120206 diff --git a/clang/test/SemaCXX/attr-target-version.cpp b/clang/test/SemaCXX/attr-target-version.cpp index 32fb97a9dc98d..974f88e77a3f7 100644 --- a/clang/test/SemaCXX/attr-target-version.cpp +++ b/clang/test/SemaCXX/attr-target-version.cpp @@ -57,7 +57,7 @@ int __attribute__((target_version("fp16fml"))) diff_type3(void) noexcept(false) int __attribute__((target_version("sve2-sha3"))) diff_type3(void) noexcept(true) { return 2; } template int __attribute__((target_version("default"))) temp(T) { return 1; } - +// expected-error@-1 {{attribute 'target_version' multiversioned functions do not yet support function templates}} template int __attribute__((target_version("simd"))) temp1(T) { return 1; } // expected-error@-1 {{attribute 'target_version' multiversioned functions do not yet support function templates}} @@ -68,6 +68,7 @@ int __attribute__((target_version("aes"))) extc(void) { return 1; } int __attribute__((target_version("lse"))) extc(void) { return 1; } auto __attribute__((target_version("default"))) ret1(void) { return 1; } +// expected-error@-1 {{attribute 'target_version' multiversioned functions do not yet support deduced return types}} auto __attribute__((target_version("dpb"))) ret2(void) { return 1; } // expected-error@-1 {{attribute 'target_version' multiversioned functions do not yet support deduced return types}} auto __attribute__((target_version("dpb2"))) ret3(void) -> int { return 1; } @@ -84,6 +85,7 @@ class Cls { // expected-error@-1 {{attribute 'target_version' multiversioned functions do not yet support deleted functions}} virtual void __attribute__((target_version("default"))) vfunc(); + // expected-error@-1 {{attribute 'target_version' multiversioned functions do not yet support virtual functions}} virtual void __attribute__((target_version("sm4"))) vfunc1(); // expected-error@-1 {{attribute 'target_version' multiversioned functions do not yet support virtual functions}} }; diff --git a/clang/test/SemaCXX/vector-bool.cpp b/clang/test/SemaCXX/vector-bool.cpp index e99d420e73fab..cd638056f348b 100644 --- a/clang/test/SemaCXX/vector-bool.cpp +++ b/clang/test/SemaCXX/vector-bool.cpp @@ -85,10 +85,10 @@ void foo(const bool& X); // Disallow element-wise access. bool* ElementRefs() { - eight_bools.y = false; // expected-error@88 {{illegal vector component name ''y''}} - &eight_bools.z; // expected-error@89 {{illegal vector component name ''z''}} - foo(eight_bools.w); // expected-error@90 {{illegal vector component name ''w''}} - foo(eight_bools.wyx); // expected-error@91 {{illegal vector component name ''wyx''}} + eight_bools.y = false; // expected-error@88 {{illegal vector component name 'y'}} + &eight_bools.z; // expected-error@89 {{illegal vector component name 'z'}} + foo(eight_bools.w); // expected-error@90 {{illegal vector component name 'w'}} + foo(eight_bools.wyx); // expected-error@91 {{illegal vector component name 'wyx'}} } void Sizeof() { diff --git a/clang/test/SemaHLSL/BuiltIns/StructuredBuffers.hlsl b/clang/test/SemaHLSL/BuiltIns/StructuredBuffers.hlsl index edfc1b48037c9..fb14429025d5a 100644 --- a/clang/test/SemaHLSL/BuiltIns/StructuredBuffers.hlsl +++ b/clang/test/SemaHLSL/BuiltIns/StructuredBuffers.hlsl @@ -5,13 +5,25 @@ typedef vector float3; StructuredBuffer Buffer; // expected-error@+2 {{class template 'StructuredBuffer' requires template arguments}} -// expected-note@*:* {{template declaration from hidden source: template class StructuredBuffer {}}} +// expected-note@*:* {{template declaration from hidden source: template requires __is_structured_resource_element_compatible class StructuredBuffer {}}} StructuredBuffer BufferErr1; // expected-error@+2 {{too few template arguments for class template 'StructuredBuffer'}} -// expected-note@*:* {{template declaration from hidden source: template class StructuredBuffer {}}} +// expected-note@*:* {{template declaration from hidden source: template requires __is_structured_resource_element_compatible class StructuredBuffer {}}} StructuredBuffer<> BufferErr2; +// test elements of 0 size +// expected-error@+3{{constraints not satisfied for class template 'StructuredBuffer' [with element_type = int[0]]}} +// expected-note@*:*{{because 'int[0]' does not satisfy '__is_structured_resource_element_compatible'}} +// expected-note@*:*{{because 'sizeof(int[0]) >= 1UL' (0 >= 1) evaluated to false}} +StructuredBuffer BufferErr3; + +// In C++, empty structs do have a size of 1. So should HLSL. +// The concept will accept empty structs as element types, despite it being unintuitive. +struct Empty {}; +StructuredBuffer BufferErr4; + + [numthreads(1,1,1)] void main() { (void)Buffer.__handle; // expected-error {{'__handle' is a private member of 'hlsl::StructuredBuffer>'}} diff --git a/clang/test/SemaOpenACC/combined-construct-async-clause.cpp b/clang/test/SemaOpenACC/combined-construct-async-clause.cpp index 872586acbaffa..c54f340cdfd96 100644 --- a/clang/test/SemaOpenACC/combined-construct-async-clause.cpp +++ b/clang/test/SemaOpenACC/combined-construct-async-clause.cpp @@ -48,7 +48,7 @@ void Test() { #pragma acc parallel loop async(Convert) for (int i = 5; i < 10; ++i); - // expected-error@+2{{OpenACC integer expression type 'struct ExplicitConvertOnly' requires explicit conversion to 'int'}} + // expected-error@+2{{OpenACC integer expression requires explicit conversion from 'struct ExplicitConvertOnly' to 'int'}} // expected-note@#EXPL_CONV{{conversion to integral type 'int'}} #pragma acc kernels loop async(Explicit) for (int i = 5; i < 10; ++i); @@ -94,12 +94,12 @@ void TestInst() { #pragma acc kernels loop async(T::ACValue) for (int i = 5; i < 10; ++i); - // expected-error@+2{{OpenACC integer expression type 'const ExplicitConvertOnly' requires explicit conversion to 'int'}} + // expected-error@+2{{OpenACC integer expression requires explicit conversion from 'const ExplicitConvertOnly' to 'int'}} // expected-note@#EXPL_CONV{{conversion to integral type 'int'}} #pragma acc parallel loop async(HasInt::EXValue) for (int i = 5; i < 10; ++i); - // expected-error@+2{{OpenACC integer expression type 'const ExplicitConvertOnly' requires explicit conversion to 'int'}} + // expected-error@+2{{OpenACC integer expression requires explicit conversion from 'const ExplicitConvertOnly' to 'int'}} // expected-note@#EXPL_CONV{{conversion to integral type 'int'}} #pragma acc kernels loop async(T::EXValue) for (int i = 5; i < 10; ++i); diff --git a/clang/test/SemaOpenACC/combined-construct-auto_seq_independent-clauses.c b/clang/test/SemaOpenACC/combined-construct-auto_seq_independent-clauses.c index a71d25ce61bed..f37c1d7e72928 100644 --- a/clang/test/SemaOpenACC/combined-construct-auto_seq_independent-clauses.c +++ b/clang/test/SemaOpenACC/combined-construct-auto_seq_independent-clauses.c @@ -134,7 +134,7 @@ void uses() { for(unsigned i = 0; i < 5; ++i); #pragma acc parallel loop auto num_workers(1) for(unsigned i = 0; i < 5; ++i); - // expected-warning@+1{{OpenACC clause 'device_num' not yet implemented}} + // expected-error@+1{{OpenACC 'device_num' clause is not valid on 'parallel loop' directive}} #pragma acc parallel loop auto device_num(1) for(unsigned i = 0; i < 5; ++i); // expected-warning@+1{{OpenACC clause 'default_async' not yet implemented}} @@ -251,7 +251,7 @@ void uses() { for(unsigned i = 0; i < 5; ++i); #pragma acc parallel loop num_workers(1) auto for(unsigned i = 0; i < 5; ++i); - // expected-warning@+1{{OpenACC clause 'device_num' not yet implemented}} + // expected-error@+1{{OpenACC 'device_num' clause is not valid on 'parallel loop' directive}} #pragma acc parallel loop device_num(1) auto for(unsigned i = 0; i < 5; ++i); // expected-warning@+1{{OpenACC clause 'default_async' not yet implemented}} @@ -369,7 +369,7 @@ void uses() { for(unsigned i = 0; i < 5; ++i); #pragma acc parallel loop independent num_workers(1) for(unsigned i = 0; i < 5; ++i); - // expected-warning@+1{{OpenACC clause 'device_num' not yet implemented}} + // expected-error@+1{{OpenACC 'device_num' clause is not valid on 'parallel loop' directive}} #pragma acc parallel loop independent device_num(1) for(unsigned i = 0; i < 5; ++i); // expected-warning@+1{{OpenACC clause 'default_async' not yet implemented}} @@ -486,7 +486,7 @@ void uses() { for(unsigned i = 0; i < 5; ++i); #pragma acc parallel loop num_workers(1) independent for(unsigned i = 0; i < 5; ++i); - // expected-warning@+1{{OpenACC clause 'device_num' not yet implemented}} + // expected-error@+1{{OpenACC 'device_num' clause is not valid on 'parallel loop' directive}} #pragma acc parallel loop device_num(1) independent for(unsigned i = 0; i < 5; ++i); // expected-warning@+1{{OpenACC clause 'default_async' not yet implemented}} @@ -612,7 +612,7 @@ void uses() { for(unsigned i = 0; i < 5; ++i); #pragma acc parallel loop seq num_workers(1) for(unsigned i = 0; i < 5; ++i); - // expected-warning@+1{{OpenACC clause 'device_num' not yet implemented}} + // expected-error@+1{{OpenACC 'device_num' clause is not valid on 'parallel loop' directive}} #pragma acc parallel loop seq device_num(1) for(unsigned i = 0; i < 5; ++i); // expected-warning@+1{{OpenACC clause 'default_async' not yet implemented}} @@ -735,7 +735,7 @@ void uses() { for(unsigned i = 0; i < 5; ++i); #pragma acc parallel loop num_workers(1) seq for(unsigned i = 0; i < 5; ++i); - // expected-warning@+1{{OpenACC clause 'device_num' not yet implemented}} + // expected-error@+1{{OpenACC 'device_num' clause is not valid on 'parallel loop' directive}} #pragma acc parallel loop device_num(1) seq for(unsigned i = 0; i < 5; ++i); // expected-warning@+1{{OpenACC clause 'default_async' not yet implemented}} diff --git a/clang/test/SemaOpenACC/combined-construct-device_type-clause.c b/clang/test/SemaOpenACC/combined-construct-device_type-clause.c index 40339941f51a9..50612c2a4685e 100644 --- a/clang/test/SemaOpenACC/combined-construct-device_type-clause.c +++ b/clang/test/SemaOpenACC/combined-construct-device_type-clause.c @@ -190,8 +190,7 @@ void uses() { for(int i = 0; i < 5; ++i); #pragma acc parallel loop device_type(*) num_workers(1) for(int i = 0; i < 5; ++i); - // expected-error@+2{{OpenACC clause 'device_num' may not follow a 'device_type' clause in a 'serial loop' construct}} - // expected-note@+1{{previous clause is here}} + // expected-error@+1{{OpenACC 'device_num' clause is not valid on 'serial loop' directive}} #pragma acc serial loop device_type(*) device_num(1) for(int i = 0; i < 5; ++i); // expected-error@+2{{OpenACC clause 'default_async' may not follow a 'device_type' clause in a 'serial loop' construct}} diff --git a/clang/test/SemaOpenACC/combined-construct-wait-clause.cpp b/clang/test/SemaOpenACC/combined-construct-wait-clause.cpp index 9ce04290cbe5a..e0411925e9f20 100644 --- a/clang/test/SemaOpenACC/combined-construct-wait-clause.cpp +++ b/clang/test/SemaOpenACC/combined-construct-wait-clause.cpp @@ -18,7 +18,7 @@ void Test() { #pragma acc parallel loop wait(Ambiguous) for (unsigned i = 0; i < 5; ++i); - // expected-error@+2{{OpenACC integer expression type 'struct ExplicitConvertOnly' requires explicit conversion to 'int'}} + // expected-error@+2{{OpenACC integer expression requires explicit conversion from 'struct ExplicitConvertOnly' to 'int'}} // expected-note@#EXPL_CONV{{conversion to integral type 'int'}} #pragma acc parallel loop wait(4, Explicit, 5) for (unsigned i = 0; i < 5; ++i); @@ -29,12 +29,12 @@ void Test() { #pragma acc parallel loop wait(queues: Ambiguous, 5) for (unsigned i = 0; i < 5; ++i); - // expected-error@+2{{OpenACC integer expression type 'struct ExplicitConvertOnly' requires explicit conversion to 'int'}} + // expected-error@+2{{OpenACC integer expression requires explicit conversion from 'struct ExplicitConvertOnly' to 'int'}} // expected-note@#EXPL_CONV{{conversion to integral type 'int'}} #pragma acc parallel loop wait(devnum: Explicit: 5) for (unsigned i = 0; i < 5; ++i); - // expected-error@+2{{OpenACC integer expression type 'struct ExplicitConvertOnly' requires explicit conversion to 'int'}} + // expected-error@+2{{OpenACC integer expression requires explicit conversion from 'struct ExplicitConvertOnly' to 'int'}} // expected-note@#EXPL_CONV{{conversion to integral type 'int'}} #pragma acc parallel loop wait(devnum: Explicit:queues: 5) for (unsigned i = 0; i < 5; ++i); @@ -70,7 +70,7 @@ void TestInst() { #pragma acc parallel loop wait(devnum:T::value :queues:T::ACValue) for (unsigned i = 0; i < 5; ++i); - // expected-error@+5{{OpenACC integer expression type 'const ExplicitConvertOnly' requires explicit conversion to 'int'}} + // expected-error@+5{{OpenACC integer expression requires explicit conversion from 'const ExplicitConvertOnly' to 'int'}} // expected-note@#EXPL_CONV{{conversion to integral type 'int'}} // expected-error@+3{{multiple conversions from expression type 'const AmbiguousConvert' to an integral type}} // expected-note@#AMBIG_INT{{conversion to integral type 'int'}} @@ -78,7 +78,7 @@ void TestInst() { #pragma acc parallel loop wait(devnum:T::EXValue :queues:T::ACValue) for (unsigned i = 0; i < 5; ++i); - // expected-error@+5{{OpenACC integer expression type 'const ExplicitConvertOnly' requires explicit conversion to 'int'}} + // expected-error@+5{{OpenACC integer expression requires explicit conversion from 'const ExplicitConvertOnly' to 'int'}} // expected-note@#EXPL_CONV{{conversion to integral type 'int'}} // expected-error@+3{{multiple conversions from expression type 'const AmbiguousConvert' to an integral type}} // expected-note@#AMBIG_INT{{conversion to integral type 'int'}} @@ -86,7 +86,7 @@ void TestInst() { #pragma acc parallel loop wait(T::EXValue, T::ACValue) for (unsigned i = 0; i < 5; ++i); - // expected-error@+5{{OpenACC integer expression type 'const ExplicitConvertOnly' requires explicit conversion to 'int'}} + // expected-error@+5{{OpenACC integer expression requires explicit conversion from 'const ExplicitConvertOnly' to 'int'}} // expected-note@#EXPL_CONV{{conversion to integral type 'int'}} // expected-error@+3{{multiple conversions from expression type 'const AmbiguousConvert' to an integral type}} // expected-note@#AMBIG_INT{{conversion to integral type 'int'}} diff --git a/clang/test/SemaOpenACC/compute-construct-async-clause.cpp b/clang/test/SemaOpenACC/compute-construct-async-clause.cpp index a5da7c8f4e56e..44b1540a934c2 100644 --- a/clang/test/SemaOpenACC/compute-construct-async-clause.cpp +++ b/clang/test/SemaOpenACC/compute-construct-async-clause.cpp @@ -46,7 +46,7 @@ void Test() { #pragma acc parallel async(Convert) while(1); - // expected-error@+2{{OpenACC integer expression type 'struct ExplicitConvertOnly' requires explicit conversion to 'int'}} + // expected-error@+2{{OpenACC integer expression requires explicit conversion from 'struct ExplicitConvertOnly' to 'int'}} // expected-note@#EXPL_CONV{{conversion to integral type 'int'}} #pragma acc kernels async(Explicit) while(1); @@ -92,12 +92,12 @@ void TestInst() { #pragma acc kernels async(T::ACValue) while (1); - // expected-error@+2{{OpenACC integer expression type 'const ExplicitConvertOnly' requires explicit conversion to 'int'}} + // expected-error@+2{{OpenACC integer expression requires explicit conversion from 'const ExplicitConvertOnly' to 'int'}} // expected-note@#EXPL_CONV{{conversion to integral type 'int'}} #pragma acc parallel async(HasInt::EXValue) while (1); - // expected-error@+2{{OpenACC integer expression type 'const ExplicitConvertOnly' requires explicit conversion to 'int'}} + // expected-error@+2{{OpenACC integer expression requires explicit conversion from 'const ExplicitConvertOnly' to 'int'}} // expected-note@#EXPL_CONV{{conversion to integral type 'int'}} #pragma acc kernels async(T::EXValue) while (1); diff --git a/clang/test/SemaOpenACC/compute-construct-device_type-clause.c b/clang/test/SemaOpenACC/compute-construct-device_type-clause.c index c1a77abf5c3f1..bbad68c425f3e 100644 --- a/clang/test/SemaOpenACC/compute-construct-device_type-clause.c +++ b/clang/test/SemaOpenACC/compute-construct-device_type-clause.c @@ -195,8 +195,7 @@ void uses() { while(1); #pragma acc kernels device_type(*) num_workers(1) while(1); - // expected-error@+2{{OpenACC clause 'device_num' may not follow a 'device_type' clause in a 'kernels' construct}} - // expected-note@+1{{previous clause is here}} + // expected-error@+1{{OpenACC 'device_num' clause is not valid on 'kernels' directive}} #pragma acc kernels device_type(*) device_num(1) while(1); // expected-error@+2{{OpenACC clause 'default_async' may not follow a 'device_type' clause in a 'kernels' construct}} diff --git a/clang/test/SemaOpenACC/compute-construct-num_gangs-clause.cpp b/clang/test/SemaOpenACC/compute-construct-num_gangs-clause.cpp index c50f52afda7c1..c6dbe4db2be64 100644 --- a/clang/test/SemaOpenACC/compute-construct-num_gangs-clause.cpp +++ b/clang/test/SemaOpenACC/compute-construct-num_gangs-clause.cpp @@ -74,20 +74,20 @@ void Test() { #pragma acc parallel num_gangs(SomeE, NC) while(1); - // expected-error@+3{{OpenACC integer expression type 'struct ExplicitConvertOnly' requires explicit conversion to 'int'}} + // expected-error@+3{{OpenACC integer expression requires explicit conversion from 'struct ExplicitConvertOnly' to 'int'}} // expected-note@#EXPL_CONV{{conversion to integral type 'int'}} // expected-error@+1{{OpenACC clause 'num_gangs' requires expression of integer type ('struct NotConvertible' invalid)}} #pragma acc parallel num_gangs(Explicit, NC) while(1); - // expected-error@+4{{OpenACC integer expression type 'struct ExplicitConvertOnly' requires explicit conversion to 'int'}} + // expected-error@+4{{OpenACC integer expression requires explicit conversion from 'struct ExplicitConvertOnly' to 'int'}} // expected-note@#EXPL_CONV{{conversion to integral type 'int'}} // expected-error@+2{{OpenACC clause 'num_gangs' requires expression of integer type ('struct NotConvertible' invalid)}} // expected-error@+1{{OpenACC 'num_gangs' clause is not valid on 'serial' directive}} #pragma acc serial num_gangs(Explicit, NC) while(1); - // expected-error@+6{{OpenACC integer expression type 'struct ExplicitConvertOnly' requires explicit conversion to 'int'}} + // expected-error@+6{{OpenACC integer expression requires explicit conversion from 'struct ExplicitConvertOnly' to 'int'}} // expected-note@#EXPL_CONV{{conversion to integral type 'int'}} // expected-error@+4{{OpenACC clause 'num_gangs' requires expression of integer type ('struct NotConvertible' invalid)}} // expected-error@+3{{multiple conversions from expression type 'struct AmbiguousConvert' to an integral type}} @@ -96,7 +96,7 @@ void Test() { #pragma acc parallel num_gangs(Explicit, NC, Ambiguous) while(1); - // expected-error@+7{{OpenACC integer expression type 'struct ExplicitConvertOnly' requires explicit conversion to 'int'}} + // expected-error@+7{{OpenACC integer expression requires explicit conversion from 'struct ExplicitConvertOnly' to 'int'}} // expected-note@#EXPL_CONV{{conversion to integral type 'int'}} // expected-error@+5{{OpenACC clause 'num_gangs' requires expression of integer type ('struct NotConvertible' invalid)}} // expected-error@+4{{multiple conversions from expression type 'struct AmbiguousConvert' to an integral type}} diff --git a/clang/test/SemaOpenACC/compute-construct-num_workers-clause.cpp b/clang/test/SemaOpenACC/compute-construct-num_workers-clause.cpp index 9449b77d092f4..c73f421222e86 100644 --- a/clang/test/SemaOpenACC/compute-construct-num_workers-clause.cpp +++ b/clang/test/SemaOpenACC/compute-construct-num_workers-clause.cpp @@ -44,7 +44,7 @@ void Test() { #pragma acc parallel num_workers(Convert) while(1); - // expected-error@+2{{OpenACC integer expression type 'struct ExplicitConvertOnly' requires explicit conversion to 'int'}} + // expected-error@+2{{OpenACC integer expression requires explicit conversion from 'struct ExplicitConvertOnly' to 'int'}} // expected-note@#EXPL_CONV{{conversion to integral type 'int'}} #pragma acc kernels num_workers(Explicit) while(1); @@ -90,12 +90,12 @@ void TestInst() { #pragma acc kernels num_workers(T::ACValue) while (1); - // expected-error@+2{{OpenACC integer expression type 'const ExplicitConvertOnly' requires explicit conversion to 'int'}} + // expected-error@+2{{OpenACC integer expression requires explicit conversion from 'const ExplicitConvertOnly' to 'int'}} // expected-note@#EXPL_CONV{{conversion to integral type 'int'}} #pragma acc parallel num_workers(HasInt::EXValue) while (1); - // expected-error@+2{{OpenACC integer expression type 'const ExplicitConvertOnly' requires explicit conversion to 'int'}} + // expected-error@+2{{OpenACC integer expression requires explicit conversion from 'const ExplicitConvertOnly' to 'int'}} // expected-note@#EXPL_CONV{{conversion to integral type 'int'}} #pragma acc kernels num_workers(T::EXValue) while (1); diff --git a/clang/test/SemaOpenACC/compute-construct-private-clause.c b/clang/test/SemaOpenACC/compute-construct-private-clause.c index d979fd909f11c..a40d84c669d9a 100644 --- a/clang/test/SemaOpenACC/compute-construct-private-clause.c +++ b/clang/test/SemaOpenACC/compute-construct-private-clause.c @@ -135,8 +135,7 @@ void uses(int IntParam, short *PointerParam, float ArrayParam[5], Complete Compo #pragma acc parallel private((float)ArrayParam[2]) while(1); - // expected-error@+2{{OpenACC 'private' clause is not valid on 'init' directive}} - // expected-warning@+1{{OpenACC construct 'init' not yet implemented}} + // expected-error@+1{{OpenACC 'private' clause is not valid on 'init' directive}} #pragma acc init private(LocalInt) for(;;); } diff --git a/clang/test/SemaOpenACC/compute-construct-reduction-clause.c b/clang/test/SemaOpenACC/compute-construct-reduction-clause.c index fcc4ca2655c20..4d426cf189fca 100644 --- a/clang/test/SemaOpenACC/compute-construct-reduction-clause.c +++ b/clang/test/SemaOpenACC/compute-construct-reduction-clause.c @@ -105,8 +105,7 @@ void uses(unsigned Parm) { #pragma acc parallel reduction(&:HA.array[1:2]) while (1); - // expected-error@+2{{OpenACC 'reduction' clause is not valid on 'init' directive}} - // expected-warning@+1{{OpenACC construct 'init' not yet implemented}} + // expected-error@+1{{OpenACC 'reduction' clause is not valid on 'init' directive}} #pragma acc init reduction(+:I) for(;;); } diff --git a/clang/test/SemaOpenACC/compute-construct-vector_length-clause.cpp b/clang/test/SemaOpenACC/compute-construct-vector_length-clause.cpp index f6c5dde1a0235..f2bbe0f022a07 100644 --- a/clang/test/SemaOpenACC/compute-construct-vector_length-clause.cpp +++ b/clang/test/SemaOpenACC/compute-construct-vector_length-clause.cpp @@ -44,7 +44,7 @@ void Test() { #pragma acc parallel vector_length(Convert) while(1); - // expected-error@+2{{OpenACC integer expression type 'struct ExplicitConvertOnly' requires explicit conversion to 'int'}} + // expected-error@+2{{OpenACC integer expression requires explicit conversion from 'struct ExplicitConvertOnly' to 'int'}} // expected-note@#EXPL_CONV{{conversion to integral type 'int'}} #pragma acc kernels vector_length(Explicit) while(1); @@ -90,12 +90,12 @@ void TestInst() { #pragma acc kernels vector_length(T::ACValue) while (1); - // expected-error@+2{{OpenACC integer expression type 'const ExplicitConvertOnly' requires explicit conversion to 'int'}} + // expected-error@+2{{OpenACC integer expression requires explicit conversion from 'const ExplicitConvertOnly' to 'int'}} // expected-note@#EXPL_CONV{{conversion to integral type 'int'}} #pragma acc parallel vector_length(HasInt::EXValue) while (1); - // expected-error@+2{{OpenACC integer expression type 'const ExplicitConvertOnly' requires explicit conversion to 'int'}} + // expected-error@+2{{OpenACC integer expression requires explicit conversion from 'const ExplicitConvertOnly' to 'int'}} // expected-note@#EXPL_CONV{{conversion to integral type 'int'}} #pragma acc kernels vector_length(T::EXValue) while (1); diff --git a/clang/test/SemaOpenACC/compute-construct-wait-clause.cpp b/clang/test/SemaOpenACC/compute-construct-wait-clause.cpp index 94f669be0f672..fbe40ce5f31c1 100644 --- a/clang/test/SemaOpenACC/compute-construct-wait-clause.cpp +++ b/clang/test/SemaOpenACC/compute-construct-wait-clause.cpp @@ -18,7 +18,7 @@ void Test() { #pragma acc parallel wait(Ambiguous) while (true); - // expected-error@+2{{OpenACC integer expression type 'struct ExplicitConvertOnly' requires explicit conversion to 'int'}} + // expected-error@+2{{OpenACC integer expression requires explicit conversion from 'struct ExplicitConvertOnly' to 'int'}} // expected-note@#EXPL_CONV{{conversion to integral type 'int'}} #pragma acc parallel wait(4, Explicit, 5) while (true); @@ -29,12 +29,12 @@ void Test() { #pragma acc parallel wait(queues: Ambiguous, 5) while (true); - // expected-error@+2{{OpenACC integer expression type 'struct ExplicitConvertOnly' requires explicit conversion to 'int'}} + // expected-error@+2{{OpenACC integer expression requires explicit conversion from 'struct ExplicitConvertOnly' to 'int'}} // expected-note@#EXPL_CONV{{conversion to integral type 'int'}} #pragma acc parallel wait(devnum: Explicit: 5) while (true); - // expected-error@+2{{OpenACC integer expression type 'struct ExplicitConvertOnly' requires explicit conversion to 'int'}} + // expected-error@+2{{OpenACC integer expression requires explicit conversion from 'struct ExplicitConvertOnly' to 'int'}} // expected-note@#EXPL_CONV{{conversion to integral type 'int'}} #pragma acc parallel wait(devnum: Explicit:queues: 5) while (true); @@ -70,7 +70,7 @@ void TestInst() { #pragma acc parallel wait(devnum:T::value :queues:T::ACValue) while (true); - // expected-error@+5{{OpenACC integer expression type 'const ExplicitConvertOnly' requires explicit conversion to 'int'}} + // expected-error@+5{{OpenACC integer expression requires explicit conversion from 'const ExplicitConvertOnly' to 'int'}} // expected-note@#EXPL_CONV{{conversion to integral type 'int'}} // expected-error@+3{{multiple conversions from expression type 'const AmbiguousConvert' to an integral type}} // expected-note@#AMBIG_INT{{conversion to integral type 'int'}} @@ -78,7 +78,7 @@ void TestInst() { #pragma acc parallel wait(devnum:T::EXValue :queues:T::ACValue) while (true); - // expected-error@+5{{OpenACC integer expression type 'const ExplicitConvertOnly' requires explicit conversion to 'int'}} + // expected-error@+5{{OpenACC integer expression requires explicit conversion from 'const ExplicitConvertOnly' to 'int'}} // expected-note@#EXPL_CONV{{conversion to integral type 'int'}} // expected-error@+3{{multiple conversions from expression type 'const AmbiguousConvert' to an integral type}} // expected-note@#AMBIG_INT{{conversion to integral type 'int'}} @@ -86,7 +86,7 @@ void TestInst() { #pragma acc parallel wait(T::EXValue, T::ACValue) while (true); - // expected-error@+5{{OpenACC integer expression type 'const ExplicitConvertOnly' requires explicit conversion to 'int'}} + // expected-error@+5{{OpenACC integer expression requires explicit conversion from 'const ExplicitConvertOnly' to 'int'}} // expected-note@#EXPL_CONV{{conversion to integral type 'int'}} // expected-error@+3{{multiple conversions from expression type 'const AmbiguousConvert' to an integral type}} // expected-note@#AMBIG_INT{{conversion to integral type 'int'}} diff --git a/clang/test/SemaOpenACC/init-construct-ast.cpp b/clang/test/SemaOpenACC/init-construct-ast.cpp new file mode 100644 index 0000000000000..7c7d07a450d51 --- /dev/null +++ b/clang/test/SemaOpenACC/init-construct-ast.cpp @@ -0,0 +1,148 @@ +// RUN: %clang_cc1 %s -fopenacc -ast-dump | FileCheck %s + +// Test this with PCH. +// RUN: %clang_cc1 %s -fopenacc -emit-pch -o %t %s +// RUN: %clang_cc1 %s -fopenacc -include-pch %t -ast-dump-all | FileCheck %s + +#ifndef PCH_HELPER +#define PCH_HELPER + +int some_int(); +long some_long(); +void NormalFunc() { + // CHECK-LABEL: NormalFunc + // CHECK-NEXT: CompoundStmt + +#pragma acc init + // CHECK-NEXT: OpenACCInitConstruct{{.*}}init +#pragma acc init if (some_int() < some_long()) + // CHECK-NEXT: OpenACCInitConstruct{{.*}}init + // CHECK-NEXT: if clause + // CHECK-NEXT: BinaryOperator{{.*}} 'bool' '<' + // CHECK-NEXT: ImplicitCastExpr{{.*}} 'long' + // CHECK-NEXT: CallExpr + // CHECK-NEXT: ImplicitCastExpr + // CHECK-NEXT: DeclRefExpr{{.*}}'some_int' 'int ()' + // CHECK-NEXT: CallExpr + // CHECK-NEXT: ImplicitCastExpr + // CHECK-NEXT: DeclRefExpr{{.*}}'some_long' 'long ()' +#pragma acc init device_num(some_int()) + // CHECK-NEXT: OpenACCInitConstruct{{.*}}init + // CHECK-NEXT: device_num clause + // CHECK-NEXT: CallExpr + // CHECK-NEXT: ImplicitCastExpr + // CHECK-NEXT: DeclRefExpr{{.*}}'some_int' 'int ()' +#pragma acc init device_type(T) + // CHECK-NEXT: OpenACCInitConstruct{{.*}}init + // CHECK-NEXT: device_type(T) +#pragma acc init if (some_int() < some_long()) device_type(T) device_num(some_int()) + // CHECK-NEXT: OpenACCInitConstruct{{.*}}init + // CHECK-NEXT: if clause + // CHECK-NEXT: BinaryOperator{{.*}} 'bool' '<' + // CHECK-NEXT: ImplicitCastExpr{{.*}} 'long' + // CHECK-NEXT: CallExpr + // CHECK-NEXT: ImplicitCastExpr + // CHECK-NEXT: DeclRefExpr{{.*}}'some_int' 'int ()' + // CHECK-NEXT: CallExpr + // CHECK-NEXT: ImplicitCastExpr + // CHECK-NEXT: DeclRefExpr{{.*}}'some_long' 'long ()' + // CHECK-NEXT: device_type(T) + // CHECK-NEXT: device_num clause + // CHECK-NEXT: CallExpr + // CHECK-NEXT: ImplicitCastExpr + // CHECK-NEXT: DeclRefExpr{{.*}}'some_int' 'int ()' +} + +template +void TemplFunc(T t) { + // CHECK-LABEL: FunctionTemplateDecl {{.*}}TemplFunc + // CHECK-NEXT: TemplateTypeParmDecl + // CHECK-NEXT: FunctionDecl{{.*}}TemplFunc + // CHECK-NEXT: ParmVarDecl{{.*}} t 'T' + // CHECK-NEXT: CompoundStmt + +#pragma acc init + // CHECK-NEXT: OpenACCInitConstruct{{.*}}init +#pragma acc init if (T::value > t) + // CHECK-NEXT: OpenACCInitConstruct{{.*}}init + // CHECK-NEXT: if clause + // CHECK-NEXT: BinaryOperator{{.*}} '' '>' + // CHECK-NEXT: DependentScopeDeclRefExpr + // CHECK-NEXT: NestedNameSpecifier{{.*}} 'T' + // CHECK-NEXT: DeclRefExpr{{.*}} 't' 'T' +#pragma acc init device_num(t) + // CHECK-NEXT: OpenACCInitConstruct{{.*}}init + // CHECK-NEXT: device_num clause + // CHECK-NEXT: DeclRefExpr{{.*}} 't' 'T' +#pragma acc init device_type(T) + // CHECK-NEXT: OpenACCInitConstruct{{.*}}init + // CHECK-NEXT: device_type(T) +#pragma acc init if (T::value > t) device_type(T) device_num(t) + // CHECK-NEXT: OpenACCInitConstruct{{.*}}init + // CHECK-NEXT: if clause + // CHECK-NEXT: BinaryOperator{{.*}} '' '>' + // CHECK-NEXT: DependentScopeDeclRefExpr + // CHECK-NEXT: NestedNameSpecifier{{.*}} 'T' + // CHECK-NEXT: DeclRefExpr{{.*}} 't' 'T' + // CHECK-NEXT: device_type(T) + // CHECK-NEXT: device_num clause + // CHECK-NEXT: DeclRefExpr{{.*}} 't' 'T' + + // Instantiation: + // CHECK-NEXT: FunctionDecl{{.*}} TemplFunc 'void (SomeStruct)' implicit_instantiation + // CHECK-NEXT: TemplateArgument type 'SomeStruct' + // CHECK-NEXT: RecordType{{.*}} 'SomeStruct' + // CHECK-NEXT: CXXRecord{{.*}} 'SomeStruct' + // CHECK-NEXT: ParmVarDecl{{.*}} t 'SomeStruct' + // CHECK-NEXT: CompoundStmt + + // CHECK-NEXT: OpenACCInitConstruct{{.*}}init + + // CHECK-NEXT: OpenACCInitConstruct{{.*}}init + // CHECK-NEXT: if clause + // CHECK-NEXT: BinaryOperator{{.*}} 'bool' '>' + // CHECK-NEXT: ImplicitCastExpr{{.*}}'unsigned int' + // CHECK-NEXT: DeclRefExpr{{.*}}'value' 'const unsigned int' + // CHECK-NEXT: NestedNameSpecifier{{.*}} 'SomeStruct' + // CHECK-NEXT: ImplicitCastExpr{{.*}}'unsigned int' + // CHECK-NEXT: CXXMemberCallExpr{{.*}} 'unsigned int' + // CHECK-NEXT: MemberExpr{{.*}} .operator unsigned int + // CHECK-NEXT: DeclRefExpr{{.*}} 't' 'SomeStruct' + + // CHECK-NEXT: OpenACCInitConstruct{{.*}}init + // CHECK-NEXT: device_num clause + // CHECK-NEXT: ImplicitCastExpr{{.*}}'unsigned int' + // CHECK-NEXT: CXXMemberCallExpr{{.*}}'unsigned int' + // CHECK-NEXT: MemberExpr{{.*}} .operator unsigned int + // CHECK-NEXT: DeclRefExpr{{.*}} 't' 'SomeStruct' + + // CHECK-NEXT: OpenACCInitConstruct{{.*}}init + // CHECK-NEXT: device_type(T) + + // CHECK-NEXT: OpenACCInitConstruct{{.*}}init + // CHECK-NEXT: if clause + // CHECK-NEXT: BinaryOperator{{.*}} 'bool' '>' + // CHECK-NEXT: ImplicitCastExpr{{.*}}'unsigned int' + // CHECK-NEXT: DeclRefExpr{{.*}}'value' 'const unsigned int' + // CHECK-NEXT: NestedNameSpecifier{{.*}} 'SomeStruct' + // CHECK-NEXT: ImplicitCastExpr{{.*}}'unsigned int' + // CHECK-NEXT: CXXMemberCallExpr{{.*}} 'unsigned int' + // CHECK-NEXT: MemberExpr{{.*}} .operator unsigned int + // CHECK-NEXT: DeclRefExpr{{.*}} 't' 'SomeStruct' + // CHECK-NEXT: device_type(T) + // CHECK-NEXT: device_num clause + // CHECK-NEXT: ImplicitCastExpr{{.*}}'unsigned int' + // CHECK-NEXT: CXXMemberCallExpr{{.*}}'unsigned int' + // CHECK-NEXT: MemberExpr{{.*}} .operator unsigned int + // CHECK-NEXT: DeclRefExpr{{.*}} 't' 'SomeStruct' +} + +struct SomeStruct{ + static constexpr unsigned value = 5; + operator unsigned(); +}; + +void use() { + TemplFunc(SomeStruct{}); +} +#endif diff --git a/clang/test/SemaOpenACC/init-construct.cpp b/clang/test/SemaOpenACC/init-construct.cpp new file mode 100644 index 0000000000000..e4491ee905f3f --- /dev/null +++ b/clang/test/SemaOpenACC/init-construct.cpp @@ -0,0 +1,71 @@ +// RUN: %clang_cc1 %s -fopenacc -verify + +struct NotConvertible{} NC; +short getS(); +int getI(); + +struct AmbiguousConvert{ + operator int(); // #AMBIG_INT + operator short(); // #AMBIG_SHORT + operator float(); +} Ambiguous; + +struct ExplicitConvertOnly { + explicit operator int() const; // #EXPL_CONV +} Explicit; + +void uses() { +#pragma acc init +#pragma acc init if (getI() < getS()) +#pragma acc init device_num(getI()) +#pragma acc init device_type(SOMETHING) device_num(getI()) +#pragma acc init device_type(SOMETHING) if (getI() < getS()) +#pragma acc init device_type(SOMETHING) device_num(getI()) if (getI() < getS()) + + // expected-error@+1{{value of type 'struct NotConvertible' is not contextually convertible to 'bool'}} +#pragma acc init if (NC) + + // expected-error@+1{{OpenACC clause 'device_num' requires expression of integer type ('struct NotConvertible' invalid)}} +#pragma acc init device_num(NC) + // expected-error@+3{{multiple conversions from expression type 'struct AmbiguousConvert' to an integral type}} + // expected-note@#AMBIG_INT{{conversion to integral type 'int'}} + // expected-note@#AMBIG_SHORT{{conversion to integral type 'short'}} +#pragma acc init device_num(Ambiguous) + // expected-error@+2{{OpenACC integer expression requires explicit conversion from 'struct ExplicitConvertOnly' to 'int'}} + // expected-note@#EXPL_CONV{{conversion to integral type 'int'}} +#pragma acc init device_num(Explicit) +} + +template +void TestInst() { + T t; +#pragma acc init +#pragma acc init if (T::value < T{}) +#pragma acc init device_type(SOMETHING) device_num(getI()) if (getI() < getS()) +#pragma acc init device_type(SOMETHING) device_type(T) device_num(t) if (t < T::value) device_num(getI()) if (getI() < getS()) + + // expected-error@+1{{value of type 'const NotConvertible' is not contextually convertible to 'bool'}} +#pragma acc init if (T::NCValue) + + // expected-error@+1{{OpenACC clause 'device_num' requires expression of integer type ('const NotConvertible' invalid)}} +#pragma acc init device_num(T::NCValue) + // expected-error@+3{{multiple conversions from expression type 'const AmbiguousConvert' to an integral type}} + // expected-note@#AMBIG_INT{{conversion to integral type 'int'}} + // expected-note@#AMBIG_SHORT{{conversion to integral type 'short'}} +#pragma acc init device_num(T::ACValue) + // expected-error@+2{{OpenACC integer expression requires explicit conversion from 'const ExplicitConvertOnly' to 'int'}} + // expected-note@#EXPL_CONV{{conversion to integral type 'int'}} +#pragma acc init device_num(T::EXValue) +} + +struct HasStuff { + static constexpr AmbiguousConvert ACValue; + static constexpr ExplicitConvertOnly EXValue; + static constexpr NotConvertible NCValue; + static constexpr unsigned value = 5; + operator char(); +}; + +void Inst() { + TestInst(); // expected-note {{in instantiation of function template specialization}} +} diff --git a/clang/test/SemaOpenACC/loop-construct-auto_seq_independent-clauses.c b/clang/test/SemaOpenACC/loop-construct-auto_seq_independent-clauses.c index d196633c8b6d9..d75d6abb99f6f 100644 --- a/clang/test/SemaOpenACC/loop-construct-auto_seq_independent-clauses.c +++ b/clang/test/SemaOpenACC/loop-construct-auto_seq_independent-clauses.c @@ -149,7 +149,7 @@ void uses() { // expected-error@+1{{OpenACC 'num_workers' clause is not valid on 'loop' directive}} #pragma acc loop auto num_workers(1) for(unsigned i = 0; i < 5; ++i); - // expected-warning@+1{{OpenACC clause 'device_num' not yet implemented}} + // expected-error@+1{{OpenACC 'device_num' clause is not valid on 'loop' directive}} #pragma acc loop auto device_num(1) for(unsigned i = 0; i < 5; ++i); // expected-warning@+1{{OpenACC clause 'default_async' not yet implemented}} @@ -283,7 +283,7 @@ void uses() { // expected-error@+1{{OpenACC 'num_workers' clause is not valid on 'loop' directive}} #pragma acc loop num_workers(1) auto for(unsigned i = 0; i < 5; ++i); - // expected-warning@+1{{OpenACC clause 'device_num' not yet implemented}} + // expected-error@+1{{OpenACC 'device_num' clause is not valid on 'loop' directive}} #pragma acc loop device_num(1) auto for(unsigned i = 0; i < 5; ++i); // expected-warning@+1{{OpenACC clause 'default_async' not yet implemented}} @@ -418,7 +418,7 @@ void uses() { // expected-error@+1{{OpenACC 'num_workers' clause is not valid on 'loop' directive}} #pragma acc loop independent num_workers(1) for(unsigned i = 0; i < 5; ++i); - // expected-warning@+1{{OpenACC clause 'device_num' not yet implemented}} + // expected-error@+1{{OpenACC 'device_num' clause is not valid on 'loop' directive}} #pragma acc loop independent device_num(1) for(unsigned i = 0; i < 5; ++i); // expected-warning@+1{{OpenACC clause 'default_async' not yet implemented}} @@ -552,7 +552,7 @@ void uses() { // expected-error@+1{{OpenACC 'num_workers' clause is not valid on 'loop' directive}} #pragma acc loop num_workers(1) independent for(unsigned i = 0; i < 5; ++i); - // expected-warning@+1{{OpenACC clause 'device_num' not yet implemented}} + // expected-error@+1{{OpenACC 'device_num' clause is not valid on 'loop' directive}} #pragma acc loop device_num(1) independent for(unsigned i = 0; i < 5; ++i); // expected-warning@+1{{OpenACC clause 'default_async' not yet implemented}} @@ -695,7 +695,7 @@ void uses() { // expected-error@+1{{OpenACC 'num_workers' clause is not valid on 'loop' directive}} #pragma acc loop seq num_workers(1) for(unsigned i = 0; i < 5; ++i); - // expected-warning@+1{{OpenACC clause 'device_num' not yet implemented}} + // expected-error@+1{{OpenACC 'device_num' clause is not valid on 'loop' directive}} #pragma acc loop seq device_num(1) for(unsigned i = 0; i < 5; ++i); // expected-warning@+1{{OpenACC clause 'default_async' not yet implemented}} @@ -835,7 +835,7 @@ void uses() { // expected-error@+1{{OpenACC 'num_workers' clause is not valid on 'loop' directive}} #pragma acc loop num_workers(1) seq for(unsigned i = 0; i < 5; ++i); - // expected-warning@+1{{OpenACC clause 'device_num' not yet implemented}} + // expected-error@+1{{OpenACC 'device_num' clause is not valid on 'loop' directive}} #pragma acc loop device_num(1) seq for(unsigned i = 0; i < 5; ++i); // expected-warning@+1{{OpenACC clause 'default_async' not yet implemented}} diff --git a/clang/test/SemaOpenACC/loop-construct-device_type-clause.c b/clang/test/SemaOpenACC/loop-construct-device_type-clause.c index 3e4d0da60b6b2..bf2a2499c3436 100644 --- a/clang/test/SemaOpenACC/loop-construct-device_type-clause.c +++ b/clang/test/SemaOpenACC/loop-construct-device_type-clause.c @@ -170,8 +170,7 @@ void uses() { // expected-error@+1{{OpenACC 'num_workers' clause is not valid on 'loop' directive}} #pragma acc loop device_type(*) num_workers(1) for(int i = 0; i < 5; ++i); - // expected-error@+2{{OpenACC clause 'device_num' may not follow a 'device_type' clause in a 'loop' construct}} - // expected-note@+1{{previous clause is here}} + // expected-error@+1{{OpenACC 'device_num' clause is not valid on 'loop' directive}} #pragma acc loop device_type(*) device_num(1) for(int i = 0; i < 5; ++i); // expected-error@+2{{OpenACC clause 'default_async' may not follow a 'device_type' clause in a 'loop' construct}} diff --git a/clang/test/SemaOpenACC/shutdown-construct-ast.cpp b/clang/test/SemaOpenACC/shutdown-construct-ast.cpp new file mode 100644 index 0000000000000..3ec1c0d936493 --- /dev/null +++ b/clang/test/SemaOpenACC/shutdown-construct-ast.cpp @@ -0,0 +1,148 @@ +// RUN: %clang_cc1 %s -fopenacc -ast-dump | FileCheck %s + +// Test this with PCH. +// RUN: %clang_cc1 %s -fopenacc -emit-pch -o %t %s +// RUN: %clang_cc1 %s -fopenacc -include-pch %t -ast-dump-all | FileCheck %s + +#ifndef PCH_HELPER +#define PCH_HELPER + +int some_int(); +long some_long(); +void NormalFunc() { + // CHECK-LABEL: NormalFunc + // CHECK-NEXT: CompoundStmt + +#pragma acc shutdown + // CHECK-NEXT: OpenACCShutdownConstruct{{.*}}shutdown +#pragma acc shutdown if (some_int() < some_long()) + // CHECK-NEXT: OpenACCShutdownConstruct{{.*}}shutdown + // CHECK-NEXT: if clause + // CHECK-NEXT: BinaryOperator{{.*}} 'bool' '<' + // CHECK-NEXT: ImplicitCastExpr{{.*}} 'long' + // CHECK-NEXT: CallExpr + // CHECK-NEXT: ImplicitCastExpr + // CHECK-NEXT: DeclRefExpr{{.*}}'some_int' 'int ()' + // CHECK-NEXT: CallExpr + // CHECK-NEXT: ImplicitCastExpr + // CHECK-NEXT: DeclRefExpr{{.*}}'some_long' 'long ()' +#pragma acc shutdown device_num(some_int()) + // CHECK-NEXT: OpenACCShutdownConstruct{{.*}}shutdown + // CHECK-NEXT: device_num clause + // CHECK-NEXT: CallExpr + // CHECK-NEXT: ImplicitCastExpr + // CHECK-NEXT: DeclRefExpr{{.*}}'some_int' 'int ()' +#pragma acc shutdown device_type(T) + // CHECK-NEXT: OpenACCShutdownConstruct{{.*}}shutdown + // CHECK-NEXT: device_type(T) +#pragma acc shutdown if (some_int() < some_long()) device_type(T) device_num(some_int()) + // CHECK-NEXT: OpenACCShutdownConstruct{{.*}}shutdown + // CHECK-NEXT: if clause + // CHECK-NEXT: BinaryOperator{{.*}} 'bool' '<' + // CHECK-NEXT: ImplicitCastExpr{{.*}} 'long' + // CHECK-NEXT: CallExpr + // CHECK-NEXT: ImplicitCastExpr + // CHECK-NEXT: DeclRefExpr{{.*}}'some_int' 'int ()' + // CHECK-NEXT: CallExpr + // CHECK-NEXT: ImplicitCastExpr + // CHECK-NEXT: DeclRefExpr{{.*}}'some_long' 'long ()' + // CHECK-NEXT: device_type(T) + // CHECK-NEXT: device_num clause + // CHECK-NEXT: CallExpr + // CHECK-NEXT: ImplicitCastExpr + // CHECK-NEXT: DeclRefExpr{{.*}}'some_int' 'int ()' +} + +template +void TemplFunc(T t) { + // CHECK-LABEL: FunctionTemplateDecl {{.*}}TemplFunc + // CHECK-NEXT: TemplateTypeParmDecl + // CHECK-NEXT: FunctionDecl{{.*}}TemplFunc + // CHECK-NEXT: ParmVarDecl{{.*}} t 'T' + // CHECK-NEXT: CompoundStmt + +#pragma acc shutdown + // CHECK-NEXT: OpenACCShutdownConstruct{{.*}}shutdown +#pragma acc shutdown if (T::value > t) + // CHECK-NEXT: OpenACCShutdownConstruct{{.*}}shutdown + // CHECK-NEXT: if clause + // CHECK-NEXT: BinaryOperator{{.*}} '' '>' + // CHECK-NEXT: DependentScopeDeclRefExpr + // CHECK-NEXT: NestedNameSpecifier{{.*}} 'T' + // CHECK-NEXT: DeclRefExpr{{.*}} 't' 'T' +#pragma acc shutdown device_num(t) + // CHECK-NEXT: OpenACCShutdownConstruct{{.*}}shutdown + // CHECK-NEXT: device_num clause + // CHECK-NEXT: DeclRefExpr{{.*}} 't' 'T' +#pragma acc shutdown device_type(T) + // CHECK-NEXT: OpenACCShutdownConstruct{{.*}}shutdown + // CHECK-NEXT: device_type(T) +#pragma acc shutdown if (T::value > t) device_type(T) device_num(t) + // CHECK-NEXT: OpenACCShutdownConstruct{{.*}}shutdown + // CHECK-NEXT: if clause + // CHECK-NEXT: BinaryOperator{{.*}} '' '>' + // CHECK-NEXT: DependentScopeDeclRefExpr + // CHECK-NEXT: NestedNameSpecifier{{.*}} 'T' + // CHECK-NEXT: DeclRefExpr{{.*}} 't' 'T' + // CHECK-NEXT: device_type(T) + // CHECK-NEXT: device_num clause + // CHECK-NEXT: DeclRefExpr{{.*}} 't' 'T' + + // Instantiation: + // CHECK-NEXT: FunctionDecl{{.*}} TemplFunc 'void (SomeStruct)' implicit_instantiation + // CHECK-NEXT: TemplateArgument type 'SomeStruct' + // CHECK-NEXT: RecordType{{.*}} 'SomeStruct' + // CHECK-NEXT: CXXRecord{{.*}} 'SomeStruct' + // CHECK-NEXT: ParmVarDecl{{.*}} t 'SomeStruct' + // CHECK-NEXT: CompoundStmt + + // CHECK-NEXT: OpenACCShutdownConstruct{{.*}}shutdown + + // CHECK-NEXT: OpenACCShutdownConstruct{{.*}}shutdown + // CHECK-NEXT: if clause + // CHECK-NEXT: BinaryOperator{{.*}} 'bool' '>' + // CHECK-NEXT: ImplicitCastExpr{{.*}}'unsigned int' + // CHECK-NEXT: DeclRefExpr{{.*}}'value' 'const unsigned int' + // CHECK-NEXT: NestedNameSpecifier{{.*}} 'SomeStruct' + // CHECK-NEXT: ImplicitCastExpr{{.*}}'unsigned int' + // CHECK-NEXT: CXXMemberCallExpr{{.*}} 'unsigned int' + // CHECK-NEXT: MemberExpr{{.*}} .operator unsigned int + // CHECK-NEXT: DeclRefExpr{{.*}} 't' 'SomeStruct' + + // CHECK-NEXT: OpenACCShutdownConstruct{{.*}}shutdown + // CHECK-NEXT: device_num clause + // CHECK-NEXT: ImplicitCastExpr{{.*}}'unsigned int' + // CHECK-NEXT: CXXMemberCallExpr{{.*}}'unsigned int' + // CHECK-NEXT: MemberExpr{{.*}} .operator unsigned int + // CHECK-NEXT: DeclRefExpr{{.*}} 't' 'SomeStruct' + + // CHECK-NEXT: OpenACCShutdownConstruct{{.*}}shutdown + // CHECK-NEXT: device_type(T) + + // CHECK-NEXT: OpenACCShutdownConstruct{{.*}}shutdown + // CHECK-NEXT: if clause + // CHECK-NEXT: BinaryOperator{{.*}} 'bool' '>' + // CHECK-NEXT: ImplicitCastExpr{{.*}}'unsigned int' + // CHECK-NEXT: DeclRefExpr{{.*}}'value' 'const unsigned int' + // CHECK-NEXT: NestedNameSpecifier{{.*}} 'SomeStruct' + // CHECK-NEXT: ImplicitCastExpr{{.*}}'unsigned int' + // CHECK-NEXT: CXXMemberCallExpr{{.*}} 'unsigned int' + // CHECK-NEXT: MemberExpr{{.*}} .operator unsigned int + // CHECK-NEXT: DeclRefExpr{{.*}} 't' 'SomeStruct' + // CHECK-NEXT: device_type(T) + // CHECK-NEXT: device_num clause + // CHECK-NEXT: ImplicitCastExpr{{.*}}'unsigned int' + // CHECK-NEXT: CXXMemberCallExpr{{.*}}'unsigned int' + // CHECK-NEXT: MemberExpr{{.*}} .operator unsigned int + // CHECK-NEXT: DeclRefExpr{{.*}} 't' 'SomeStruct' +} + +struct SomeStruct{ + static constexpr unsigned value = 5; + operator unsigned(); +}; + +void use() { + TemplFunc(SomeStruct{}); +} +#endif diff --git a/clang/test/SemaOpenACC/shutdown-construct.cpp b/clang/test/SemaOpenACC/shutdown-construct.cpp new file mode 100644 index 0000000000000..c3390b0412873 --- /dev/null +++ b/clang/test/SemaOpenACC/shutdown-construct.cpp @@ -0,0 +1,71 @@ +// RUN: %clang_cc1 %s -fopenacc -verify + +struct NotConvertible{} NC; +short getS(); +int getI(); + +struct AmbiguousConvert{ + operator int(); // #AMBIG_INT + operator short(); // #AMBIG_SHORT + operator float(); +} Ambiguous; + +struct ExplicitConvertOnly { + explicit operator int() const; // #EXPL_CONV +} Explicit; + +void uses() { +#pragma acc shutdown +#pragma acc shutdown if (getI() < getS()) +#pragma acc shutdown device_num(getI()) +#pragma acc shutdown device_type(SOMETHING) device_num(getI()) +#pragma acc shutdown device_type(SOMETHING) if (getI() < getS()) +#pragma acc shutdown device_type(SOMETHING) device_num(getI()) if (getI() < getS()) + + // expected-error@+1{{value of type 'struct NotConvertible' is not contextually convertible to 'bool'}} +#pragma acc shutdown if (NC) + + // expected-error@+1{{OpenACC clause 'device_num' requires expression of integer type ('struct NotConvertible' invalid)}} +#pragma acc shutdown device_num(NC) + // expected-error@+3{{multiple conversions from expression type 'struct AmbiguousConvert' to an integral type}} + // expected-note@#AMBIG_INT{{conversion to integral type 'int'}} + // expected-note@#AMBIG_SHORT{{conversion to integral type 'short'}} +#pragma acc shutdown device_num(Ambiguous) + // expected-error@+2{{OpenACC integer expression requires explicit conversion from 'struct ExplicitConvertOnly' to 'int'}} + // expected-note@#EXPL_CONV{{conversion to integral type 'int'}} +#pragma acc shutdown device_num(Explicit) +} + +template +void TestInst() { + T t; +#pragma acc shutdown +#pragma acc shutdown if (T::value < T{}) +#pragma acc shutdown device_type(SOMETHING) device_num(getI()) if (getI() < getS()) +#pragma acc shutdown device_type(SOMETHING) device_type(T) device_num(t) if (t < T::value) device_num(getI()) if (getI() < getS()) + + // expected-error@+1{{value of type 'const NotConvertible' is not contextually convertible to 'bool'}} +#pragma acc shutdown if (T::NCValue) + + // expected-error@+1{{OpenACC clause 'device_num' requires expression of integer type ('const NotConvertible' invalid)}} +#pragma acc shutdown device_num(T::NCValue) + // expected-error@+3{{multiple conversions from expression type 'const AmbiguousConvert' to an integral type}} + // expected-note@#AMBIG_INT{{conversion to integral type 'int'}} + // expected-note@#AMBIG_SHORT{{conversion to integral type 'short'}} +#pragma acc shutdown device_num(T::ACValue) + // expected-error@+2{{OpenACC integer expression requires explicit conversion from 'const ExplicitConvertOnly' to 'int'}} + // expected-note@#EXPL_CONV{{conversion to integral type 'int'}} +#pragma acc shutdown device_num(T::EXValue) +} + +struct HasStuff { + static constexpr AmbiguousConvert ACValue; + static constexpr ExplicitConvertOnly EXValue; + static constexpr NotConvertible NCValue; + static constexpr unsigned value = 5; + operator char(); +}; + +void Inst() { + TestInst(); // expected-note {{in instantiation of function template specialization}} +} diff --git a/clang/test/SemaOpenACC/wait-construct.cpp b/clang/test/SemaOpenACC/wait-construct.cpp index a68fc54b6e8f2..2de98762ea600 100644 --- a/clang/test/SemaOpenACC/wait-construct.cpp +++ b/clang/test/SemaOpenACC/wait-construct.cpp @@ -35,7 +35,7 @@ void uses() { // expected-note@#AMBIG_SHORT{{conversion to integral type 'short'}} #pragma acc wait(Ambiguous) - // expected-error@+2{{OpenACC integer expression type 'struct ExplicitConvertOnly' requires explicit conversion to 'int'}} + // expected-error@+2{{OpenACC integer expression requires explicit conversion from 'struct ExplicitConvertOnly' to 'int'}} // expected-note@#EXPL_CONV{{conversion to integral type 'int'}} #pragma acc wait(4, Explicit, 5) @@ -61,7 +61,7 @@ void TestInst() { // expected-note@#AMBIG_SHORT{{conversion to integral type 'short'}} #pragma acc wait(devnum:T::value :queues:T::ACValue) - // expected-error@+5{{OpenACC integer expression type 'const ExplicitConvertOnly' requires explicit conversion to 'int'}} + // expected-error@+5{{OpenACC integer expression requires explicit conversion from 'const ExplicitConvertOnly' to 'int'}} // expected-note@#EXPL_CONV{{conversion to integral type 'int'}} // expected-error@+3{{multiple conversions from expression type 'const AmbiguousConvert' to an integral type}} // expected-note@#AMBIG_INT{{conversion to integral type 'int'}} diff --git a/clang/test/SemaTemplate/pack-deduction.cpp b/clang/test/SemaTemplate/pack-deduction.cpp index 28fb127a38644..b3104609994a4 100644 --- a/clang/test/SemaTemplate/pack-deduction.cpp +++ b/clang/test/SemaTemplate/pack-deduction.cpp @@ -199,3 +199,62 @@ constexpr auto baz(Int(T())>... x) -> int { return 1; } static_assert(baz, Int<2>, Int<3>>(Int<10>(), Int<10>(), Int<10>()) == 1, ""); } + +namespace GH17042 { + +template struct X { + template using Y = X; // #GH17042_Y +}; + +template +using any_pairs_list = X::Y; // #any_pairs_list + +template +using any_pairs_list_2 = X::Y<>; +// expected-error@#GH17042_Y {{different length (2 vs. 0)}} \ +// expected-note@-1 {{requested here}} + +template +using any_pairs_list_3 = X::Y; // #any_pairs_list_3 + +template +using any_pairs_list_4 = X::Y; +// expected-error@#GH17042_Y {{different length (2 vs. at least 3)}} \ +// expected-note@-1 {{requested here}} + +static_assert(__is_same(any_pairs_list, X), ""); + +static_assert(!__is_same(any_pairs_list, X), ""); +// expected-error@#GH17042_Y {{different length (2 vs. 3)}} \ +// expected-note@#any_pairs_list {{requested here}} \ +// expected-note@-1 {{requested here}} + +static_assert(__is_same(any_pairs_list_3, X), ""); + +static_assert(!__is_same(any_pairs_list_3, X), ""); +// expected-error@#GH17042_Y {{different length (2 vs. 3)}} \ +// expected-note@#any_pairs_list_3 {{requested here}} \ +// expected-note@-1 {{requested here}} + +namespace TemplateTemplateParameters { +template struct C {}; + +template class... Args1> struct Ttp { + template